uqm-0.6.2/0000755000175000017500000000000010552603255011022 5ustar joeyjoeyuqm-0.6.2/tools/0000755000175000017500000000000010552603255012162 5ustar joeyjoeyuqm-0.6.2/tools/keys/0000755000175000017500000000000010552603257013137 5ustar joeyjoeyuqm-0.6.2/tools/keys/keyjam.c0000644000175000017500000000636710552603257014577 0ustar joeyjoey#include #include #include #include "SDL.h" #include "SDL_gfxPrimitives.h" #define BUFFERSIZE 1024 static int keystate[SDLK_LAST]; static char held_keys[BUFFERSIZE]; static char videoname[BUFFERSIZE]; void DrawCenteredText (SDL_Surface *s, int y, const char *c) { int w = strlen (c) * 8; stringRGBA(s, (s->w - w) / 2, y, c, 0xc0, 0xc0, 0xc0, 0xff); } void DrawScreen (SDL_Surface *s) { int y; SDL_FillRect (s, NULL, SDL_MapRGB (s->format, 0, 0, 0x80)); DrawCenteredText (s, 8, "Key Jamming"); y = 32; DrawCenteredText (s, y, "Many keyboards have hardware that does not permit them to send"); y += 8; DrawCenteredText (s, y, "arbitrary keychords to the computer. This can complicate games"); y += 8; DrawCenteredText (s, y, "with keyboard control, as activating certain controls may lock out"); y += 8; DrawCenteredText (s, y, "others. This application lets you pre-test control combinations so"); y += 8; DrawCenteredText (s, y, "as to avoid such conflicts."); y += 16; DrawCenteredText (s, y, "Test your keyboard by pressing key combinations. The keyboard's"); y += 8; DrawCenteredText (s, y, "status will be reported in the bottom half of the screen. When"); y += 8; DrawCenteredText (s, y, "configuring keys for a game, do not select keys that do not all"); y += 8; DrawCenteredText (s, y, "register when simultaneously pressed."); y += 16; DrawCenteredText (s, y, "You are using the following SDL driver:"); y += 8; DrawCenteredText (s, y, videoname); y += 16; DrawCenteredText (s, y, "Press ESCAPE to exit."); DrawCenteredText (s, 300, held_keys); SDL_Flip (s); } int main (int argc, char *argv[]) { SDL_Event event; SDL_Surface *screen; int quit = 0; int i, changed; /* Initialise SDL */ if (SDL_Init (SDL_INIT_VIDEO) < 0) { fprintf (stderr, "Could not initialise SDL: %s\n", SDL_GetError()); exit (-1); } /* Set a video mode */ if (!(screen = SDL_SetVideoMode (640, 480, 0, SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_ANYFORMAT))) { fprintf (stderr, "Could not set video mode: %s\n", SDL_GetError()); SDL_Quit (); exit (-1); } SDL_WM_SetCaption ("Key Jammer", "Key Jammer"); SDL_VideoDriverName (videoname, BUFFERSIZE); for (i = 0; i < SDLK_LAST; i++) { keystate[i] = 0; } DrawScreen (screen); /* Loop until an SDL_QUIT event is found */ while( !quit ) { changed = 0; /* Poll for events */ while (SDL_PollEvent (&event)) { switch( event.type ) { case SDL_KEYDOWN: keystate[event.key.keysym.sym] = 1; changed = 1; break; case SDL_KEYUP: keystate[event.key.keysym.sym] = 0; changed = 1; break; case SDL_QUIT: quit = 1; break; default: break; } } if (changed) { held_keys[0] = '\0'; for (i = 0; i < SDLK_LAST; i++) { if (keystate[i]) { if (held_keys[0]) { strcat(held_keys, " | "); } strcat(held_keys, SDL_GetKeyName (i)); } if (strlen (held_keys) > 200) { break; } } for (i = 0; i < BUFFERSIZE; i++) { if (!held_keys[i]) { break; } held_keys[i] = toupper (held_keys[i]); } DrawScreen (screen); } if (keystate[SDLK_ESCAPE]) { quit = 1; } SDL_Delay (20); } /* Clean up */ SDL_Quit (); exit (0); } uqm-0.6.2/tools/keys/Makefile0000644000175000017500000000017610552603257014603 0ustar joeyjoeyall: keyjam.c gcc $(shell sdl-config --cflags) -o keyjam keyjam.c $(shell sdl-config --libs) -lSDL_gfx clean: rm -f keyjam uqm-0.6.2/sc2/0000755000175000017500000000000010556254064011515 5ustar joeyjoeyuqm-0.6.2/sc2/Makefile.build0000600000175000017500000000265410543204460014241 0ustar joeyjoey# Make file for the uqm build system. Invoked from build/unix/build_functions # By Serge van den Boom .DELETE_ON_ERROR: SOURCES := $(shell cat "$(DEPEND_FILE)") -include $(SOURCES:=.d) ifeq ($(MAKE_VERBOSE),1) define act $(call $(1)) endef else define act @echo " $(2) $(3)" @$(call $(1)) endef endif define act_mkdep_c $(MKDEP_C) $(CFLAGS) "$<" -MT "$(@D)/$( XFree86 4.x comes with Mesa, which is a clone. Note: Mesa is a software emulation. For enjoyable results you will need hardware accelerated OpenGL (GLX). These usually conflict with mesa (can result in X server crash). SDL v1.2 The Simple Direct-Media Layer A fairly good multiplatform low level graphics library. Homepage: www.libsdl.org Download: http://www.libsdl.org/download-1.2.php Debian package: libsdl1.2-dev (and various runtime debs) SDL_image An image loading library used with SDL. Homepage: http://www.libsdl.org/projects/SDL_image/ Download: http://www.libsdl.org/projects/SDL_image/release/ Debian packages: libsdl-image1.2 libsdl-image1.2-dev OpenAL (Win32 only) A cross-platform spatialized audio library. Homepage: http://www.openal.org/ SDK download: http://developer.creative.com/articles/article.asp?aid=45&file=OpenAL11CoreSDK.exe libogg and libvorbis Audio codec to play Ogg Vorbis files, used for music and speech. Homepage: http://www.xiph.org/ogg/vorbis/index.html Download: For Windows: SDK download: http://www.vorbis.com/files/1.0.1/windows/OggVorbis-win32sdk-1.0.1.zip For Linux: http://www.vorbis.com/download_unix.psp download libogg and libvorbis. Tremor (alternative for libogg and libvorbis) Audio codec to play Ogg Vorbis files, used for music and speech. This library avoids floating point math and should be used instead of libogg and libvorbis when floating point support is not available or slow (on some handhelds and game consoles). Homepage: http://www.xiph.org/vorbis/ Download: http://svn.xiph.org/trunk/Tremor (Subversion) Libmikmod Audio codec to play .mof files, used for the original PC music. Homepage: http://mikmod.raphnet.net/ Download: http://sourceforge.net/project/showfiles.php?group_id=40531 Zlib v1.2 Data compression / decompression library Homepage: http://www.gzip.org/zlib/ Download: For Windows: http://www.gzip.org/zlib/ (mid-page 'zlib compiled DLL') If you find these aren't enough, or if you know the names of the corresponding RPM etc. packages, please report to or visit http://sourceforge.net/projects/sc2/ uqm-0.6.2/sc2/Makeproject0000600000175000017500000000220110543204460013656 0ustar joeyjoeyTARGETS="uqm" # For the 'uqm' target: if [ "$DEBUG" = "1" ]; then uqm_OBJS=obj/debug/ # Directory for object files uqm_NAME=uqm-debug # File name of executable else uqm_OBJS=obj/release/ # Directory for object files uqm_NAME=uqm # File name of executable fi uqm_CFLAGS="$uqm_CFLAGS -I src -I src/sc2code -I src/sc2code/libs" if [ "$uqm_HAVE_REGEX" = 0 ]; then uqm_CFLAGS="$uqm_CFLAGS -I src/regex" fi # Stuff to install under the directory for libraries, as specified during # config. uqm_INSTALL_LIBS="executable" uqm_INSTALL_LIB_executable_SRC="$BUILD_WORK/$uqm_NAME" uqm_INSTALL_LIB_executable_DEST=uqm/uqm uqm_INSTALL_LIB_executable_MODE="0755" # Stuff to install under the directory for system-independant data, as # specified during config. uqm_INSTALL_SHARED="content" uqm_INSTALL_SHARED_content_SRC=content uqm_INSTALL_SHARED_content_DEST=uqm/ uqm_INSTALL_SHARED_content_MODE="go+rX" # Stuff to install under the directory for binaries, as specified during # config. uqm_INSTALL_BINS=wrapper uqm_INSTALL_BIN_wrapper_SRC="$BUILD_WORK/uqm-wrapper" uqm_INSTALL_BIN_wrapper_DEST="uqm" uqm_INSTALL_BIN_wrapper_MODE="0755" uqm-0.6.2/sc2/src/0000755000175000017500000000000010552600273012275 5ustar joeyjoeyuqm-0.6.2/sc2/src/regex/0000755000175000017500000000000010552600273013407 5ustar joeyjoeyuqm-0.6.2/sc2/src/regex/regex_internal.ci0000600000175000017500000012773510543202107016733 0ustar joeyjoey/* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ static void re_string_construct_common (const char *str, int len, re_string_t *pstr, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) internal_function; #ifdef RE_ENABLE_I18N static int re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc) internal_function; #endif /* RE_ENABLE_I18N */ static reg_errcode_t register_state (re_dfa_t *dfa, re_dfastate_t *newstate, unsigned int hash) internal_function; static re_dfastate_t *create_ci_newstate (re_dfa_t *dfa, const re_node_set *nodes, unsigned int hash) internal_function; static re_dfastate_t *create_cd_newstate (re_dfa_t *dfa, const re_node_set *nodes, unsigned int context, unsigned int hash) internal_function; static unsigned int inline calc_state_hash (const re_node_set *nodes, unsigned int context) internal_function; /* Functions for string operation. */ /* This function allocate the buffers. It is necessary to call re_string_reconstruct before using the object. */ static reg_errcode_t re_string_allocate (pstr, str, len, init_len, trans, icase, dfa) re_string_t *pstr; const char *str; int len, init_len, icase; RE_TRANSLATE_TYPE trans; const re_dfa_t *dfa; { reg_errcode_t ret; int init_buf_len; /* Ensure at least one character fits into the buffers. */ if (init_len < dfa->mb_cur_max) init_len = dfa->mb_cur_max; init_buf_len = (len + 1 < init_len) ? len + 1: init_len; re_string_construct_common (str, len, pstr, trans, icase, dfa); ret = re_string_realloc_buffers (pstr, init_buf_len); if (BE (ret != REG_NOERROR, 0)) return ret; pstr->word_char = dfa->word_char; pstr->word_ops_used = dfa->word_ops_used; pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; pstr->valid_raw_len = pstr->valid_len; return REG_NOERROR; } /* This function allocate the buffers, and initialize them. */ static reg_errcode_t re_string_construct (pstr, str, len, trans, icase, dfa) re_string_t *pstr; const char *str; int len, icase; RE_TRANSLATE_TYPE trans; const re_dfa_t *dfa; { reg_errcode_t ret; memset (pstr, '\0', sizeof (re_string_t)); re_string_construct_common (str, len, pstr, trans, icase, dfa); if (len > 0) { ret = re_string_realloc_buffers (pstr, len + 1); if (BE (ret != REG_NOERROR, 0)) return ret; } pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; if (icase) { #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { while (1) { ret = build_wcs_upper_buffer (pstr); if (BE (ret != REG_NOERROR, 0)) return ret; if (pstr->valid_raw_len >= len) break; if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) break; ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); if (BE (ret != REG_NOERROR, 0)) return ret; } } else #endif /* RE_ENABLE_I18N */ build_upper_buffer (pstr); } else { #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) build_wcs_buffer (pstr); else #endif /* RE_ENABLE_I18N */ { if (trans != NULL) re_string_translate_buffer (pstr); else { pstr->valid_len = pstr->bufs_len; pstr->valid_raw_len = pstr->bufs_len; } } } return REG_NOERROR; } /* Helper functions for re_string_allocate, and re_string_construct. */ static reg_errcode_t re_string_realloc_buffers (pstr, new_buf_len) re_string_t *pstr; int new_buf_len; { #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { wint_t *new_array = re_realloc (pstr->wcs, wint_t, new_buf_len); if (BE (new_array == NULL, 0)) return REG_ESPACE; pstr->wcs = new_array; if (pstr->offsets != NULL) { int *new_array = re_realloc (pstr->offsets, int, new_buf_len); if (BE (new_array == NULL, 0)) return REG_ESPACE; pstr->offsets = new_array; } } #endif /* RE_ENABLE_I18N */ if (pstr->mbs_allocated) { unsigned char *new_array = re_realloc (pstr->mbs, unsigned char, new_buf_len); if (BE (new_array == NULL, 0)) return REG_ESPACE; pstr->mbs = new_array; } pstr->bufs_len = new_buf_len; return REG_NOERROR; } static void re_string_construct_common (str, len, pstr, trans, icase, dfa) const char *str; int len; re_string_t *pstr; RE_TRANSLATE_TYPE trans; int icase; const re_dfa_t *dfa; { pstr->raw_mbs = (const unsigned char *) str; pstr->len = len; pstr->raw_len = len; pstr->trans = (unsigned RE_TRANSLATE_TYPE) trans; pstr->icase = icase ? 1 : 0; pstr->mbs_allocated = (trans != NULL || icase); pstr->mb_cur_max = dfa->mb_cur_max; pstr->is_utf8 = dfa->is_utf8; pstr->map_notascii = dfa->map_notascii; pstr->stop = pstr->len; pstr->raw_stop = pstr->stop; } #ifdef RE_ENABLE_I18N /* Build wide character buffer PSTR->WCS. If the byte sequence of the string are: (0), (1), (0), (1), Then wide character buffer will be: , WEOF , , WEOF , We use WEOF for padding, they indicate that the position isn't a first byte of a multibyte character. Note that this function assumes PSTR->VALID_LEN elements are already built and starts from PSTR->VALID_LEN. */ static void build_wcs_buffer (pstr) re_string_t *pstr; { #ifdef _LIBC unsigned char buf[pstr->mb_cur_max]; #else unsigned char buf[64]; #endif mbstate_t prev_st; int byte_idx, end_idx, mbclen, remain_len; /* Build the buffers from pstr->valid_len to either pstr->len or pstr->bufs_len. */ end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; for (byte_idx = pstr->valid_len; byte_idx < end_idx;) { wchar_t wc; const char *p; remain_len = end_idx - byte_idx; prev_st = pstr->cur_state; /* Apply the translation if we need. */ if (BE (pstr->trans != NULL, 0)) { int i, ch; for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) { ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; } p = (const char *) buf; } else p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); if (BE (mbclen == (size_t) -2, 0)) { /* The buffer doesn't have enough space, finish to build. */ pstr->cur_state = prev_st; break; } else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) { /* We treat these cases as a singlebyte character. */ mbclen = 1; wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; if (BE (pstr->trans != NULL, 0)) wc = pstr->trans[wc]; pstr->cur_state = prev_st; } /* Write wide character and padding. */ pstr->wcs[byte_idx++] = wc; /* Write paddings. */ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } pstr->valid_len = byte_idx; pstr->valid_raw_len = byte_idx; } /* Build wide character buffer PSTR->WCS like build_wcs_buffer, but for REG_ICASE. */ static int build_wcs_upper_buffer (pstr) re_string_t *pstr; { mbstate_t prev_st; int src_idx, byte_idx, end_idx, mbclen, remain_len; #ifdef _LIBC unsigned char buf[pstr->mb_cur_max]; #else unsigned char buf[64]; #endif byte_idx = pstr->valid_len; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; /* The following optimization assumes that ASCII characters can be mapped to wide characters with a simple cast. */ if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) { while (byte_idx < end_idx) { wchar_t wc; if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]) && mbsinit (&pstr->cur_state)) { /* In case of a singlebyte character. */ pstr->mbs[byte_idx] = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); /* The next step uses the assumption that wchar_t is encoded ASCII-safe: all ASCII values can be converted like this. */ pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; ++byte_idx; continue; } remain_len = end_idx - byte_idx; prev_st = pstr->cur_state; mbclen = mbrtowc (&wc, ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx), remain_len, &pstr->cur_state); if (BE (mbclen > 0, 1)) { wchar_t wcu = wc; if (iswlower (wc)) { int mbcdlen; wcu = towupper (wc); mbcdlen = wcrtomb (buf, wcu, &prev_st); if (BE (mbclen == mbcdlen, 1)) memcpy (pstr->mbs + byte_idx, buf, mbclen); else { src_idx = byte_idx; goto offsets_needed; } } else memcpy (pstr->mbs + byte_idx, pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); pstr->wcs[byte_idx++] = wcu; /* Write paddings. */ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } else if (mbclen == (size_t) -1 || mbclen == 0) { /* It is an invalid character or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; pstr->mbs[byte_idx] = ch; /* And also cast it to wide char. */ pstr->wcs[byte_idx++] = (wchar_t) ch; if (BE (mbclen == (size_t) -1, 0)) pstr->cur_state = prev_st; } else { /* The buffer doesn't have enough space, finish to build. */ pstr->cur_state = prev_st; break; } } pstr->valid_len = byte_idx; pstr->valid_raw_len = byte_idx; return REG_NOERROR; } else for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) { wchar_t wc; const char *p; offsets_needed: remain_len = end_idx - byte_idx; prev_st = pstr->cur_state; if (BE (pstr->trans != NULL, 0)) { int i, ch; for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) { ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; buf[i] = pstr->trans[ch]; } p = (const char *) buf; } else p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); if (BE (mbclen > 0, 1)) { wchar_t wcu = wc; if (iswlower (wc)) { int mbcdlen; wcu = towupper (wc); mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st); if (BE (mbclen == mbcdlen, 1)) memcpy (pstr->mbs + byte_idx, buf, mbclen); else { int i; if (byte_idx + mbcdlen > pstr->bufs_len) { pstr->cur_state = prev_st; break; } if (pstr->offsets == NULL) { pstr->offsets = re_malloc (int, pstr->bufs_len); if (pstr->offsets == NULL) return REG_ESPACE; } if (!pstr->offsets_needed) { for (i = 0; i < byte_idx; ++i) pstr->offsets[i] = i; pstr->offsets_needed = 1; } memcpy (pstr->mbs + byte_idx, buf, mbcdlen); pstr->wcs[byte_idx] = wcu; pstr->offsets[byte_idx] = src_idx; for (i = 1; i < mbcdlen; ++i) { pstr->offsets[byte_idx + i] = src_idx + (i < mbclen ? i : mbclen - 1); pstr->wcs[byte_idx + i] = WEOF; } pstr->len += mbcdlen - mbclen; if (pstr->raw_stop > src_idx) pstr->stop += mbcdlen - mbclen; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; byte_idx += mbcdlen; src_idx += mbclen; continue; } } else memcpy (pstr->mbs + byte_idx, p, mbclen); if (BE (pstr->offsets_needed != 0, 0)) { int i; for (i = 0; i < mbclen; ++i) pstr->offsets[byte_idx + i] = src_idx + i; } src_idx += mbclen; pstr->wcs[byte_idx++] = wcu; /* Write paddings. */ for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } else if (mbclen == (size_t) -1 || mbclen == 0) { /* It is an invalid character or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; if (BE (pstr->trans != NULL, 0)) ch = pstr->trans [ch]; pstr->mbs[byte_idx] = ch; if (BE (pstr->offsets_needed != 0, 0)) pstr->offsets[byte_idx] = src_idx; ++src_idx; /* And also cast it to wide char. */ pstr->wcs[byte_idx++] = (wchar_t) ch; if (BE (mbclen == (size_t) -1, 0)) pstr->cur_state = prev_st; } else { /* The buffer doesn't have enough space, finish to build. */ pstr->cur_state = prev_st; break; } } pstr->valid_len = byte_idx; pstr->valid_raw_len = src_idx; return REG_NOERROR; } /* Skip characters until the index becomes greater than NEW_RAW_IDX. Return the index. */ static int re_string_skip_chars (pstr, new_raw_idx, last_wc) re_string_t *pstr; int new_raw_idx; wint_t *last_wc; { mbstate_t prev_st; int rawbuf_idx, mbclen; wchar_t wc = 0; /* Skip the characters which are not necessary to check. */ for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; rawbuf_idx < new_raw_idx;) { int remain_len; remain_len = pstr->len - rawbuf_idx; prev_st = pstr->cur_state; mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx, remain_len, &pstr->cur_state); if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0)) { /* We treat these cases as a singlebyte character. */ mbclen = 1; pstr->cur_state = prev_st; } /* Then proceed the next character. */ rawbuf_idx += mbclen; } *last_wc = (wint_t) wc; return rawbuf_idx; } #endif /* RE_ENABLE_I18N */ /* Build the buffer PSTR->MBS, and apply the translation if we need. This function is used in case of REG_ICASE. */ static void build_upper_buffer (pstr) re_string_t *pstr; { int char_idx, end_idx; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) { int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; if (BE (pstr->trans != NULL, 0)) ch = pstr->trans[ch]; if (islower (ch)) pstr->mbs[char_idx] = toupper (ch); else pstr->mbs[char_idx] = ch; } pstr->valid_len = char_idx; pstr->valid_raw_len = char_idx; } /* Apply TRANS to the buffer in PSTR. */ static void re_string_translate_buffer (pstr) re_string_t *pstr; { int buf_idx, end_idx; end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) { int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; pstr->mbs[buf_idx] = pstr->trans[ch]; } pstr->valid_len = buf_idx; pstr->valid_raw_len = buf_idx; } /* This function re-construct the buffers. Concretely, convert to wide character in case of pstr->mb_cur_max > 1, convert to upper case in case of REG_ICASE, apply translation. */ static reg_errcode_t re_string_reconstruct (pstr, idx, eflags) re_string_t *pstr; int idx, eflags; { int offset = idx - pstr->raw_mbs_idx; if (BE (offset < 0, 0)) { /* Reset buffer. */ #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); #endif /* RE_ENABLE_I18N */ pstr->len = pstr->raw_len; pstr->stop = pstr->raw_stop; pstr->valid_len = 0; pstr->raw_mbs_idx = 0; pstr->valid_raw_len = 0; pstr->offsets_needed = 0; pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF : CONTEXT_NEWLINE | CONTEXT_BEGBUF); if (!pstr->mbs_allocated) pstr->mbs = (unsigned char *) pstr->raw_mbs; offset = idx; } if (BE (offset != 0, 1)) { /* Are the characters which are already checked remain? */ if (BE (offset < pstr->valid_raw_len, 1) #ifdef RE_ENABLE_I18N /* Handling this would enlarge the code too much. Accept a slowdown in that case. */ && pstr->offsets_needed == 0 #endif ) { /* Yes, move them to the front of the buffer. */ pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags); #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) memmove (pstr->wcs, pstr->wcs + offset, (pstr->valid_len - offset) * sizeof (wint_t)); #endif /* RE_ENABLE_I18N */ if (BE (pstr->mbs_allocated, 0)) memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); pstr->valid_len -= offset; pstr->valid_raw_len -= offset; #if DEBUG assert (pstr->valid_len > 0); #endif } else { /* No, skip all characters until IDX. */ #ifdef RE_ENABLE_I18N if (BE (pstr->offsets_needed, 0)) { pstr->len = pstr->raw_len - idx + offset; pstr->stop = pstr->raw_stop - idx + offset; pstr->offsets_needed = 0; } #endif pstr->valid_len = 0; pstr->valid_raw_len = 0; #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { int wcs_idx; wint_t wc = WEOF; if (pstr->is_utf8) { const unsigned char *raw, *p, *q, *end; /* Special case UTF-8. Multi-byte chars start with any byte other than 0x80 - 0xbf. */ raw = pstr->raw_mbs + pstr->raw_mbs_idx; end = raw + (offset - pstr->mb_cur_max); for (p = raw + offset - 1; p >= end; --p) if ((*p & 0xc0) != 0x80) { mbstate_t cur_state; wchar_t wc2; int mlen = raw + pstr->len - p; unsigned char buf[6]; q = p; if (BE (pstr->trans != NULL, 0)) { int i = mlen < 6 ? mlen : 6; while (--i >= 0) buf[i] = pstr->trans[p[i]]; q = buf; } /* XXX Don't use mbrtowc, we know which conversion to use (UTF-8 -> UCS4). */ memset (&cur_state, 0, sizeof (cur_state)); mlen = mbrtowc (&wc2, p, mlen, &cur_state) - (raw + offset - p); if (mlen >= 0) { memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); pstr->valid_len = mlen; wc = wc2; } break; } } if (wc == WEOF) pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; if (BE (pstr->valid_len, 0)) { for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) pstr->wcs[wcs_idx] = WEOF; if (pstr->mbs_allocated) memset (pstr->mbs, 255, pstr->valid_len); } pstr->valid_raw_len = pstr->valid_len; pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) ? CONTEXT_WORD : ((IS_WIDE_NEWLINE (wc) && pstr->newline_anchor) ? CONTEXT_NEWLINE : 0)); } else #endif /* RE_ENABLE_I18N */ { int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; if (pstr->trans) c = pstr->trans[c]; pstr->tip_context = (bitset_contain (pstr->word_char, c) ? CONTEXT_WORD : ((IS_NEWLINE (c) && pstr->newline_anchor) ? CONTEXT_NEWLINE : 0)); } } if (!BE (pstr->mbs_allocated, 0)) pstr->mbs += offset; } pstr->raw_mbs_idx = idx; pstr->len -= offset; pstr->stop -= offset; /* Then build the buffers. */ #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { if (pstr->icase) { int ret = build_wcs_upper_buffer (pstr); if (BE (ret != REG_NOERROR, 0)) return ret; } else build_wcs_buffer (pstr); } else #endif /* RE_ENABLE_I18N */ if (BE (pstr->mbs_allocated, 0)) { if (pstr->icase) build_upper_buffer (pstr); else if (pstr->trans != NULL) re_string_translate_buffer (pstr); } else pstr->valid_len = pstr->len; pstr->cur_idx = 0; return REG_NOERROR; } static unsigned char re_string_peek_byte_case (pstr, idx) const re_string_t *pstr; int idx; { int ch, off; /* Handle the common (easiest) cases first. */ if (BE (!pstr->mbs_allocated, 1)) return re_string_peek_byte (pstr, idx); #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1 && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) return re_string_peek_byte (pstr, idx); #endif off = pstr->cur_idx + idx; #ifdef RE_ENABLE_I18N if (pstr->offsets_needed) off = pstr->offsets[off]; #endif ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; #ifdef RE_ENABLE_I18N /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I this function returns CAPITAL LETTER I instead of first byte of DOTLESS SMALL LETTER I. The latter would confuse the parser, since peek_byte_case doesn't advance cur_idx in any way. */ if (pstr->offsets_needed && !isascii (ch)) return re_string_peek_byte (pstr, idx); #endif return ch; } static unsigned char re_string_fetch_byte_case (pstr) re_string_t *pstr; { if (BE (!pstr->mbs_allocated, 1)) return re_string_fetch_byte (pstr); #ifdef RE_ENABLE_I18N if (pstr->offsets_needed) { int off, ch; /* For tr_TR.UTF-8 [[:islower:]] there is [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip in that case the whole multi-byte character and return the original letter. On the other side, with [[: DOTLESS SMALL LETTER I return [[:I, as doing anything else would complicate things too much. */ if (!re_string_first_byte (pstr, pstr->cur_idx)) return re_string_fetch_byte (pstr); off = pstr->offsets[pstr->cur_idx]; ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; if (! isascii (ch)) return re_string_fetch_byte (pstr); re_string_skip_bytes (pstr, re_string_char_size_at (pstr, pstr->cur_idx)); return ch; } #endif return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; } static void re_string_destruct (pstr) re_string_t *pstr; { #ifdef RE_ENABLE_I18N re_free (pstr->wcs); re_free (pstr->offsets); #endif /* RE_ENABLE_I18N */ if (pstr->mbs_allocated) re_free (pstr->mbs); } /* Return the context at IDX in INPUT. */ static unsigned int re_string_context_at (input, idx, eflags) const re_string_t *input; int idx, eflags; { int c; if (BE (idx < 0, 0)) /* In this case, we use the value stored in input->tip_context, since we can't know the character in input->mbs[-1] here. */ return input->tip_context; if (BE (idx == input->len, 0)) return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF : CONTEXT_NEWLINE | CONTEXT_ENDBUF); #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc; int wc_idx = idx; while(input->wcs[wc_idx] == WEOF) { #ifdef DEBUG /* It must not happen. */ assert (wc_idx >= 0); #endif --wc_idx; if (wc_idx < 0) return input->tip_context; } wc = input->wcs[wc_idx]; if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) return CONTEXT_WORD; return (IS_WIDE_NEWLINE (wc) && input->newline_anchor ? CONTEXT_NEWLINE : 0); } else #endif { c = re_string_byte_at (input, idx); if (bitset_contain (input->word_char, c)) return CONTEXT_WORD; return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; } } /* Functions for set operation. */ static reg_errcode_t re_node_set_alloc (set, size) re_node_set *set; int size; { set->alloc = size; set->nelem = 0; set->elems = re_malloc (int, size); if (BE (set->elems == NULL, 0)) return REG_ESPACE; return REG_NOERROR; } static reg_errcode_t re_node_set_init_1 (set, elem) re_node_set *set; int elem; { set->alloc = 1; set->nelem = 1; set->elems = re_malloc (int, 1); if (BE (set->elems == NULL, 0)) { set->alloc = set->nelem = 0; return REG_ESPACE; } set->elems[0] = elem; return REG_NOERROR; } static reg_errcode_t re_node_set_init_2 (set, elem1, elem2) re_node_set *set; int elem1, elem2; { set->alloc = 2; set->elems = re_malloc (int, 2); if (BE (set->elems == NULL, 0)) return REG_ESPACE; if (elem1 == elem2) { set->nelem = 1; set->elems[0] = elem1; } else { set->nelem = 2; if (elem1 < elem2) { set->elems[0] = elem1; set->elems[1] = elem2; } else { set->elems[0] = elem2; set->elems[1] = elem1; } } return REG_NOERROR; } static reg_errcode_t re_node_set_init_copy (dest, src) re_node_set *dest; const re_node_set *src; { dest->nelem = src->nelem; if (src->nelem > 0) { dest->alloc = dest->nelem; dest->elems = re_malloc (int, dest->alloc); if (BE (dest->elems == NULL, 0)) { dest->alloc = dest->nelem = 0; return REG_ESPACE; } memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); } else re_node_set_init_empty (dest); return REG_NOERROR; } /* Calculate the intersection of the sets SRC1 and SRC2. And merge it to DEST. Return value indicate the error code or REG_NOERROR if succeeded. Note: We assume dest->elems is NULL, when dest->alloc is 0. */ static reg_errcode_t re_node_set_add_intersect (dest, src1, src2) re_node_set *dest; const re_node_set *src1, *src2; { int i1, i2, is, id, delta, sbase; if (src1->nelem == 0 || src2->nelem == 0) return REG_NOERROR; /* We need dest->nelem + 2 * elems_in_intersection; this is a conservative estimate. */ if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) { int new_alloc = src1->nelem + src2->nelem + dest->alloc; int *new_elems = re_realloc (dest->elems, int, new_alloc); if (BE (new_elems == NULL, 0)) return REG_ESPACE; dest->elems = new_elems; dest->alloc = new_alloc; } /* Find the items in the intersection of SRC1 and SRC2, and copy into the top of DEST those that are not already in DEST itself. */ sbase = dest->nelem + src1->nelem + src2->nelem; i1 = src1->nelem - 1; i2 = src2->nelem - 1; id = dest->nelem - 1; for (;;) { if (src1->elems[i1] == src2->elems[i2]) { /* Try to find the item in DEST. Maybe we could binary search? */ while (id >= 0 && dest->elems[id] > src1->elems[i1]) --id; if (id < 0 || dest->elems[id] != src1->elems[i1]) dest->elems[--sbase] = src1->elems[i1]; if (--i1 < 0 || --i2 < 0) break; } /* Lower the highest of the two items. */ else if (src1->elems[i1] < src2->elems[i2]) { if (--i2 < 0) break; } else { if (--i1 < 0) break; } } id = dest->nelem - 1; is = dest->nelem + src1->nelem + src2->nelem - 1; delta = is - sbase + 1; /* Now copy. When DELTA becomes zero, the remaining DEST elements are already in place; this is more or less the same loop that is in re_node_set_merge. */ dest->nelem += delta; if (delta > 0 && id >= 0) for (;;) { if (dest->elems[is] > dest->elems[id]) { /* Copy from the top. */ dest->elems[id + delta--] = dest->elems[is--]; if (delta == 0) break; } else { /* Slide from the bottom. */ dest->elems[id + delta] = dest->elems[id]; if (--id < 0) break; } } /* Copy remaining SRC elements. */ memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int)); return REG_NOERROR; } /* Calculate the union set of the sets SRC1 and SRC2. And store it to DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ static reg_errcode_t re_node_set_init_union (dest, src1, src2) re_node_set *dest; const re_node_set *src1, *src2; { int i1, i2, id; if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) { dest->alloc = src1->nelem + src2->nelem; dest->elems = re_malloc (int, dest->alloc); if (BE (dest->elems == NULL, 0)) return REG_ESPACE; } else { if (src1 != NULL && src1->nelem > 0) return re_node_set_init_copy (dest, src1); else if (src2 != NULL && src2->nelem > 0) return re_node_set_init_copy (dest, src2); else re_node_set_init_empty (dest); return REG_NOERROR; } for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) { if (src1->elems[i1] > src2->elems[i2]) { dest->elems[id++] = src2->elems[i2++]; continue; } if (src1->elems[i1] == src2->elems[i2]) ++i2; dest->elems[id++] = src1->elems[i1++]; } if (i1 < src1->nelem) { memcpy (dest->elems + id, src1->elems + i1, (src1->nelem - i1) * sizeof (int)); id += src1->nelem - i1; } else if (i2 < src2->nelem) { memcpy (dest->elems + id, src2->elems + i2, (src2->nelem - i2) * sizeof (int)); id += src2->nelem - i2; } dest->nelem = id; return REG_NOERROR; } /* Calculate the union set of the sets DEST and SRC. And store it to DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ static reg_errcode_t re_node_set_merge (dest, src) re_node_set *dest; const re_node_set *src; { int is, id, sbase, delta; if (src == NULL || src->nelem == 0) return REG_NOERROR; if (dest->alloc < 2 * src->nelem + dest->nelem) { int new_alloc = 2 * (src->nelem + dest->alloc); int *new_buffer = re_realloc (dest->elems, int, new_alloc); if (BE (new_buffer == NULL, 0)) return REG_ESPACE; dest->elems = new_buffer; dest->alloc = new_alloc; } if (BE (dest->nelem == 0, 0)) { dest->nelem = src->nelem; memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); return REG_NOERROR; } /* Copy into the top of DEST the items of SRC that are not found in DEST. Maybe we could binary search in DEST? */ for (sbase = dest->nelem + 2 * src->nelem, is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; ) { if (dest->elems[id] == src->elems[is]) is--, id--; else if (dest->elems[id] < src->elems[is]) dest->elems[--sbase] = src->elems[is--]; else /* if (dest->elems[id] > src->elems[is]) */ --id; } if (is >= 0) { /* If DEST is exhausted, the remaining items of SRC must be unique. */ sbase -= is + 1; memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int)); } id = dest->nelem - 1; is = dest->nelem + 2 * src->nelem - 1; delta = is - sbase + 1; if (delta == 0) return REG_NOERROR; /* Now copy. When DELTA becomes zero, the remaining DEST elements are already in place. */ dest->nelem += delta; for (;;) { if (dest->elems[is] > dest->elems[id]) { /* Copy from the top. */ dest->elems[id + delta--] = dest->elems[is--]; if (delta == 0) break; } else { /* Slide from the bottom. */ dest->elems[id + delta] = dest->elems[id]; if (--id < 0) { /* Copy remaining SRC elements. */ memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int)); break; } } } return REG_NOERROR; } /* Insert the new element ELEM to the re_node_set* SET. SET should not already have ELEM. return -1 if an error is occured, return 1 otherwise. */ static int re_node_set_insert (set, elem) re_node_set *set; int elem; { int idx; /* In case the set is empty. */ if (set->alloc == 0) { if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1)) return 1; else return -1; } if (BE (set->nelem, 0) == 0) { /* We already guaranteed above that set->alloc != 0. */ set->elems[0] = elem; ++set->nelem; return 1; } /* Realloc if we need. */ if (set->alloc == set->nelem) { int *new_array; set->alloc = set->alloc * 2; new_array = re_realloc (set->elems, int, set->alloc); if (BE (new_array == NULL, 0)) return -1; set->elems = new_array; } /* Move the elements which follows the new element. Test the first element separately to skip a check in the inner loop. */ if (elem < set->elems[0]) { idx = 0; for (idx = set->nelem; idx > 0; idx--) set->elems[idx] = set->elems[idx - 1]; } else { for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) set->elems[idx] = set->elems[idx - 1]; } /* Insert the new element. */ set->elems[idx] = elem; ++set->nelem; return 1; } /* Insert the new element ELEM to the re_node_set* SET. SET should not already have any element greater than or equal to ELEM. Return -1 if an error is occured, return 1 otherwise. */ static int re_node_set_insert_last (set, elem) re_node_set *set; int elem; { /* Realloc if we need. */ if (set->alloc == set->nelem) { int *new_array; set->alloc = (set->alloc + 1) * 2; new_array = re_realloc (set->elems, int, set->alloc); if (BE (new_array == NULL, 0)) return -1; set->elems = new_array; } /* Insert the new element. */ set->elems[set->nelem++] = elem; return 1; } /* Compare two node sets SET1 and SET2. return 1 if SET1 and SET2 are equivalent, return 0 otherwise. */ static int re_node_set_compare (set1, set2) const re_node_set *set1, *set2; { int i; if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) return 0; for (i = set1->nelem ; --i >= 0 ; ) if (set1->elems[i] != set2->elems[i]) return 0; return 1; } /* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ static int re_node_set_contains (set, elem) const re_node_set *set; int elem; { unsigned int idx, right, mid; if (set->nelem <= 0) return 0; /* Binary search the element. */ idx = 0; right = set->nelem - 1; while (idx < right) { mid = (idx + right) / 2; if (set->elems[mid] < elem) idx = mid + 1; else right = mid; } return set->elems[idx] == elem ? idx + 1 : 0; } static void re_node_set_remove_at (set, idx) re_node_set *set; int idx; { if (idx < 0 || idx >= set->nelem) return; --set->nelem; for (; idx < set->nelem; idx++) set->elems[idx] = set->elems[idx + 1]; } /* Add the token TOKEN to dfa->nodes, and return the index of the token. Or return -1, if an error will be occured. */ static int re_dfa_add_node (dfa, token, mode) re_dfa_t *dfa; re_token_t token; int mode; { if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) { int new_nodes_alloc = dfa->nodes_alloc * 2; re_token_t *new_array = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); if (BE (new_array == NULL, 0)) return -1; dfa->nodes = new_array; if (mode) { int *new_nexts, *new_indices; re_node_set *new_edests, *new_eclosures, *new_inveclosures; new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc); new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc); new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); new_inveclosures = re_realloc (dfa->inveclosures, re_node_set, new_nodes_alloc); if (BE (new_nexts == NULL || new_indices == NULL || new_edests == NULL || new_eclosures == NULL || new_inveclosures == NULL, 0)) return -1; dfa->nexts = new_nexts; dfa->org_indices = new_indices; dfa->edests = new_edests; dfa->eclosures = new_eclosures; dfa->inveclosures = new_inveclosures; } dfa->nodes_alloc = new_nodes_alloc; } dfa->nodes[dfa->nodes_len] = token; dfa->nodes[dfa->nodes_len].opt_subexp = 0; dfa->nodes[dfa->nodes_len].duplicated = 0; dfa->nodes[dfa->nodes_len].constraint = 0; return dfa->nodes_len++; } static unsigned int inline calc_state_hash (nodes, context) const re_node_set *nodes; unsigned int context; { unsigned int hash = nodes->nelem + context; int i; for (i = 0 ; i < nodes->nelem ; i++) hash += nodes->elems[i]; return hash; } /* Search for the state whose node_set is equivalent to NODES. Return the pointer to the state, if we found it in the DFA. Otherwise create the new one and return it. In case of an error return NULL and set the error code in ERR. Note: - We assume NULL as the invalid state, then it is possible that return value is NULL and ERR is REG_NOERROR. - We never return non-NULL value in case of any errors, it is for optimization. */ static re_dfastate_t* re_acquire_state (err, dfa, nodes) reg_errcode_t *err; re_dfa_t *dfa; const re_node_set *nodes; { unsigned int hash; re_dfastate_t *new_state; struct re_state_table_entry *spot; int i; if (BE (nodes->nelem == 0, 0)) { *err = REG_NOERROR; return NULL; } hash = calc_state_hash (nodes, 0); spot = dfa->state_table + (hash & dfa->state_hash_mask); for (i = 0 ; i < spot->num ; i++) { re_dfastate_t *state = spot->array[i]; if (hash != state->hash) continue; if (re_node_set_compare (&state->nodes, nodes)) return state; } /* There are no appropriate state in the dfa, create the new one. */ new_state = create_ci_newstate (dfa, nodes, hash); if (BE (new_state != NULL, 1)) return new_state; else { *err = REG_ESPACE; return NULL; } } /* Search for the state whose node_set is equivalent to NODES and whose context is equivalent to CONTEXT. Return the pointer to the state, if we found it in the DFA. Otherwise create the new one and return it. In case of an error return NULL and set the error code in ERR. Note: - We assume NULL as the invalid state, then it is possible that return value is NULL and ERR is REG_NOERROR. - We never return non-NULL value in case of any errors, it is for optimization. */ static re_dfastate_t* re_acquire_state_context (err, dfa, nodes, context) reg_errcode_t *err; re_dfa_t *dfa; const re_node_set *nodes; unsigned int context; { unsigned int hash; re_dfastate_t *new_state; struct re_state_table_entry *spot; int i; if (nodes->nelem == 0) { *err = REG_NOERROR; return NULL; } hash = calc_state_hash (nodes, context); spot = dfa->state_table + (hash & dfa->state_hash_mask); for (i = 0 ; i < spot->num ; i++) { re_dfastate_t *state = spot->array[i]; if (state->hash == hash && state->context == context && re_node_set_compare (state->entrance_nodes, nodes)) return state; } /* There are no appropriate state in `dfa', create the new one. */ new_state = create_cd_newstate (dfa, nodes, context, hash); if (BE (new_state != NULL, 1)) return new_state; else { *err = REG_ESPACE; return NULL; } } /* Finish initialization of the new state NEWSTATE, and using its hash value HASH put in the appropriate bucket of DFA's state table. Return value indicates the error code if failed. */ static reg_errcode_t register_state (dfa, newstate, hash) re_dfa_t *dfa; re_dfastate_t *newstate; unsigned int hash; { struct re_state_table_entry *spot; reg_errcode_t err; int i; newstate->hash = hash; err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); if (BE (err != REG_NOERROR, 0)) return REG_ESPACE; for (i = 0; i < newstate->nodes.nelem; i++) { int elem = newstate->nodes.elems[i]; if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) re_node_set_insert_last (&newstate->non_eps_nodes, elem); } spot = dfa->state_table + (hash & dfa->state_hash_mask); if (BE (spot->alloc <= spot->num, 0)) { int new_alloc = 2 * spot->num + 2; re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, new_alloc); if (BE (new_array == NULL, 0)) return REG_ESPACE; spot->array = new_array; spot->alloc = new_alloc; } spot->array[spot->num++] = newstate; return REG_NOERROR; } /* Create the new state which is independ of contexts. Return the new state if succeeded, otherwise return NULL. */ static re_dfastate_t * create_ci_newstate (dfa, nodes, hash) re_dfa_t *dfa; const re_node_set *nodes; unsigned int hash; { int i; reg_errcode_t err; re_dfastate_t *newstate; newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); if (BE (newstate == NULL, 0)) return NULL; err = re_node_set_init_copy (&newstate->nodes, nodes); if (BE (err != REG_NOERROR, 0)) { re_free (newstate); return NULL; } newstate->entrance_nodes = &newstate->nodes; for (i = 0 ; i < nodes->nelem ; i++) { re_token_t *node = dfa->nodes + nodes->elems[i]; re_token_type_t type = node->type; if (type == CHARACTER && !node->constraint) continue; /* If the state has the halt node, the state is a halt state. */ else if (type == END_OF_RE) newstate->halt = 1; #ifdef RE_ENABLE_I18N else if (type == COMPLEX_BRACKET || type == OP_UTF8_PERIOD || (type == OP_PERIOD && dfa->mb_cur_max > 1)) newstate->accept_mb = 1; #endif /* RE_ENABLE_I18N */ else if (type == OP_BACK_REF) newstate->has_backref = 1; else if (type == ANCHOR || node->constraint) newstate->has_constraint = 1; } err = register_state (dfa, newstate, hash); if (BE (err != REG_NOERROR, 0)) { free_state (newstate); newstate = NULL; } return newstate; } /* Create the new state which is depend on the context CONTEXT. Return the new state if succeeded, otherwise return NULL. */ static re_dfastate_t * create_cd_newstate (dfa, nodes, context, hash) re_dfa_t *dfa; const re_node_set *nodes; unsigned int context, hash; { int i, nctx_nodes = 0; reg_errcode_t err; re_dfastate_t *newstate; newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); if (BE (newstate == NULL, 0)) return NULL; err = re_node_set_init_copy (&newstate->nodes, nodes); if (BE (err != REG_NOERROR, 0)) { re_free (newstate); return NULL; } newstate->context = context; newstate->entrance_nodes = &newstate->nodes; for (i = 0 ; i < nodes->nelem ; i++) { unsigned int constraint = 0; re_token_t *node = dfa->nodes + nodes->elems[i]; re_token_type_t type = node->type; if (node->constraint) constraint = node->constraint; if (type == CHARACTER && !constraint) continue; /* If the state has the halt node, the state is a halt state. */ else if (type == END_OF_RE) newstate->halt = 1; #ifdef RE_ENABLE_I18N else if (type == COMPLEX_BRACKET || type == OP_UTF8_PERIOD || (type == OP_PERIOD && dfa->mb_cur_max > 1)) newstate->accept_mb = 1; #endif /* RE_ENABLE_I18N */ else if (type == OP_BACK_REF) newstate->has_backref = 1; else if (type == ANCHOR) constraint = node->opr.ctx_type; if (constraint) { if (newstate->entrance_nodes == &newstate->nodes) { newstate->entrance_nodes = re_malloc (re_node_set, 1); if (BE (newstate->entrance_nodes == NULL, 0)) { free_state (newstate); return NULL; } re_node_set_init_copy (newstate->entrance_nodes, nodes); nctx_nodes = 0; newstate->has_constraint = 1; } if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) { re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); ++nctx_nodes; } } } err = register_state (dfa, newstate, hash); if (BE (err != REG_NOERROR, 0)) { free_state (newstate); newstate = NULL; } return newstate; } static void free_state (state) re_dfastate_t *state; { re_node_set_free (&state->non_eps_nodes); re_node_set_free (&state->inveclosure); if (state->entrance_nodes != &state->nodes) { re_node_set_free (state->entrance_nodes); re_free (state->entrance_nodes); } re_node_set_free (&state->nodes); re_free (state->trtable); re_free (state); } uqm-0.6.2/sc2/src/regex/regexec.ci0000600000175000017500000037325310543202107015345 0ustar joeyjoey/* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, int n) internal_function; static void match_ctx_clean (re_match_context_t *mctx) internal_function; static void match_ctx_free (re_match_context_t *cache) internal_function; static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node, int str_idx, int from, int to) internal_function; static int search_cur_bkref_entry (re_match_context_t *mctx, int str_idx) internal_function; static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx) internal_function; static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx) internal_function; static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, re_dfastate_t **limited_sts, int last_node, int last_str_idx) internal_function; static reg_errcode_t re_search_internal (const regex_t *preg, const char *string, int length, int start, int range, int stop, size_t nmatch, regmatch_t pmatch[], int eflags) internal_function; static int re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1, int length1, const char *string2, int length2, int start, int range, struct re_registers *regs, int stop, int ret_len) internal_function; static int re_search_stub (struct re_pattern_buffer *bufp, const char *string, int length, int start, int range, int stop, struct re_registers *regs, int ret_len) internal_function; static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, int nregs, int regs_allocated) internal_function; static inline re_dfastate_t *acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, int idx) __attribute ((always_inline)) internal_function; static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) internal_function; static int check_matching (re_match_context_t *mctx, int fl_longest_match, int *p_match_first) internal_function; static int check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context) internal_function; static int check_halt_state_context (const re_match_context_t *mctx, const re_dfastate_t *state, int idx) internal_function; static void update_regs (re_dfa_t *dfa, regmatch_t *pmatch, regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch) internal_function; static int proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs, int *pidx, int node, re_node_set *eps_via_nodes, struct re_fail_stack_t *fs) internal_function; static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node, int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) internal_function; static int pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) internal_function; static reg_errcode_t set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, regmatch_t *pmatch, int fl_backtrack) internal_function; static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs) internal_function; #ifdef RE_ENABLE_I18N static int sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, int node_idx, int str_idx, int max_str_idx) internal_function; #endif /* RE_ENABLE_I18N */ static reg_errcode_t sift_states_backward (re_match_context_t *mctx, re_sift_context_t *sctx) internal_function; static reg_errcode_t build_sifted_states (re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *cur_dest) internal_function; static reg_errcode_t update_cur_sifted_state (re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *dest_nodes) internal_function; static reg_errcode_t add_epsilon_src_nodes (re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates) internal_function; static reg_errcode_t sub_epsilon_src_nodes (re_dfa_t *dfa, int node, re_node_set *dest_nodes, const re_node_set *and_nodes) internal_function; static int check_dst_limits (re_match_context_t *mctx, re_node_set *limits, int dst_node, int dst_idx, int src_node, int src_idx) internal_function; static int check_dst_limits_calc_pos_1 (re_match_context_t *mctx, int boundaries, int subexp_idx, int from_node, int bkref_idx) internal_function; static int check_dst_limits_calc_pos (re_match_context_t *mctx, int limit, int subexp_idx, int node, int str_idx, int bkref_idx) internal_function; static reg_errcode_t check_subexp_limits (re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates, re_node_set *limits, struct re_backref_cache_entry *bkref_ents, int str_idx) internal_function; static reg_errcode_t sift_states_bkref (re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, const re_node_set *candidates) internal_function; static reg_errcode_t clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx) internal_function; static reg_errcode_t merge_state_array (re_dfa_t *dfa, re_dfastate_t **dst, re_dfastate_t **src, int num) internal_function; static re_dfastate_t *find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) internal_function; static re_dfastate_t *transit_state (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *state) internal_function; static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *next_state) internal_function; static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, int str_idx) internal_function; #if 0 static re_dfastate_t *transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *pstate) internal_function; #endif #ifdef RE_ENABLE_I18N static reg_errcode_t transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) internal_function; #endif /* RE_ENABLE_I18N */ static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) internal_function; static reg_errcode_t get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx) internal_function; static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, re_sub_match_last_t *sub_last, int bkref_node, int bkref_str) internal_function; static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, int subexp_idx, int type) internal_function; static reg_errcode_t check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node, int top_str, int last_node, int last_str, int type) internal_function; static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx, re_node_set *cur_nodes, re_node_set *next_nodes) internal_function; static reg_errcode_t check_arrival_expand_ecl (re_dfa_t *dfa, re_node_set *cur_nodes, int ex_subexp, int type) internal_function; static reg_errcode_t check_arrival_expand_ecl_sub (re_dfa_t *dfa, re_node_set *dst_nodes, int target, int ex_subexp, int type) internal_function; static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, int cur_str, int subexp_num, int type) internal_function; static re_dfastate_t **build_trtable (re_dfa_t *dfa, re_dfastate_t *state) internal_function; #ifdef RE_ENABLE_I18N static int check_node_accept_bytes (re_dfa_t *dfa, int node_idx, const re_string_t *input, int idx) internal_function; # ifdef _LIBC static unsigned int find_collation_sequence_value (const unsigned char *mbs, size_t name_len) internal_function; # endif /* _LIBC */ #endif /* RE_ENABLE_I18N */ static int group_nodes_into_DFAstates (re_dfa_t *dfa, const re_dfastate_t *state, re_node_set *states_node, bitset *states_ch) internal_function; static int check_node_accept (const re_match_context_t *mctx, const re_token_t *node, int idx) internal_function; static reg_errcode_t extend_buffers (re_match_context_t *mctx) internal_function; /* Entry point for POSIX code. */ /* regexec searches for a given pattern, specified by PREG, in the string STRING. If NMATCH is zero or REG_NOSUB was set in the cflags argument to `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at least NMATCH elements, and we set them to the offsets of the corresponding matched substrings. EFLAGS specifies `execution flags' which affect matching: if REG_NOTBOL is set, then ^ does not match at the beginning of the string; if REG_NOTEOL is set, then $ does not match at the end. We return 0 if we find a match and REG_NOMATCH if not. */ int regexec (preg, string, nmatch, pmatch, eflags) const regex_t *__restrict preg; const char *__restrict string; size_t nmatch; regmatch_t pmatch[]; int eflags; { reg_errcode_t err; int start, length; if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) return REG_BADPAT; if (eflags & REG_STARTEND) { start = pmatch[0].rm_so; length = pmatch[0].rm_eo; } else { start = 0; length = strlen (string); } if (preg->no_sub) err = re_search_internal (preg, string, length, start, length - start, length, 0, NULL, eflags); else err = re_search_internal (preg, string, length, start, length - start, length, nmatch, pmatch, eflags); return err != REG_NOERROR; } #ifdef _LIBC # include versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) __typeof__ (__regexec) __compat_regexec; int attribute_compat_text_section __compat_regexec (const regex_t *__restrict preg, const char *__restrict string, size_t nmatch, regmatch_t pmatch[], int eflags) { return regexec (preg, string, nmatch, pmatch, eflags & (REG_NOTBOL | REG_NOTEOL)); } compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); # endif #endif /* Entry points for GNU code. */ /* re_match, re_search, re_match_2, re_search_2 The former two functions operate on STRING with length LENGTH, while the later two operate on concatenation of STRING1 and STRING2 with lengths LENGTH1 and LENGTH2, respectively. re_match() matches the compiled pattern in BUFP against the string, starting at index START. re_search() first tries matching at index START, then it tries to match starting from index START + 1, and so on. The last start position tried is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same way as re_match().) The parameter STOP of re_{match,search}_2 specifies that no match exceeding the first STOP characters of the concatenation of the strings should be concerned. If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match and all groups is stroed in REGS. (For the "_2" variants, the offsets are computed relative to the concatenation, not relative to the individual strings.) On success, re_match* functions return the length of the match, re_search* return the position of the start of the match. Return value -1 means no match was found and -2 indicates an internal error. */ int re_match (bufp, string, length, start, regs) struct re_pattern_buffer *bufp; const char *string; int length, start; struct re_registers *regs; { return re_search_stub (bufp, string, length, start, 0, length, regs, 1); } #ifdef _LIBC weak_alias (__re_match, re_match) #endif int re_search (bufp, string, length, start, range, regs) struct re_pattern_buffer *bufp; const char *string; int length, start, range; struct re_registers *regs; { return re_search_stub (bufp, string, length, start, range, length, regs, 0); } #ifdef _LIBC weak_alias (__re_search, re_search) #endif int re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int length1, length2, start, stop; struct re_registers *regs; { return re_search_2_stub (bufp, string1, length1, string2, length2, start, 0, regs, stop, 1); } #ifdef _LIBC weak_alias (__re_match_2, re_match_2) #endif int re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop) struct re_pattern_buffer *bufp; const char *string1, *string2; int length1, length2, start, range, stop; struct re_registers *regs; { return re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs, stop, 0); } #ifdef _LIBC weak_alias (__re_search_2, re_search_2) #endif static int re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs, stop, ret_len) struct re_pattern_buffer *bufp; const char *string1, *string2; int length1, length2, start, range, stop, ret_len; struct re_registers *regs; { const char *str; int rval; int len = length1 + length2; int free_str = 0; if (BE (length1 < 0 || length2 < 0 || stop < 0, 0)) return -2; /* Concatenate the strings. */ if (length2 > 0) if (length1 > 0) { char *s = re_malloc (char, len); if (BE (s == NULL, 0)) return -2; memcpy (s, string1, length1); memcpy (s + length1, string2, length2); str = s; free_str = 1; } else str = string2; else str = string1; rval = re_search_stub (bufp, str, len, start, range, stop, regs, ret_len); if (free_str) re_free ((char *) str); return rval; } /* The parameters have the same meaning as those of re_search. Additional parameters: If RET_LEN is nonzero the length of the match is returned (re_match style); otherwise the position of the match is returned. */ static int re_search_stub (bufp, string, length, start, range, stop, regs, ret_len) struct re_pattern_buffer *bufp; const char *string; int length, start, range, stop, ret_len; struct re_registers *regs; { reg_errcode_t result; regmatch_t *pmatch; int nregs, rval; int eflags = 0; /* Check for out-of-range. */ if (BE (start < 0 || start > length, 0)) return -1; if (BE (start + range > length, 0)) range = length - start; else if (BE (start + range < 0, 0)) range = -start; eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; /* Compile fastmap if we haven't yet. */ if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate) re_compile_fastmap (bufp); if (BE (bufp->no_sub, 0)) regs = NULL; /* We need at least 1 register. */ if (regs == NULL) nregs = 1; else if (BE (bufp->regs_allocated == REGS_FIXED && regs->num_regs < bufp->re_nsub + 1, 0)) { nregs = regs->num_regs; if (BE (nregs < 1, 0)) { /* Nothing can be copied to regs. */ regs = NULL; nregs = 1; } } else nregs = bufp->re_nsub + 1; pmatch = re_malloc (regmatch_t, nregs); if (BE (pmatch == NULL, 0)) return -2; result = re_search_internal (bufp, string, length, start, range, stop, nregs, pmatch, eflags); rval = 0; /* I hope we needn't fill ther regs with -1's when no match was found. */ if (result != REG_NOERROR) rval = -1; else if (regs != NULL) { /* If caller wants register contents data back, copy them. */ bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, bufp->regs_allocated); if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0)) rval = -2; } if (BE (rval == 0, 1)) { if (ret_len) { assert (pmatch[0].rm_so == start); rval = pmatch[0].rm_eo - start; } else rval = pmatch[0].rm_so; } re_free (pmatch); return rval; } static unsigned re_copy_regs (regs, pmatch, nregs, regs_allocated) struct re_registers *regs; regmatch_t *pmatch; int nregs, regs_allocated; { int rval = REGS_REALLOCATE; int i; int need_regs = nregs + 1; /* We need one extra element beyond `num_regs' for the `-1' marker GNU code uses. */ /* Have the register data arrays been allocated? */ if (regs_allocated == REGS_UNALLOCATED) { /* No. So allocate them with malloc. */ regs->start = re_malloc (regoff_t, need_regs); regs->end = re_malloc (regoff_t, need_regs); if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0)) return REGS_UNALLOCATED; regs->num_regs = need_regs; } else if (regs_allocated == REGS_REALLOCATE) { /* Yes. If we need more elements than were already allocated, reallocate them. If we need fewer, just leave it alone. */ if (BE (need_regs > regs->num_regs, 0)) { regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs); if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0)) return REGS_UNALLOCATED; regs->start = new_start; regs->end = new_end; regs->num_regs = need_regs; } } else { assert (regs_allocated == REGS_FIXED); /* This function may not be called with REGS_FIXED and nregs too big. */ assert (regs->num_regs >= nregs); rval = REGS_FIXED; } /* Copy the regs. */ for (i = 0; i < nregs; ++i) { regs->start[i] = pmatch[i].rm_so; regs->end[i] = pmatch[i].rm_eo; } for ( ; i < regs->num_regs; ++i) regs->start[i] = regs->end[i] = -1; return rval; } /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated using the malloc library routine, and must each be at least NUM_REGS * sizeof (regoff_t) bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ void re_set_registers (bufp, regs, num_regs, starts, ends) struct re_pattern_buffer *bufp; struct re_registers *regs; unsigned num_regs; regoff_t *starts, *ends; { if (num_regs) { bufp->regs_allocated = REGS_REALLOCATE; regs->num_regs = num_regs; regs->start = starts; regs->end = ends; } else { bufp->regs_allocated = REGS_UNALLOCATED; regs->num_regs = 0; regs->start = regs->end = (regoff_t *) 0; } } #ifdef _LIBC weak_alias (__re_set_registers, re_set_registers) #endif /* Entry points compatible with 4.2 BSD regex library. We don't define them unless specifically requested. */ #if defined _REGEX_RE_COMP || defined _LIBC int # ifdef _LIBC weak_function # endif re_exec (s) const char *s; { return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); } #endif /* _REGEX_RE_COMP */ /* Internal entry point. */ /* Searches for a compiled pattern PREG in the string STRING, whose length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same mingings with regexec. START, and RANGE have the same meanings with re_search. Return REG_NOERROR if we find a match, and REG_NOMATCH if not, otherwise return the error code. Note: We assume front end functions already check ranges. (START + RANGE >= 0 && START + RANGE <= LENGTH) */ static reg_errcode_t re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch, eflags) const regex_t *preg; const char *string; int length, start, range, stop, eflags; size_t nmatch; regmatch_t pmatch[]; { reg_errcode_t err; re_dfa_t *dfa = (re_dfa_t *)preg->buffer; int left_lim, right_lim, incr; int fl_longest_match, match_first, match_kind, match_last = -1; int sb, ch; #if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) re_match_context_t mctx = { .dfa = dfa }; #else re_match_context_t mctx; #endif char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate && range && !preg->can_be_null) ? preg->fastmap : NULL; unsigned RE_TRANSLATE_TYPE t = (unsigned RE_TRANSLATE_TYPE) preg->translate; #if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) memset (&mctx, '\0', sizeof (re_match_context_t)); mctx.dfa = dfa; #endif /* Check if the DFA haven't been compiled. */ if (BE (preg->used == 0 || dfa->init_state == NULL || dfa->init_state_word == NULL || dfa->init_state_nl == NULL || dfa->init_state_begbuf == NULL, 0)) return REG_NOMATCH; #ifdef DEBUG /* We assume front-end functions already check them. */ assert (start + range >= 0 && start + range <= length); #endif /* If initial states with non-begbuf contexts have no elements, the regex must be anchored. If preg->newline_anchor is set, we'll never use init_state_nl, so do not check it. */ if (dfa->init_state->nodes.nelem == 0 && dfa->init_state_word->nodes.nelem == 0 && (dfa->init_state_nl->nodes.nelem == 0 || !preg->newline_anchor)) { if (start != 0 && start + range != 0) return REG_NOMATCH; start = range = 0; } /* We must check the longest matching, if nmatch > 0. */ fl_longest_match = (nmatch != 0 || dfa->nbackref); err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, preg->translate, preg->syntax & RE_ICASE, dfa); if (BE (err != REG_NOERROR, 0)) goto free_return; mctx.input.stop = stop; mctx.input.raw_stop = stop; mctx.input.newline_anchor = preg->newline_anchor; err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); if (BE (err != REG_NOERROR, 0)) goto free_return; /* We will log all the DFA states through which the dfa pass, if nmatch > 1, or this dfa has "multibyte node", which is a back-reference or a node which can accept multibyte character or multi character collating element. */ if (nmatch > 1 || dfa->has_mb_node) { mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); if (BE (mctx.state_log == NULL, 0)) { err = REG_ESPACE; goto free_return; } } else mctx.state_log = NULL; match_first = start; mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF : CONTEXT_NEWLINE | CONTEXT_BEGBUF; /* Check incrementally whether of not the input string match. */ incr = (range < 0) ? -1 : 1; left_lim = (range < 0) ? start + range : start; right_lim = (range < 0) ? start : start + range; sb = dfa->mb_cur_max == 1; match_kind = (fastmap ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) | (range >= 0 ? 2 : 0) | (t != NULL ? 1 : 0)) : 8); for (;; match_first += incr) { err = REG_NOMATCH; if (match_first < left_lim || right_lim < match_first) goto free_return; /* Advance as rapidly as possible through the string, until we find a plausible place to start matching. This may be done with varying efficiency, so there are various possibilities: only the most common of them are specialized, in order to save on code size. We use a switch statement for speed. */ switch (match_kind) { case 8: /* No fastmap. */ break; case 7: /* Fastmap with single-byte translation, match forward. */ while (BE (match_first < right_lim, 1) && !fastmap[t[(unsigned char) string[match_first]]]) ++match_first; goto forward_match_found_start_or_reached_end; case 6: /* Fastmap without translation, match forward. */ while (BE (match_first < right_lim, 1) && !fastmap[(unsigned char) string[match_first]]) ++match_first; forward_match_found_start_or_reached_end: if (BE (match_first == right_lim, 0)) { ch = match_first >= length ? 0 : (unsigned char) string[match_first]; if (!fastmap[t ? t[ch] : ch]) goto free_return; } break; case 4: case 5: /* Fastmap without multi-byte translation, match backwards. */ while (match_first >= left_lim) { ch = match_first >= length ? 0 : (unsigned char) string[match_first]; if (fastmap[t ? t[ch] : ch]) break; --match_first; } if (match_first < left_lim) goto free_return; break; default: /* In this case, we can't determine easily the current byte, since it might be a component byte of a multibyte character. Then we use the constructed buffer instead. */ for (;;) { /* If MATCH_FIRST is out of the valid range, reconstruct the buffers. */ unsigned int offset = match_first - mctx.input.raw_mbs_idx; if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0)) { err = re_string_reconstruct (&mctx.input, match_first, eflags); if (BE (err != REG_NOERROR, 0)) goto free_return; offset = match_first - mctx.input.raw_mbs_idx; } /* If MATCH_FIRST is out of the buffer, leave it as '\0'. Note that MATCH_FIRST must not be smaller than 0. */ ch = (match_first >= length ? 0 : re_string_byte_at (&mctx.input, offset)); if (fastmap[ch]) break; match_first += incr; if (match_first < left_lim || match_first > right_lim) { err = REG_NOMATCH; goto free_return; } } break; } /* Reconstruct the buffers so that the matcher can assume that the matching starts from the beginning of the buffer. */ err = re_string_reconstruct (&mctx.input, match_first, eflags); if (BE (err != REG_NOERROR, 0)) goto free_return; #ifdef RE_ENABLE_I18N /* Don't consider this char as a possible match start if it part, yet isn't the head, of a multibyte character. */ if (!sb && !re_string_first_byte (&mctx.input, 0)) continue; #endif /* It seems to be appropriate one, then use the matcher. */ /* We assume that the matching starts from 0. */ mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; match_last = check_matching (&mctx, fl_longest_match, range >= 0 ? &match_first : NULL); if (match_last != -1) { if (BE (match_last == -2, 0)) { err = REG_ESPACE; goto free_return; } else { mctx.match_last = match_last; if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) { re_dfastate_t *pstate = mctx.state_log[match_last]; mctx.last_node = check_halt_state_context (&mctx, pstate, match_last); } if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) || dfa->nbackref) { err = prune_impossible_nodes (&mctx); if (err == REG_NOERROR) break; if (BE (err != REG_NOMATCH, 0)) goto free_return; match_last = -1; } else break; /* We found a match. */ } } match_ctx_clean (&mctx); } #ifdef DEBUG assert (match_last != -1); assert (err == REG_NOERROR); #endif /* Set pmatch[] if we need. */ if (nmatch > 0) { int reg_idx; /* Initialize registers. */ for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; /* Set the points where matching start/end. */ pmatch[0].rm_so = 0; pmatch[0].rm_eo = mctx.match_last; if (!preg->no_sub && nmatch > 1) { err = set_regs (preg, &mctx, nmatch, pmatch, dfa->has_plural_match && dfa->nbackref > 0); if (BE (err != REG_NOERROR, 0)) goto free_return; } /* At last, add the offset to the each registers, since we slided the buffers so that we could assume that the matching starts from 0. */ for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) if (pmatch[reg_idx].rm_so != -1) { #ifdef RE_ENABLE_I18N if (BE (mctx.input.offsets_needed != 0, 0)) { if (pmatch[reg_idx].rm_so == mctx.input.valid_len) pmatch[reg_idx].rm_so += mctx.input.valid_raw_len - mctx.input.valid_len; else pmatch[reg_idx].rm_so = mctx.input.offsets[pmatch[reg_idx].rm_so]; if (pmatch[reg_idx].rm_eo == mctx.input.valid_len) pmatch[reg_idx].rm_eo += mctx.input.valid_raw_len - mctx.input.valid_len; else pmatch[reg_idx].rm_eo = mctx.input.offsets[pmatch[reg_idx].rm_eo]; } #else assert (mctx.input.offsets_needed == 0); #endif pmatch[reg_idx].rm_so += match_first; pmatch[reg_idx].rm_eo += match_first; } if (dfa->subexp_map) for (reg_idx = 0; reg_idx + 1 < nmatch && reg_idx < preg->re_nsub; reg_idx++) if (dfa->subexp_map[reg_idx] != reg_idx) { pmatch[reg_idx + 1].rm_so = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; pmatch[reg_idx + 1].rm_eo = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; } } free_return: re_free (mctx.state_log); if (dfa->nbackref) match_ctx_free (&mctx); re_string_destruct (&mctx.input); return err; } static reg_errcode_t prune_impossible_nodes (mctx) re_match_context_t *mctx; { re_dfa_t *const dfa = mctx->dfa; int halt_node, match_last; reg_errcode_t ret; re_dfastate_t **sifted_states; re_dfastate_t **lim_states = NULL; re_sift_context_t sctx; #ifdef DEBUG assert (mctx->state_log != NULL); #endif match_last = mctx->match_last; halt_node = mctx->last_node; sifted_states = re_malloc (re_dfastate_t *, match_last + 1); if (BE (sifted_states == NULL, 0)) { ret = REG_ESPACE; goto free_return; } if (dfa->nbackref) { lim_states = re_malloc (re_dfastate_t *, match_last + 1); if (BE (lim_states == NULL, 0)) { ret = REG_ESPACE; goto free_return; } while (1) { memset (lim_states, '\0', sizeof (re_dfastate_t *) * (match_last + 1)); sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); ret = sift_states_backward (mctx, &sctx); re_node_set_free (&sctx.limits); if (BE (ret != REG_NOERROR, 0)) goto free_return; if (sifted_states[0] != NULL || lim_states[0] != NULL) break; do { --match_last; if (match_last < 0) { ret = REG_NOMATCH; goto free_return; } } while (mctx->state_log[match_last] == NULL || !mctx->state_log[match_last]->halt); halt_node = check_halt_state_context (mctx, mctx->state_log[match_last], match_last); } ret = merge_state_array (dfa, sifted_states, lim_states, match_last + 1); re_free (lim_states); lim_states = NULL; if (BE (ret != REG_NOERROR, 0)) goto free_return; } else { sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); ret = sift_states_backward (mctx, &sctx); re_node_set_free (&sctx.limits); if (BE (ret != REG_NOERROR, 0)) goto free_return; } re_free (mctx->state_log); mctx->state_log = sifted_states; sifted_states = NULL; mctx->last_node = halt_node; mctx->match_last = match_last; ret = REG_NOERROR; free_return: re_free (sifted_states); re_free (lim_states); return ret; } /* Acquire an initial state and return it. We must select appropriate initial state depending on the context, since initial states may have constraints like "\<", "^", etc.. */ static inline re_dfastate_t * acquire_init_state_context (err, mctx, idx) reg_errcode_t *err; const re_match_context_t *mctx; int idx; { re_dfa_t *const dfa = mctx->dfa; if (dfa->init_state->has_constraint) { unsigned int context; context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); if (IS_WORD_CONTEXT (context)) return dfa->init_state_word; else if (IS_ORDINARY_CONTEXT (context)) return dfa->init_state; else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) return dfa->init_state_begbuf; else if (IS_NEWLINE_CONTEXT (context)) return dfa->init_state_nl; else if (IS_BEGBUF_CONTEXT (context)) { /* It is relatively rare case, then calculate on demand. */ return re_acquire_state_context (err, dfa, dfa->init_state->entrance_nodes, context); } else /* Must not happen? */ return dfa->init_state; } else return dfa->init_state; } /* Check whether the regular expression match input string INPUT or not, and return the index where the matching end, return -1 if not match, or return -2 in case of an error. FL_LONGEST_MATCH means we want the POSIX longest matching. If P_MATCH_FIRST is not NULL, and the match fails, it is set to the next place where we may want to try matching. Note that the matcher assume that the maching starts from the current index of the buffer. */ static int check_matching (mctx, fl_longest_match, p_match_first) re_match_context_t *mctx; int fl_longest_match; int *p_match_first; { re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int match = 0; int match_last = -1; int cur_str_idx = re_string_cur_idx (&mctx->input); re_dfastate_t *cur_state; int at_init_state = p_match_first != NULL; int next_start_idx = cur_str_idx; err = REG_NOERROR; cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); /* An initial state must not be NULL (invalid). */ if (BE (cur_state == NULL, 0)) { assert (err == REG_ESPACE); return -2; } if (mctx->state_log != NULL) { mctx->state_log[cur_str_idx] = cur_state; /* Check OP_OPEN_SUBEXP in the initial state in case that we use them later. E.g. Processing back references. */ if (BE (dfa->nbackref, 0)) { at_init_state = 0; err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); if (BE (err != REG_NOERROR, 0)) return err; if (cur_state->has_backref) { err = transit_state_bkref (mctx, &cur_state->nodes); if (BE (err != REG_NOERROR, 0)) return err; } } } /* If the RE accepts NULL string. */ if (BE (cur_state->halt, 0)) { if (!cur_state->has_constraint || check_halt_state_context (mctx, cur_state, cur_str_idx)) { if (!fl_longest_match) return cur_str_idx; else { match_last = cur_str_idx; match = 1; } } } while (!re_string_eoi (&mctx->input)) { re_dfastate_t *old_state = cur_state; int next_char_idx = re_string_cur_idx (&mctx->input) + 1; if (BE (next_char_idx >= mctx->input.bufs_len, 0) || (BE (next_char_idx >= mctx->input.valid_len, 0) && mctx->input.valid_len < mctx->input.len)) { err = extend_buffers (mctx); if (BE (err != REG_NOERROR, 0)) { assert (err == REG_ESPACE); return -2; } } cur_state = transit_state (&err, mctx, cur_state); if (mctx->state_log != NULL) cur_state = merge_state_with_log (&err, mctx, cur_state); if (cur_state == NULL) { /* Reached the invalid state or an error. Try to recover a valid state using the state log, if available and if we have not already found a valid (even if not the longest) match. */ if (BE (err != REG_NOERROR, 0)) return -2; if (mctx->state_log == NULL || (match && !fl_longest_match) || (cur_state = find_recover_state (&err, mctx)) == NULL) break; } if (BE (at_init_state, 0)) { if (old_state == cur_state) next_start_idx = next_char_idx; else at_init_state = 0; } if (cur_state->halt) { /* Reached a halt state. Check the halt state can satisfy the current context. */ if (!cur_state->has_constraint || check_halt_state_context (mctx, cur_state, re_string_cur_idx (&mctx->input))) { /* We found an appropriate halt state. */ match_last = re_string_cur_idx (&mctx->input); match = 1; /* We found a match, do not modify match_first below. */ p_match_first = NULL; if (!fl_longest_match) break; } } } if (p_match_first) *p_match_first += next_start_idx; return match_last; } /* Check NODE match the current context. */ static int check_halt_node_context (dfa, node, context) const re_dfa_t *dfa; int node; unsigned int context; { re_token_type_t type = dfa->nodes[node].type; unsigned int constraint = dfa->nodes[node].constraint; if (type != END_OF_RE) return 0; if (!constraint) return 1; if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) return 0; return 1; } /* Check the halt state STATE match the current context. Return 0 if not match, if the node, STATE has, is a halt node and match the context, return the node. */ static int check_halt_state_context (mctx, state, idx) const re_match_context_t *mctx; const re_dfastate_t *state; int idx; { int i; unsigned int context; #ifdef DEBUG assert (state->halt); #endif context = re_string_context_at (&mctx->input, idx, mctx->eflags); for (i = 0; i < state->nodes.nelem; ++i) if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) return state->nodes.elems[i]; return 0; } /* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA corresponding to the DFA). Return the destination node, and update EPS_VIA_NODES, return -1 in case of errors. */ static int proceed_next_node (mctx, nregs, regs, pidx, node, eps_via_nodes, fs) const re_match_context_t *mctx; regmatch_t *regs; int nregs, *pidx, node; re_node_set *eps_via_nodes; struct re_fail_stack_t *fs; { re_dfa_t *const dfa = mctx->dfa; int i, err, dest_node; dest_node = -1; if (IS_EPSILON_NODE (dfa->nodes[node].type)) { re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; re_node_set *edests = &dfa->edests[node]; int dest_node; err = re_node_set_insert (eps_via_nodes, node); if (BE (err < 0, 0)) return -2; /* Pick up a valid destination, or return -1 if none is found. */ for (dest_node = -1, i = 0; i < edests->nelem; ++i) { int candidate = edests->elems[i]; if (!re_node_set_contains (cur_nodes, candidate)) continue; if (dest_node == -1) dest_node = candidate; else { /* In order to avoid infinite loop like "(a*)*", return the second epsilon-transition if the first was already considered. */ if (re_node_set_contains (eps_via_nodes, dest_node)) return candidate; /* Otherwise, push the second epsilon-transition on the fail stack. */ else if (fs != NULL && push_fail_stack (fs, *pidx, candidate, nregs, regs, eps_via_nodes)) return -2; /* We know we are going to exit. */ break; } } return dest_node; } else { int naccepted = 0; re_token_type_t type = dfa->nodes[node].type; #ifdef RE_ENABLE_I18N if (ACCEPT_MB_NODE (type)) naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); else #endif /* RE_ENABLE_I18N */ if (type == OP_BACK_REF) { int subexp_idx = dfa->nodes[node].opr.idx + 1; naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; if (fs != NULL) { if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1) return -1; else if (naccepted) { char *buf = (char *) re_string_get_buffer (&mctx->input); if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, naccepted) != 0) return -1; } } if (naccepted == 0) { err = re_node_set_insert (eps_via_nodes, node); if (BE (err < 0, 0)) return -2; dest_node = dfa->edests[node].elems[0]; if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, dest_node)) return dest_node; } } if (naccepted != 0 || check_node_accept (mctx, dfa->nodes + node, *pidx)) { dest_node = dfa->nexts[node]; *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, dest_node))) return -1; re_node_set_empty (eps_via_nodes); return dest_node; } } return -1; } static reg_errcode_t push_fail_stack (fs, str_idx, dest_node, nregs, regs, eps_via_nodes) struct re_fail_stack_t *fs; int str_idx, dest_node, nregs; regmatch_t *regs; re_node_set *eps_via_nodes; { reg_errcode_t err; int num = fs->num++; if (fs->num == fs->alloc) { struct re_fail_stack_ent_t *new_array; new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t) * fs->alloc * 2)); if (new_array == NULL) return REG_ESPACE; fs->alloc *= 2; fs->stack = new_array; } fs->stack[num].idx = str_idx; fs->stack[num].node = dest_node; fs->stack[num].regs = re_malloc (regmatch_t, nregs); if (fs->stack[num].regs == NULL) return REG_ESPACE; memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); return err; } static int pop_fail_stack (fs, pidx, nregs, regs, eps_via_nodes) struct re_fail_stack_t *fs; int *pidx, nregs; regmatch_t *regs; re_node_set *eps_via_nodes; { int num = --fs->num; assert (num >= 0); *pidx = fs->stack[num].idx; memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); re_node_set_free (eps_via_nodes); re_free (fs->stack[num].regs); *eps_via_nodes = fs->stack[num].eps_via_nodes; return fs->stack[num].node; } /* Set the positions where the subexpressions are starts/ends to registers PMATCH. Note: We assume that pmatch[0] is already set, and pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ static reg_errcode_t set_regs (preg, mctx, nmatch, pmatch, fl_backtrack) const regex_t *preg; const re_match_context_t *mctx; size_t nmatch; regmatch_t *pmatch; int fl_backtrack; { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; int idx, cur_node, real_nmatch; re_node_set eps_via_nodes; struct re_fail_stack_t *fs; struct re_fail_stack_t fs_body = { 0, 2, NULL }; regmatch_t *prev_idx_match; #ifdef DEBUG assert (nmatch > 1); assert (mctx->state_log != NULL); #endif if (fl_backtrack) { fs = &fs_body; fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); if (fs->stack == NULL) return REG_ESPACE; } else fs = NULL; cur_node = dfa->init_node; real_nmatch = (nmatch <= preg->re_nsub) ? nmatch : preg->re_nsub + 1; re_node_set_init_empty (&eps_via_nodes); prev_idx_match = (regmatch_t *) alloca (sizeof (regmatch_t) * real_nmatch); memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * real_nmatch); for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) { update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, real_nmatch); if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) { int reg_idx; if (fs) { for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) break; if (reg_idx == nmatch) { re_node_set_free (&eps_via_nodes); return free_fail_stack_return (fs); } cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, &eps_via_nodes); } else { re_node_set_free (&eps_via_nodes); return REG_NOERROR; } } /* Proceed to next node. */ cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, &eps_via_nodes, fs); if (BE (cur_node < 0, 0)) { if (BE (cur_node == -2, 0)) { re_node_set_free (&eps_via_nodes); free_fail_stack_return (fs); return REG_ESPACE; } if (fs) cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, &eps_via_nodes); else { re_node_set_free (&eps_via_nodes); return REG_NOMATCH; } } } re_node_set_free (&eps_via_nodes); return free_fail_stack_return (fs); } static reg_errcode_t free_fail_stack_return (fs) struct re_fail_stack_t *fs; { if (fs) { int fs_idx; for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) { re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); re_free (fs->stack[fs_idx].regs); } re_free (fs->stack); } return REG_NOERROR; } static void update_regs (dfa, pmatch, prev_idx_match, cur_node, cur_idx, nmatch) re_dfa_t *dfa; regmatch_t *pmatch, *prev_idx_match; int cur_node, cur_idx, nmatch; { int type = dfa->nodes[cur_node].type; if (type == OP_OPEN_SUBEXP) { int reg_num = dfa->nodes[cur_node].opr.idx + 1; /* We are at the first node of this sub expression. */ if (reg_num < nmatch) { pmatch[reg_num].rm_so = cur_idx; pmatch[reg_num].rm_eo = -1; } } else if (type == OP_CLOSE_SUBEXP) { int reg_num = dfa->nodes[cur_node].opr.idx + 1; if (reg_num < nmatch) { /* We are at the last node of this sub expression. */ if (pmatch[reg_num].rm_so < cur_idx) { pmatch[reg_num].rm_eo = cur_idx; /* This is a non-empty match or we are not inside an optional subexpression. Accept this right away. */ memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); } else { if (dfa->nodes[cur_node].opt_subexp && prev_idx_match[reg_num].rm_so != -1) /* We transited through an empty match for an optional subexpression, like (a?)*, and this is not the subexp's first match. Copy back the old content of the registers so that matches of an inner subexpression are undone as well, like in ((a?))*. */ memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); else /* We completed a subexpression, but it may be part of an optional one, so do not update PREV_IDX_MATCH. */ pmatch[reg_num].rm_eo = cur_idx; } } } } /* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 and sift the nodes in each states according to the following rules. Updated state_log will be wrote to STATE_LOG. Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... 1. When STR_IDX == MATCH_LAST(the last index in the state_log): If `a' isn't the LAST_NODE and `a' can't epsilon transit to the LAST_NODE, we throw away the node `a'. 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts string `s' and transit to `b': i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw away the node `a'. ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is thrown away, we throw away the node `a'. 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the node `a'. ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, we throw away the node `a'. */ #define STATE_NODE_CONTAINS(state,node) \ ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) static reg_errcode_t sift_states_backward (mctx, sctx) re_match_context_t *mctx; re_sift_context_t *sctx; { reg_errcode_t err; int null_cnt = 0; int str_idx = sctx->last_str_idx; re_node_set cur_dest; #ifdef DEBUG assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); #endif /* Build sifted state_log[str_idx]. It has the nodes which can epsilon transit to the last_node and the last_node itself. */ err = re_node_set_init_1 (&cur_dest, sctx->last_node); if (BE (err != REG_NOERROR, 0)) return err; err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); if (BE (err != REG_NOERROR, 0)) goto free_return; /* Then check each states in the state_log. */ while (str_idx > 0) { /* Update counters. */ null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; if (null_cnt > mctx->max_mb_elem_len) { memset (sctx->sifted_states, '\0', sizeof (re_dfastate_t *) * str_idx); re_node_set_free (&cur_dest); return REG_NOERROR; } re_node_set_empty (&cur_dest); --str_idx; if (mctx->state_log[str_idx]) { err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); if (BE (err != REG_NOERROR, 0)) goto free_return; } /* Add all the nodes which satisfy the following conditions: - It can epsilon transit to a node in CUR_DEST. - It is in CUR_SRC. And update state_log. */ err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); if (BE (err != REG_NOERROR, 0)) goto free_return; } err = REG_NOERROR; free_return: re_node_set_free (&cur_dest); return err; } static reg_errcode_t build_sifted_states (mctx, sctx, str_idx, cur_dest) re_match_context_t *mctx; re_sift_context_t *sctx; int str_idx; re_node_set *cur_dest; { re_dfa_t *const dfa = mctx->dfa; re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; int i; /* Then build the next sifted state. We build the next sifted state on `cur_dest', and update `sifted_states[str_idx]' with `cur_dest'. Note: `cur_dest' is the sifted state from `state_log[str_idx + 1]'. `cur_src' points the node_set of the old `state_log[str_idx]' (with the epsilon nodes pre-filtered out). */ for (i = 0; i < cur_src->nelem; i++) { int prev_node = cur_src->elems[i]; int naccepted = 0; int ret; #if defined DEBUG || defined RE_ENABLE_I18N re_token_type_t type = dfa->nodes[prev_node].type; #endif #ifdef DEBUG assert (!IS_EPSILON_NODE (type)); #endif #ifdef RE_ENABLE_I18N /* If the node may accept `multi byte'. */ if (ACCEPT_MB_NODE (type)) naccepted = sift_states_iter_mb (mctx, sctx, prev_node, str_idx, sctx->last_str_idx); #endif /* RE_ENABLE_I18N */ /* We don't check backreferences here. See update_cur_sifted_state(). */ if (!naccepted && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], dfa->nexts[prev_node])) naccepted = 1; if (naccepted == 0) continue; if (sctx->limits.nelem) { int to_idx = str_idx + naccepted; if (check_dst_limits (mctx, &sctx->limits, dfa->nexts[prev_node], to_idx, prev_node, str_idx)) continue; } ret = re_node_set_insert (cur_dest, prev_node); if (BE (ret == -1, 0)) return REG_ESPACE; } return REG_NOERROR; } /* Helper functions. */ static reg_errcode_t clean_state_log_if_needed (mctx, next_state_log_idx) re_match_context_t *mctx; int next_state_log_idx; { int top = mctx->state_log_top; if (next_state_log_idx >= mctx->input.bufs_len || (next_state_log_idx >= mctx->input.valid_len && mctx->input.valid_len < mctx->input.len)) { reg_errcode_t err; err = extend_buffers (mctx); if (BE (err != REG_NOERROR, 0)) return err; } if (top < next_state_log_idx) { memset (mctx->state_log + top + 1, '\0', sizeof (re_dfastate_t *) * (next_state_log_idx - top)); mctx->state_log_top = next_state_log_idx; } return REG_NOERROR; } static reg_errcode_t merge_state_array (dfa, dst, src, num) re_dfa_t *dfa; re_dfastate_t **dst; re_dfastate_t **src; int num; { int st_idx; reg_errcode_t err; for (st_idx = 0; st_idx < num; ++st_idx) { if (dst[st_idx] == NULL) dst[st_idx] = src[st_idx]; else if (src[st_idx] != NULL) { re_node_set merged_set; err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, &src[st_idx]->nodes); if (BE (err != REG_NOERROR, 0)) return err; dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); re_node_set_free (&merged_set); if (BE (err != REG_NOERROR, 0)) return err; } } return REG_NOERROR; } static reg_errcode_t update_cur_sifted_state (mctx, sctx, str_idx, dest_nodes) re_match_context_t *mctx; re_sift_context_t *sctx; int str_idx; re_node_set *dest_nodes; { re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; const re_node_set *candidates; candidates = ((mctx->state_log[str_idx] == NULL) ? NULL : &mctx->state_log[str_idx]->nodes); if (dest_nodes->nelem == 0) sctx->sifted_states[str_idx] = NULL; else { if (candidates) { /* At first, add the nodes which can epsilon transit to a node in DEST_NODE. */ err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; /* Then, check the limitations in the current sift_context. */ if (sctx->limits.nelem) { err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, mctx->bkref_ents, str_idx); if (BE (err != REG_NOERROR, 0)) return err; } } sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); if (BE (err != REG_NOERROR, 0)) return err; } if (candidates && mctx->state_log[str_idx]->has_backref) { err = sift_states_bkref (mctx, sctx, str_idx, candidates); if (BE (err != REG_NOERROR, 0)) return err; } return REG_NOERROR; } static reg_errcode_t add_epsilon_src_nodes (dfa, dest_nodes, candidates) re_dfa_t *dfa; re_node_set *dest_nodes; const re_node_set *candidates; { reg_errcode_t err = REG_NOERROR; int i; re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); if (BE (err != REG_NOERROR, 0)) return err; if (!state->inveclosure.alloc) { err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); if (BE (err != REG_NOERROR, 0)) return REG_ESPACE; for (i = 0; i < dest_nodes->nelem; i++) re_node_set_merge (&state->inveclosure, dfa->inveclosures + dest_nodes->elems[i]); } return re_node_set_add_intersect (dest_nodes, candidates, &state->inveclosure); } static reg_errcode_t sub_epsilon_src_nodes (dfa, node, dest_nodes, candidates) re_dfa_t *dfa; int node; re_node_set *dest_nodes; const re_node_set *candidates; { int ecl_idx; reg_errcode_t err; re_node_set *inv_eclosure = dfa->inveclosures + node; re_node_set except_nodes; re_node_set_init_empty (&except_nodes); for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) { int cur_node = inv_eclosure->elems[ecl_idx]; if (cur_node == node) continue; if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) { int edst1 = dfa->edests[cur_node].elems[0]; int edst2 = ((dfa->edests[cur_node].nelem > 1) ? dfa->edests[cur_node].elems[1] : -1); if ((!re_node_set_contains (inv_eclosure, edst1) && re_node_set_contains (dest_nodes, edst1)) || (edst2 > 0 && !re_node_set_contains (inv_eclosure, edst2) && re_node_set_contains (dest_nodes, edst2))) { err = re_node_set_add_intersect (&except_nodes, candidates, dfa->inveclosures + cur_node); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&except_nodes); return err; } } } } for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) { int cur_node = inv_eclosure->elems[ecl_idx]; if (!re_node_set_contains (&except_nodes, cur_node)) { int idx = re_node_set_contains (dest_nodes, cur_node) - 1; re_node_set_remove_at (dest_nodes, idx); } } re_node_set_free (&except_nodes); return REG_NOERROR; } static int check_dst_limits (mctx, limits, dst_node, dst_idx, src_node, src_idx) re_match_context_t *mctx; re_node_set *limits; int dst_node, dst_idx, src_node, src_idx; { re_dfa_t *const dfa = mctx->dfa; int lim_idx, src_pos, dst_pos; int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) { int subexp_idx; struct re_backref_cache_entry *ent; ent = mctx->bkref_ents + limits->elems[lim_idx]; subexp_idx = dfa->nodes[ent->node].opr.idx; dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], subexp_idx, dst_node, dst_idx, dst_bkref_idx); src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], subexp_idx, src_node, src_idx, src_bkref_idx); /* In case of: ( ) ( ) ( ) */ if (src_pos == dst_pos) continue; /* This is unrelated limitation. */ else return 1; } return 0; } static int check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, from_node, bkref_idx) re_match_context_t *mctx; int boundaries, subexp_idx, from_node, bkref_idx; { re_dfa_t *const dfa = mctx->dfa; re_node_set *eclosures = dfa->eclosures + from_node; int node_idx; /* Else, we are on the boundary: examine the nodes on the epsilon closure. */ for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) { int node = eclosures->elems[node_idx]; switch (dfa->nodes[node].type) { case OP_BACK_REF: if (bkref_idx != -1) { struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; do { int dst, cpos; if (ent->node != node) continue; if (subexp_idx <= 8 * sizeof (ent->eps_reachable_subexps_map) && !(ent->eps_reachable_subexps_map & (1 << subexp_idx))) continue; /* Recurse trying to reach the OP_OPEN_SUBEXP and OP_CLOSE_SUBEXP cases below. But, if the destination node is the same node as the source node, don't recurse because it would cause an infinite loop: a regex that exhibits this behavior is ()\1*\1* */ dst = dfa->edests[node].elems[0]; if (dst == from_node) { if (boundaries & 1) return -1; else /* if (boundaries & 2) */ return 0; } cpos = check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, dst, bkref_idx); if (cpos == -1 /* && (boundaries & 1) */) return -1; if (cpos == 0 && (boundaries & 2)) return 0; ent->eps_reachable_subexps_map &= ~(1 << subexp_idx); } while (ent++->more); } break; case OP_OPEN_SUBEXP: if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) return -1; break; case OP_CLOSE_SUBEXP: if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) return 0; break; default: break; } } return (boundaries & 2) ? 1 : 0; } static int check_dst_limits_calc_pos (mctx, limit, subexp_idx, from_node, str_idx, bkref_idx) re_match_context_t *mctx; int limit, subexp_idx, from_node, str_idx, bkref_idx; { struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; int boundaries; /* If we are outside the range of the subexpression, return -1 or 1. */ if (str_idx < lim->subexp_from) return -1; if (lim->subexp_to < str_idx) return 1; /* If we are within the subexpression, return 0. */ boundaries = (str_idx == lim->subexp_from); boundaries |= (str_idx == lim->subexp_to) << 1; if (boundaries == 0) return 0; /* Else, examine epsilon closure. */ return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, from_node, bkref_idx); } /* Check the limitations of sub expressions LIMITS, and remove the nodes which are against limitations from DEST_NODES. */ static reg_errcode_t check_subexp_limits (dfa, dest_nodes, candidates, limits, bkref_ents, str_idx) re_dfa_t *dfa; re_node_set *dest_nodes; const re_node_set *candidates; re_node_set *limits; struct re_backref_cache_entry *bkref_ents; int str_idx; { reg_errcode_t err; int node_idx, lim_idx; for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) { int subexp_idx; struct re_backref_cache_entry *ent; ent = bkref_ents + limits->elems[lim_idx]; if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) continue; /* This is unrelated limitation. */ subexp_idx = dfa->nodes[ent->node].opr.idx; if (ent->subexp_to == str_idx) { int ops_node = -1; int cls_node = -1; for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) { int node = dest_nodes->elems[node_idx]; re_token_type_t type = dfa->nodes[node].type; if (type == OP_OPEN_SUBEXP && subexp_idx == dfa->nodes[node].opr.idx) ops_node = node; else if (type == OP_CLOSE_SUBEXP && subexp_idx == dfa->nodes[node].opr.idx) cls_node = node; } /* Check the limitation of the open subexpression. */ /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ if (ops_node >= 0) { err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; } /* Check the limitation of the close subexpression. */ if (cls_node >= 0) for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) { int node = dest_nodes->elems[node_idx]; if (!re_node_set_contains (dfa->inveclosures + node, cls_node) && !re_node_set_contains (dfa->eclosures + node, cls_node)) { /* It is against this limitation. Remove it form the current sifted state. */ err = sub_epsilon_src_nodes (dfa, node, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; --node_idx; } } } else /* (ent->subexp_to != str_idx) */ { for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) { int node = dest_nodes->elems[node_idx]; re_token_type_t type = dfa->nodes[node].type; if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) { if (subexp_idx != dfa->nodes[node].opr.idx) continue; /* It is against this limitation. Remove it form the current sifted state. */ err = sub_epsilon_src_nodes (dfa, node, dest_nodes, candidates); if (BE (err != REG_NOERROR, 0)) return err; } } } } return REG_NOERROR; } static reg_errcode_t sift_states_bkref (mctx, sctx, str_idx, candidates) re_match_context_t *mctx; re_sift_context_t *sctx; int str_idx; const re_node_set *candidates; { re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int node_idx, node; re_sift_context_t local_sctx; int first_idx = search_cur_bkref_entry (mctx, str_idx); if (first_idx == -1) return REG_NOERROR; local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) { int enabled_idx; re_token_type_t type; struct re_backref_cache_entry *entry; node = candidates->elems[node_idx]; type = dfa->nodes[node].type; /* Avoid infinite loop for the REs like "()\1+". */ if (node == sctx->last_node && str_idx == sctx->last_str_idx) continue; if (type != OP_BACK_REF) continue; entry = mctx->bkref_ents + first_idx; enabled_idx = first_idx; do { int subexp_len, to_idx, dst_node; re_dfastate_t *cur_state; if (entry->node != node) continue; subexp_len = entry->subexp_to - entry->subexp_from; to_idx = str_idx + subexp_len; dst_node = (subexp_len ? dfa->nexts[node] : dfa->edests[node].elems[0]); if (to_idx > sctx->last_str_idx || sctx->sifted_states[to_idx] == NULL || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) || check_dst_limits (mctx, &sctx->limits, node, str_idx, dst_node, to_idx)) continue; if (local_sctx.sifted_states == NULL) { local_sctx = *sctx; err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); if (BE (err != REG_NOERROR, 0)) goto free_return; } local_sctx.last_node = node; local_sctx.last_str_idx = str_idx; err = re_node_set_insert (&local_sctx.limits, enabled_idx); if (BE (err < 0, 0)) { err = REG_ESPACE; goto free_return; } cur_state = local_sctx.sifted_states[str_idx]; err = sift_states_backward (mctx, &local_sctx); if (BE (err != REG_NOERROR, 0)) goto free_return; if (sctx->limited_states != NULL) { err = merge_state_array (dfa, sctx->limited_states, local_sctx.sifted_states, str_idx + 1); if (BE (err != REG_NOERROR, 0)) goto free_return; } local_sctx.sifted_states[str_idx] = cur_state; re_node_set_remove (&local_sctx.limits, enabled_idx); /* mctx->bkref_ents may have changed, reload the pointer. */ entry = mctx->bkref_ents + enabled_idx; } while (enabled_idx++, entry++->more); } err = REG_NOERROR; free_return: if (local_sctx.sifted_states != NULL) { re_node_set_free (&local_sctx.limits); } return err; } #ifdef RE_ENABLE_I18N static int sift_states_iter_mb (mctx, sctx, node_idx, str_idx, max_str_idx) const re_match_context_t *mctx; re_sift_context_t *sctx; int node_idx, str_idx, max_str_idx; { re_dfa_t *const dfa = mctx->dfa; int naccepted; /* Check the node can accept `multi byte'. */ naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); if (naccepted > 0 && str_idx + naccepted <= max_str_idx && !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], dfa->nexts[node_idx])) /* The node can't accept the `multi byte', or the destination was already thrown away, then the node could't accept the current input `multi byte'. */ naccepted = 0; /* Otherwise, it is sure that the node could accept `naccepted' bytes input. */ return naccepted; } #endif /* RE_ENABLE_I18N */ /* Functions for state transition. */ /* Return the next state to which the current state STATE will transit by accepting the current input byte, and update STATE_LOG if necessary. If STATE can accept a multibyte char/collating element/back reference update the destination of STATE_LOG. */ static re_dfastate_t * transit_state (err, mctx, state) reg_errcode_t *err; re_match_context_t *mctx; re_dfastate_t *state; { re_dfa_t *const dfa = mctx->dfa; re_dfastate_t **trtable; unsigned char ch; #ifdef RE_ENABLE_I18N /* If the current state can accept multibyte. */ if (BE (state->accept_mb, 0)) { *err = transit_state_mb (mctx, state); if (BE (*err != REG_NOERROR, 0)) return NULL; } #endif /* RE_ENABLE_I18N */ /* Then decide the next state with the single byte. */ if (1) { /* Use transition table */ ch = re_string_fetch_byte (&mctx->input); trtable = state->trtable; if (trtable == NULL) { trtable = build_trtable (dfa, state); if (trtable == NULL) { *err = REG_ESPACE; return NULL; } } if (BE (state->word_trtable, 0)) { unsigned int context; context = re_string_context_at (&mctx->input, re_string_cur_idx (&mctx->input) - 1, mctx->eflags); if (IS_WORD_CONTEXT (context)) return trtable[ch + SBC_MAX]; else return trtable[ch]; } else return trtable[ch]; } #if 0 else /* don't use transition table */ return transit_state_sb (err, mctx, state); #endif } /* Update the state_log if we need */ re_dfastate_t * merge_state_with_log (err, mctx, next_state) reg_errcode_t *err; re_match_context_t *mctx; re_dfastate_t *next_state; { re_dfa_t *const dfa = mctx->dfa; int cur_idx = re_string_cur_idx (&mctx->input); if (cur_idx > mctx->state_log_top) { mctx->state_log[cur_idx] = next_state; mctx->state_log_top = cur_idx; } else if (mctx->state_log[cur_idx] == 0) { mctx->state_log[cur_idx] = next_state; } else { re_dfastate_t *pstate; unsigned int context; re_node_set next_nodes, *log_nodes, *table_nodes = NULL; /* If (state_log[cur_idx] != 0), it implies that cur_idx is the destination of a multibyte char/collating element/ back reference. Then the next state is the union set of these destinations and the results of the transition table. */ pstate = mctx->state_log[cur_idx]; log_nodes = pstate->entrance_nodes; if (next_state != NULL) { table_nodes = next_state->entrance_nodes; *err = re_node_set_init_union (&next_nodes, table_nodes, log_nodes); if (BE (*err != REG_NOERROR, 0)) return NULL; } else next_nodes = *log_nodes; /* Note: We already add the nodes of the initial state, then we don't need to add them here. */ context = re_string_context_at (&mctx->input, re_string_cur_idx (&mctx->input) - 1, mctx->eflags); next_state = mctx->state_log[cur_idx] = re_acquire_state_context (err, dfa, &next_nodes, context); /* We don't need to check errors here, since the return value of this function is next_state and ERR is already set. */ if (table_nodes != NULL) re_node_set_free (&next_nodes); } if (BE (dfa->nbackref, 0) && next_state != NULL) { /* Check OP_OPEN_SUBEXP in the current state in case that we use them later. We must check them here, since the back references in the next state might use them. */ *err = check_subexp_matching_top (mctx, &next_state->nodes, cur_idx); if (BE (*err != REG_NOERROR, 0)) return NULL; /* If the next state has back references. */ if (next_state->has_backref) { *err = transit_state_bkref (mctx, &next_state->nodes); if (BE (*err != REG_NOERROR, 0)) return NULL; next_state = mctx->state_log[cur_idx]; } } return next_state; } /* Skip bytes in the input that correspond to part of a multi-byte match, then look in the log for a state from which to restart matching. */ re_dfastate_t * find_recover_state (err, mctx) reg_errcode_t *err; re_match_context_t *mctx; { re_dfastate_t *cur_state = NULL; do { int max = mctx->state_log_top; int cur_str_idx = re_string_cur_idx (&mctx->input); do { if (++cur_str_idx > max) return NULL; re_string_skip_bytes (&mctx->input, 1); } while (mctx->state_log[cur_str_idx] == NULL); cur_state = merge_state_with_log (err, mctx, NULL); } while (*err == REG_NOERROR && cur_state == NULL); return cur_state; } /* Helper functions for transit_state. */ /* From the node set CUR_NODES, pick up the nodes whose types are OP_OPEN_SUBEXP and which have corresponding back references in the regular expression. And register them to use them later for evaluating the correspoding back references. */ static reg_errcode_t check_subexp_matching_top (mctx, cur_nodes, str_idx) re_match_context_t *mctx; re_node_set *cur_nodes; int str_idx; { re_dfa_t *const dfa = mctx->dfa; int node_idx; reg_errcode_t err; /* TODO: This isn't efficient. Because there might be more than one nodes whose types are OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all nodes. E.g. RE: (a){2} */ for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) { int node = cur_nodes->elems[node_idx]; if (dfa->nodes[node].type == OP_OPEN_SUBEXP && dfa->nodes[node].opr.idx < (8 * sizeof (dfa->used_bkref_map)) && dfa->used_bkref_map & (1 << dfa->nodes[node].opr.idx)) { err = match_ctx_add_subtop (mctx, node, str_idx); if (BE (err != REG_NOERROR, 0)) return err; } } return REG_NOERROR; } #if 0 /* Return the next state to which the current state STATE will transit by accepting the current input byte. */ static re_dfastate_t * transit_state_sb (err, mctx, state) reg_errcode_t *err; re_match_context_t *mctx; re_dfastate_t *state; { re_dfa_t *const dfa = mctx->dfa; re_node_set next_nodes; re_dfastate_t *next_state; int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); unsigned int context; *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); if (BE (*err != REG_NOERROR, 0)) return NULL; for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) { int cur_node = state->nodes.elems[node_cnt]; if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) { *err = re_node_set_merge (&next_nodes, dfa->eclosures + dfa->nexts[cur_node]); if (BE (*err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return NULL; } } } context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); next_state = re_acquire_state_context (err, dfa, &next_nodes, context); /* We don't need to check errors here, since the return value of this function is next_state and ERR is already set. */ re_node_set_free (&next_nodes); re_string_skip_bytes (&mctx->input, 1); return next_state; } #endif #ifdef RE_ENABLE_I18N static reg_errcode_t transit_state_mb (mctx, pstate) re_match_context_t *mctx; re_dfastate_t *pstate; { re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int i; for (i = 0; i < pstate->nodes.nelem; ++i) { re_node_set dest_nodes, *new_nodes; int cur_node_idx = pstate->nodes.elems[i]; int naccepted = 0, dest_idx; unsigned int context; re_dfastate_t *dest_state; if (dfa->nodes[cur_node_idx].constraint) { context = re_string_context_at (&mctx->input, re_string_cur_idx (&mctx->input), mctx->eflags); if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, context)) continue; } /* How many bytes the node can accept? */ if (ACCEPT_MB_NODE (dfa->nodes[cur_node_idx].type)) naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, re_string_cur_idx (&mctx->input)); if (naccepted == 0) continue; /* The node can accepts `naccepted' bytes. */ dest_idx = re_string_cur_idx (&mctx->input) + naccepted; mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted : mctx->max_mb_elem_len); err = clean_state_log_if_needed (mctx, dest_idx); if (BE (err != REG_NOERROR, 0)) return err; #ifdef DEBUG assert (dfa->nexts[cur_node_idx] != -1); #endif /* `cur_node_idx' may point the entity of the OP_CONTEXT_NODE, then we use pstate->nodes.elems[i] instead. */ new_nodes = dfa->eclosures + dfa->nexts[pstate->nodes.elems[i]]; dest_state = mctx->state_log[dest_idx]; if (dest_state == NULL) dest_nodes = *new_nodes; else { err = re_node_set_init_union (&dest_nodes, dest_state->entrance_nodes, new_nodes); if (BE (err != REG_NOERROR, 0)) return err; } context = re_string_context_at (&mctx->input, dest_idx - 1, mctx->eflags); mctx->state_log[dest_idx] = re_acquire_state_context (&err, dfa, &dest_nodes, context); if (dest_state != NULL) re_node_set_free (&dest_nodes); if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0)) return err; } return REG_NOERROR; } #endif /* RE_ENABLE_I18N */ static reg_errcode_t transit_state_bkref (mctx, nodes) re_match_context_t *mctx; const re_node_set *nodes; { re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int i; int cur_str_idx = re_string_cur_idx (&mctx->input); for (i = 0; i < nodes->nelem; ++i) { int dest_str_idx, prev_nelem, bkc_idx; int node_idx = nodes->elems[i]; unsigned int context; const re_token_t *node = dfa->nodes + node_idx; re_node_set *new_dest_nodes; /* Check whether `node' is a backreference or not. */ if (node->type != OP_BACK_REF) continue; if (node->constraint) { context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) continue; } /* `node' is a backreference. Check the substring which the substring matched. */ bkc_idx = mctx->nbkref_ents; err = get_subexp (mctx, node_idx, cur_str_idx); if (BE (err != REG_NOERROR, 0)) goto free_return; /* And add the epsilon closures (which is `new_dest_nodes') of the backreference to appropriate state_log. */ #ifdef DEBUG assert (dfa->nexts[node_idx] != -1); #endif for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) { int subexp_len; re_dfastate_t *dest_state; struct re_backref_cache_entry *bkref_ent; bkref_ent = mctx->bkref_ents + bkc_idx; if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) continue; subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; new_dest_nodes = (subexp_len == 0 ? dfa->eclosures + dfa->edests[node_idx].elems[0] : dfa->eclosures + dfa->nexts[node_idx]); dest_str_idx = (cur_str_idx + bkref_ent->subexp_to - bkref_ent->subexp_from); context = re_string_context_at (&mctx->input, dest_str_idx - 1, mctx->eflags); dest_state = mctx->state_log[dest_str_idx]; prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 : mctx->state_log[cur_str_idx]->nodes.nelem); /* Add `new_dest_node' to state_log. */ if (dest_state == NULL) { mctx->state_log[dest_str_idx] = re_acquire_state_context (&err, dfa, new_dest_nodes, context); if (BE (mctx->state_log[dest_str_idx] == NULL && err != REG_NOERROR, 0)) goto free_return; } else { re_node_set dest_nodes; err = re_node_set_init_union (&dest_nodes, dest_state->entrance_nodes, new_dest_nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&dest_nodes); goto free_return; } mctx->state_log[dest_str_idx] = re_acquire_state_context (&err, dfa, &dest_nodes, context); re_node_set_free (&dest_nodes); if (BE (mctx->state_log[dest_str_idx] == NULL && err != REG_NOERROR, 0)) goto free_return; } /* We need to check recursively if the backreference can epsilon transit. */ if (subexp_len == 0 && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) { err = check_subexp_matching_top (mctx, new_dest_nodes, cur_str_idx); if (BE (err != REG_NOERROR, 0)) goto free_return; err = transit_state_bkref (mctx, new_dest_nodes); if (BE (err != REG_NOERROR, 0)) goto free_return; } } } err = REG_NOERROR; free_return: return err; } /* Enumerate all the candidates which the backreference BKREF_NODE can match at BKREF_STR_IDX, and register them by match_ctx_add_entry(). Note that we might collect inappropriate candidates here. However, the cost of checking them strictly here is too high, then we delay these checking for prune_impossible_nodes(). */ static reg_errcode_t get_subexp (mctx, bkref_node, bkref_str_idx) re_match_context_t *mctx; int bkref_node, bkref_str_idx; { re_dfa_t *const dfa = mctx->dfa; int subexp_num, sub_top_idx; const char *buf = (const char *) re_string_get_buffer (&mctx->input); /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); if (cache_idx != -1) { const struct re_backref_cache_entry *entry = mctx->bkref_ents + cache_idx; do if (entry->node == bkref_node) return REG_NOERROR; /* We already checked it. */ while (entry++->more); } subexp_num = dfa->nodes[bkref_node].opr.idx; /* For each sub expression */ for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) { reg_errcode_t err; re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; re_sub_match_last_t *sub_last; int sub_last_idx, sl_str, bkref_str_off; if (dfa->nodes[sub_top->node].opr.idx != subexp_num) continue; /* It isn't related. */ sl_str = sub_top->str_idx; bkref_str_off = bkref_str_idx; /* At first, check the last node of sub expressions we already evaluated. */ for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) { int sl_str_diff; sub_last = sub_top->lasts[sub_last_idx]; sl_str_diff = sub_last->str_idx - sl_str; /* The matched string by the sub expression match with the substring at the back reference? */ if (sl_str_diff > 0) { if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0)) { /* Not enough chars for a successful match. */ if (bkref_str_off + sl_str_diff > mctx->input.len) break; err = clean_state_log_if_needed (mctx, bkref_str_off + sl_str_diff); if (BE (err != REG_NOERROR, 0)) return err; buf = (const char *) re_string_get_buffer (&mctx->input); } if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) break; /* We don't need to search this sub expression any more. */ } bkref_str_off += sl_str_diff; sl_str += sl_str_diff; err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, bkref_str_idx); /* Reload buf, since the preceding call might have reallocated the buffer. */ buf = (const char *) re_string_get_buffer (&mctx->input); if (err == REG_NOMATCH) continue; if (BE (err != REG_NOERROR, 0)) return err; } if (sub_last_idx < sub_top->nlasts) continue; if (sub_last_idx > 0) ++sl_str; /* Then, search for the other last nodes of the sub expression. */ for (; sl_str <= bkref_str_idx; ++sl_str) { int cls_node, sl_str_off; const re_node_set *nodes; sl_str_off = sl_str - sub_top->str_idx; /* The matched string by the sub expression match with the substring at the back reference? */ if (sl_str_off > 0) { if (BE (bkref_str_off >= mctx->input.valid_len, 0)) { /* If we are at the end of the input, we cannot match. */ if (bkref_str_off >= mctx->input.len) break; err = extend_buffers (mctx); if (BE (err != REG_NOERROR, 0)) return err; buf = (const char *) re_string_get_buffer (&mctx->input); } if (buf [bkref_str_off++] != buf[sl_str - 1]) break; /* We don't need to search this sub expression any more. */ } if (mctx->state_log[sl_str] == NULL) continue; /* Does this state have a ')' of the sub expression? */ nodes = &mctx->state_log[sl_str]->nodes; cls_node = find_subexp_node (dfa, nodes, subexp_num, OP_CLOSE_SUBEXP); if (cls_node == -1) continue; /* No. */ if (sub_top->path == NULL) { sub_top->path = calloc (sizeof (state_array_t), sl_str - sub_top->str_idx + 1); if (sub_top->path == NULL) return REG_ESPACE; } /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node in the current context? */ err = check_arrival (mctx, sub_top->path, sub_top->node, sub_top->str_idx, cls_node, sl_str, OP_CLOSE_SUBEXP); if (err == REG_NOMATCH) continue; if (BE (err != REG_NOERROR, 0)) return err; sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); if (BE (sub_last == NULL, 0)) return REG_ESPACE; err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, bkref_str_idx); if (err == REG_NOMATCH) continue; } } return REG_NOERROR; } /* Helper functions for get_subexp(). */ /* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. If it can arrive, register the sub expression expressed with SUB_TOP and SUB_LAST. */ static reg_errcode_t get_subexp_sub (mctx, sub_top, sub_last, bkref_node, bkref_str) re_match_context_t *mctx; const re_sub_match_top_t *sub_top; re_sub_match_last_t *sub_last; int bkref_node, bkref_str; { reg_errcode_t err; int to_idx; /* Can the subexpression arrive the back reference? */ err = check_arrival (mctx, &sub_last->path, sub_last->node, sub_last->str_idx, bkref_node, bkref_str, OP_OPEN_SUBEXP); if (err != REG_NOERROR) return err; err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, sub_last->str_idx); if (BE (err != REG_NOERROR, 0)) return err; to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; return clean_state_log_if_needed (mctx, to_idx); } /* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. Search '(' if FL_OPEN, or search ')' otherwise. TODO: This function isn't efficient... Because there might be more than one nodes whose types are OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all nodes. E.g. RE: (a){2} */ static int find_subexp_node (dfa, nodes, subexp_idx, type) const re_dfa_t *dfa; const re_node_set *nodes; int subexp_idx, type; { int cls_idx; for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) { int cls_node = nodes->elems[cls_idx]; const re_token_t *node = dfa->nodes + cls_node; if (node->type == type && node->opr.idx == subexp_idx) return cls_node; } return -1; } /* Check whether the node TOP_NODE at TOP_STR can arrive to the node LAST_NODE at LAST_STR. We record the path onto PATH since it will be heavily reused. Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ static reg_errcode_t check_arrival (mctx, path, top_node, top_str, last_node, last_str, type) re_match_context_t *mctx; state_array_t *path; int top_node, top_str, last_node, last_str, type; { re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int subexp_num, backup_cur_idx, str_idx, null_cnt; re_dfastate_t *cur_state = NULL; re_node_set *cur_nodes, next_nodes; re_dfastate_t **backup_state_log; unsigned int context; subexp_num = dfa->nodes[top_node].opr.idx; /* Extend the buffer if we need. */ if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0)) { re_dfastate_t **new_array; int old_alloc = path->alloc; path->alloc += last_str + mctx->max_mb_elem_len + 1; new_array = re_realloc (path->array, re_dfastate_t *, path->alloc); if (new_array == NULL) { path->alloc = old_alloc; return REG_ESPACE; } path->array = new_array; memset (new_array + old_alloc, '\0', sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); } str_idx = path->next_idx == 0 ? top_str : path->next_idx; /* Temporary modify MCTX. */ backup_state_log = mctx->state_log; backup_cur_idx = mctx->input.cur_idx; mctx->state_log = path->array; mctx->input.cur_idx = str_idx; /* Setup initial node set. */ context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); if (str_idx == top_str) { err = re_node_set_init_1 (&next_nodes, top_node); if (BE (err != REG_NOERROR, 0)) return err; err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } else { cur_state = mctx->state_log[str_idx]; if (cur_state && cur_state->has_backref) { err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); if (BE ( err != REG_NOERROR, 0)) return err; } else re_node_set_init_empty (&next_nodes); } if (str_idx == top_str || (cur_state && cur_state->has_backref)) { if (next_nodes.nelem) { err = expand_bkref_cache (mctx, &next_nodes, str_idx, subexp_num, type); if (BE ( err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); if (BE (cur_state == NULL && err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } mctx->state_log[str_idx] = cur_state; } for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) { re_node_set_empty (&next_nodes); if (mctx->state_log[str_idx + 1]) { err = re_node_set_merge (&next_nodes, &mctx->state_log[str_idx + 1]->nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } if (cur_state) { err = check_arrival_add_next_nodes (mctx, str_idx, &cur_state->non_eps_nodes, &next_nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } ++str_idx; if (next_nodes.nelem) { err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } err = expand_bkref_cache (mctx, &next_nodes, str_idx, subexp_num, type); if (BE ( err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } } context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); if (BE (cur_state == NULL && err != REG_NOERROR, 0)) { re_node_set_free (&next_nodes); return err; } mctx->state_log[str_idx] = cur_state; null_cnt = cur_state == NULL ? null_cnt + 1 : 0; } re_node_set_free (&next_nodes); cur_nodes = (mctx->state_log[last_str] == NULL ? NULL : &mctx->state_log[last_str]->nodes); path->next_idx = str_idx; /* Fix MCTX. */ mctx->state_log = backup_state_log; mctx->input.cur_idx = backup_cur_idx; /* Then check the current node set has the node LAST_NODE. */ if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) return REG_NOERROR; return REG_NOMATCH; } /* Helper functions for check_arrival. */ /* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them to NEXT_NODES. TODO: This function is similar to the functions transit_state*(), however this function has many additional works. Can't we unify them? */ static reg_errcode_t check_arrival_add_next_nodes (mctx, str_idx, cur_nodes, next_nodes) re_match_context_t *mctx; int str_idx; re_node_set *cur_nodes, *next_nodes; { re_dfa_t *const dfa = mctx->dfa; int result; int cur_idx; reg_errcode_t err; re_node_set union_set; re_node_set_init_empty (&union_set); for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) { int naccepted = 0; int cur_node = cur_nodes->elems[cur_idx]; #if defined DEBUG || defined RE_ENABLE_I18N re_token_type_t type = dfa->nodes[cur_node].type; #endif #ifdef DEBUG assert (!IS_EPSILON_NODE (type)); #endif #ifdef RE_ENABLE_I18N /* If the node may accept `multi byte'. */ if (ACCEPT_MB_NODE (type)) { naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, str_idx); if (naccepted > 1) { re_dfastate_t *dest_state; int next_node = dfa->nexts[cur_node]; int next_idx = str_idx + naccepted; dest_state = mctx->state_log[next_idx]; re_node_set_empty (&union_set); if (dest_state) { err = re_node_set_merge (&union_set, &dest_state->nodes); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&union_set); return err; } } result = re_node_set_insert (&union_set, next_node); if (BE (result < 0, 0)) { re_node_set_free (&union_set); return REG_ESPACE; } mctx->state_log[next_idx] = re_acquire_state (&err, dfa, &union_set); if (BE (mctx->state_log[next_idx] == NULL && err != REG_NOERROR, 0)) { re_node_set_free (&union_set); return err; } } } #endif /* RE_ENABLE_I18N */ if (naccepted || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) { result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); if (BE (result < 0, 0)) { re_node_set_free (&union_set); return REG_ESPACE; } } } re_node_set_free (&union_set); return REG_NOERROR; } /* For all the nodes in CUR_NODES, add the epsilon closures of them to CUR_NODES, however exclude the nodes which are: - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. */ static reg_errcode_t check_arrival_expand_ecl (dfa, cur_nodes, ex_subexp, type) re_dfa_t *dfa; re_node_set *cur_nodes; int ex_subexp, type; { reg_errcode_t err; int idx, outside_node; re_node_set new_nodes; #ifdef DEBUG assert (cur_nodes->nelem); #endif err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); if (BE (err != REG_NOERROR, 0)) return err; /* Create a new node set NEW_NODES with the nodes which are epsilon closures of the node in CUR_NODES. */ for (idx = 0; idx < cur_nodes->nelem; ++idx) { int cur_node = cur_nodes->elems[idx]; re_node_set *eclosure = dfa->eclosures + cur_node; outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); if (outside_node == -1) { /* There are no problematic nodes, just merge them. */ err = re_node_set_merge (&new_nodes, eclosure); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&new_nodes); return err; } } else { /* There are problematic nodes, re-calculate incrementally. */ err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, ex_subexp, type); if (BE (err != REG_NOERROR, 0)) { re_node_set_free (&new_nodes); return err; } } } re_node_set_free (cur_nodes); *cur_nodes = new_nodes; return REG_NOERROR; } /* Helper function for check_arrival_expand_ecl. Check incrementally the epsilon closure of TARGET, and if it isn't problematic append it to DST_NODES. */ static reg_errcode_t check_arrival_expand_ecl_sub (dfa, dst_nodes, target, ex_subexp, type) re_dfa_t *dfa; int target, ex_subexp, type; re_node_set *dst_nodes; { int cur_node; for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) { int err; if (dfa->nodes[cur_node].type == type && dfa->nodes[cur_node].opr.idx == ex_subexp) { if (type == OP_CLOSE_SUBEXP) { err = re_node_set_insert (dst_nodes, cur_node); if (BE (err == -1, 0)) return REG_ESPACE; } break; } err = re_node_set_insert (dst_nodes, cur_node); if (BE (err == -1, 0)) return REG_ESPACE; if (dfa->edests[cur_node].nelem == 0) break; if (dfa->edests[cur_node].nelem == 2) { err = check_arrival_expand_ecl_sub (dfa, dst_nodes, dfa->edests[cur_node].elems[1], ex_subexp, type); if (BE (err != REG_NOERROR, 0)) return err; } cur_node = dfa->edests[cur_node].elems[0]; } return REG_NOERROR; } /* For all the back references in the current state, calculate the destination of the back references by the appropriate entry in MCTX->BKREF_ENTS. */ static reg_errcode_t expand_bkref_cache (mctx, cur_nodes, cur_str, subexp_num, type) re_match_context_t *mctx; int cur_str, subexp_num, type; re_node_set *cur_nodes; { re_dfa_t *const dfa = mctx->dfa; reg_errcode_t err; int cache_idx_start = search_cur_bkref_entry (mctx, cur_str); struct re_backref_cache_entry *ent; if (cache_idx_start == -1) return REG_NOERROR; restart: ent = mctx->bkref_ents + cache_idx_start; do { int to_idx, next_node; /* Is this entry ENT is appropriate? */ if (!re_node_set_contains (cur_nodes, ent->node)) continue; /* No. */ to_idx = cur_str + ent->subexp_to - ent->subexp_from; /* Calculate the destination of the back reference, and append it to MCTX->STATE_LOG. */ if (to_idx == cur_str) { /* The backreference did epsilon transit, we must re-check all the node in the current state. */ re_node_set new_dests; reg_errcode_t err2, err3; next_node = dfa->edests[ent->node].elems[0]; if (re_node_set_contains (cur_nodes, next_node)) continue; err = re_node_set_init_1 (&new_dests, next_node); err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); err3 = re_node_set_merge (cur_nodes, &new_dests); re_node_set_free (&new_dests); if (BE (err != REG_NOERROR || err2 != REG_NOERROR || err3 != REG_NOERROR, 0)) { err = (err != REG_NOERROR ? err : (err2 != REG_NOERROR ? err2 : err3)); return err; } /* TODO: It is still inefficient... */ goto restart; } else { re_node_set union_set; next_node = dfa->nexts[ent->node]; if (mctx->state_log[to_idx]) { int ret; if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, next_node)) continue; err = re_node_set_init_copy (&union_set, &mctx->state_log[to_idx]->nodes); ret = re_node_set_insert (&union_set, next_node); if (BE (err != REG_NOERROR || ret < 0, 0)) { re_node_set_free (&union_set); err = err != REG_NOERROR ? err : REG_ESPACE; return err; } } else { err = re_node_set_init_1 (&union_set, next_node); if (BE (err != REG_NOERROR, 0)) return err; } mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); re_node_set_free (&union_set); if (BE (mctx->state_log[to_idx] == NULL && err != REG_NOERROR, 0)) return err; } } while (ent++->more); return REG_NOERROR; } /* Build transition table for the state. Return the new table if succeeded, otherwise return NULL. */ static re_dfastate_t ** build_trtable (dfa, state) re_dfa_t *dfa; re_dfastate_t *state; { reg_errcode_t err; int i, j, ch; unsigned int elem, mask; int dests_node_malloced = 0, dest_states_malloced = 0; int ndests; /* Number of the destination states from `state'. */ re_dfastate_t **trtable; re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; re_node_set follows, *dests_node; bitset *dests_ch; bitset acceptable; /* We build DFA states which corresponds to the destination nodes from `state'. `dests_node[i]' represents the nodes which i-th destination state contains, and `dests_ch[i]' represents the characters which i-th destination state accepts. */ #ifdef _LIBC if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX)) dests_node = (re_node_set *) alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX); else #endif { dests_node = (re_node_set *) malloc ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX); if (BE (dests_node == NULL, 0)) return NULL; dests_node_malloced = 1; } dests_ch = (bitset *) (dests_node + SBC_MAX); /* Initialize transiton table. */ state->word_trtable = 0; /* At first, group all nodes belonging to `state' into several destinations. */ ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); if (BE (ndests <= 0, 0)) { if (dests_node_malloced) free (dests_node); /* Return NULL in case of an error, trtable otherwise. */ if (ndests == 0) { state->trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);; return state->trtable; } return NULL; } err = re_node_set_alloc (&follows, ndests + 1); if (BE (err != REG_NOERROR, 0)) goto out_free; #ifdef _LIBC if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX + ndests * 3 * sizeof (re_dfastate_t *))) dest_states = (re_dfastate_t **) alloca (ndests * 3 * sizeof (re_dfastate_t *)); else #endif { dest_states = (re_dfastate_t **) malloc (ndests * 3 * sizeof (re_dfastate_t *)); if (BE (dest_states == NULL, 0)) { out_free: if (dest_states_malloced) free (dest_states); re_node_set_free (&follows); for (i = 0; i < ndests; ++i) re_node_set_free (dests_node + i); if (dests_node_malloced) free (dests_node); return NULL; } dest_states_malloced = 1; } dest_states_word = dest_states + ndests; dest_states_nl = dest_states_word + ndests; bitset_empty (acceptable); /* Then build the states for all destinations. */ for (i = 0; i < ndests; ++i) { int next_node; re_node_set_empty (&follows); /* Merge the follows of this destination states. */ for (j = 0; j < dests_node[i].nelem; ++j) { next_node = dfa->nexts[dests_node[i].elems[j]]; if (next_node != -1) { err = re_node_set_merge (&follows, dfa->eclosures + next_node); if (BE (err != REG_NOERROR, 0)) goto out_free; } } dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0)) goto out_free; /* If the new state has context constraint, build appropriate states for these contexts. */ if (dest_states[i]->has_constraint) { dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, CONTEXT_WORD); if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) goto out_free; if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) state->word_trtable = 1; dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, CONTEXT_NEWLINE); if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0)) goto out_free; } else { dest_states_word[i] = dest_states[i]; dest_states_nl[i] = dest_states[i]; } bitset_merge (acceptable, dests_ch[i]); } if (!BE (state->word_trtable, 0)) { /* We don't care about whether the following character is a word character, or we are in a single-byte character set so we can discern by looking at the character code: allocate a 256-entry transition table. */ trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); if (BE (trtable == NULL, 0)) goto out_free; /* For all characters ch...: */ for (i = 0; i < BITSET_UINTS; ++i) for (ch = i * UINT_BITS, elem = acceptable[i], mask = 1; elem; mask <<= 1, elem >>= 1, ++ch) if (BE (elem & 1, 0)) { /* There must be exactly one destination which accepts character ch. See group_nodes_into_DFAstates. */ for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) ; /* j-th destination accepts the word character ch. */ if (dfa->word_char[i] & mask) trtable[ch] = dest_states_word[j]; else trtable[ch] = dest_states[j]; } } else { /* We care about whether the following character is a word character, and we are in a multi-byte character set: discern by looking at the character code: build two 256-entry transition tables, one starting at trtable[0] and one starting at trtable[SBC_MAX]. */ trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); if (BE (trtable == NULL, 0)) goto out_free; /* For all characters ch...: */ for (i = 0; i < BITSET_UINTS; ++i) for (ch = i * UINT_BITS, elem = acceptable[i], mask = 1; elem; mask <<= 1, elem >>= 1, ++ch) if (BE (elem & 1, 0)) { /* There must be exactly one destination which accepts character ch. See group_nodes_into_DFAstates. */ for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) ; /* j-th destination accepts the word character ch. */ trtable[ch] = dest_states[j]; trtable[ch + SBC_MAX] = dest_states_word[j]; } } /* new line */ if (bitset_contain (acceptable, NEWLINE_CHAR)) { /* The current state accepts newline character. */ for (j = 0; j < ndests; ++j) if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) { /* k-th destination accepts newline character. */ trtable[NEWLINE_CHAR] = dest_states_nl[j]; if (state->word_trtable) trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; /* There must be only one destination which accepts newline. See group_nodes_into_DFAstates. */ break; } } if (dest_states_malloced) free (dest_states); re_node_set_free (&follows); for (i = 0; i < ndests; ++i) re_node_set_free (dests_node + i); if (dests_node_malloced) free (dests_node); state->trtable = trtable; return trtable; } /* Group all nodes belonging to STATE into several destinations. Then for all destinations, set the nodes belonging to the destination to DESTS_NODE[i] and set the characters accepted by the destination to DEST_CH[i]. This function return the number of destinations. */ static int group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch) re_dfa_t *dfa; const re_dfastate_t *state; re_node_set *dests_node; bitset *dests_ch; { reg_errcode_t err; int result; int i, j, k; int ndests; /* Number of the destinations from `state'. */ bitset accepts; /* Characters a node can accept. */ const re_node_set *cur_nodes = &state->nodes; bitset_empty (accepts); ndests = 0; /* For all the nodes belonging to `state', */ for (i = 0; i < cur_nodes->nelem; ++i) { re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; re_token_type_t type = node->type; unsigned int constraint = node->constraint; /* Enumerate all single byte character this node can accept. */ if (type == CHARACTER) bitset_set (accepts, node->opr.c); else if (type == SIMPLE_BRACKET) { bitset_merge (accepts, node->opr.sbcset); } else if (type == OP_PERIOD) { #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) bitset_merge (accepts, dfa->sb_char); else #endif bitset_set_all (accepts); if (!(dfa->syntax & RE_DOT_NEWLINE)) bitset_clear (accepts, '\n'); if (dfa->syntax & RE_DOT_NOT_NULL) bitset_clear (accepts, '\0'); } #ifdef RE_ENABLE_I18N else if (type == OP_UTF8_PERIOD) { memset (accepts, 255, sizeof (unsigned int) * BITSET_UINTS / 2); if (!(dfa->syntax & RE_DOT_NEWLINE)) bitset_clear (accepts, '\n'); if (dfa->syntax & RE_DOT_NOT_NULL) bitset_clear (accepts, '\0'); } #endif else continue; /* Check the `accepts' and sift the characters which are not match it the context. */ if (constraint) { if (constraint & NEXT_NEWLINE_CONSTRAINT) { int accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); bitset_empty (accepts); if (accepts_newline) bitset_set (accepts, NEWLINE_CHAR); else continue; } if (constraint & NEXT_ENDBUF_CONSTRAINT) { bitset_empty (accepts); continue; } if (constraint & NEXT_WORD_CONSTRAINT) { unsigned int any_set = 0; if (type == CHARACTER && !node->word_char) { bitset_empty (accepts); continue; } #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) for (j = 0; j < BITSET_UINTS; ++j) any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); else #endif for (j = 0; j < BITSET_UINTS; ++j) any_set |= (accepts[j] &= dfa->word_char[j]); if (!any_set) continue; } if (constraint & NEXT_NOTWORD_CONSTRAINT) { unsigned int any_set = 0; if (type == CHARACTER && node->word_char) { bitset_empty (accepts); continue; } #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) for (j = 0; j < BITSET_UINTS; ++j) any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); else #endif for (j = 0; j < BITSET_UINTS; ++j) any_set |= (accepts[j] &= ~dfa->word_char[j]); if (!any_set) continue; } } /* Then divide `accepts' into DFA states, or create a new state. Above, we make sure that accepts is not empty. */ for (j = 0; j < ndests; ++j) { bitset intersec; /* Intersection sets, see below. */ bitset remains; /* Flags, see below. */ int has_intersec, not_subset, not_consumed; /* Optimization, skip if this state doesn't accept the character. */ if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) continue; /* Enumerate the intersection set of this state and `accepts'. */ has_intersec = 0; for (k = 0; k < BITSET_UINTS; ++k) has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; /* And skip if the intersection set is empty. */ if (!has_intersec) continue; /* Then check if this state is a subset of `accepts'. */ not_subset = not_consumed = 0; for (k = 0; k < BITSET_UINTS; ++k) { not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; } /* If this state isn't a subset of `accepts', create a new group state, which has the `remains'. */ if (not_subset) { bitset_copy (dests_ch[ndests], remains); bitset_copy (dests_ch[j], intersec); err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); if (BE (err != REG_NOERROR, 0)) goto error_return; ++ndests; } /* Put the position in the current group. */ result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); if (BE (result < 0, 0)) goto error_return; /* If all characters are consumed, go to next node. */ if (!not_consumed) break; } /* Some characters remain, create a new group. */ if (j == ndests) { bitset_copy (dests_ch[ndests], accepts); err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); if (BE (err != REG_NOERROR, 0)) goto error_return; ++ndests; bitset_empty (accepts); } } return ndests; error_return: for (j = 0; j < ndests; ++j) re_node_set_free (dests_node + j); return -1; } #ifdef RE_ENABLE_I18N /* Check how many bytes the node `dfa->nodes[node_idx]' accepts. Return the number of the bytes the node accepts. STR_IDX is the current index of the input string. This function handles the nodes which can accept one character, or one collating element like '.', '[a-z]', opposite to the other nodes can only accept one byte. */ static int check_node_accept_bytes (dfa, node_idx, input, str_idx) re_dfa_t *dfa; int node_idx, str_idx; const re_string_t *input; { const re_token_t *node = dfa->nodes + node_idx; int char_len, elem_len; int i; if (BE (node->type == OP_UTF8_PERIOD, 0)) { unsigned char c = re_string_byte_at (input, str_idx), d; if (BE (c < 0xc2, 1)) return 0; if (str_idx + 2 > input->len) return 0; d = re_string_byte_at (input, str_idx + 1); if (c < 0xe0) return (d < 0x80 || d > 0xbf) ? 0 : 2; else if (c < 0xf0) { char_len = 3; if (c == 0xe0 && d < 0xa0) return 0; } else if (c < 0xf8) { char_len = 4; if (c == 0xf0 && d < 0x90) return 0; } else if (c < 0xfc) { char_len = 5; if (c == 0xf8 && d < 0x88) return 0; } else if (c < 0xfe) { char_len = 6; if (c == 0xfc && d < 0x84) return 0; } else return 0; if (str_idx + char_len > input->len) return 0; for (i = 1; i < char_len; ++i) { d = re_string_byte_at (input, str_idx + i); if (d < 0x80 || d > 0xbf) return 0; } return char_len; } char_len = re_string_char_size_at (input, str_idx); if (node->type == OP_PERIOD) { if (char_len <= 1) return 0; /* FIXME: I don't think this if is needed, as both '\n' and '\0' are char_len == 1. */ /* '.' accepts any one character except the following two cases. */ if ((!(dfa->syntax & RE_DOT_NEWLINE) && re_string_byte_at (input, str_idx) == '\n') || ((dfa->syntax & RE_DOT_NOT_NULL) && re_string_byte_at (input, str_idx) == '\0')) return 0; return char_len; } elem_len = re_string_elem_size_at (input, str_idx); if ((elem_len <= 1 && char_len <= 1) || char_len == 0) return 0; if (node->type == COMPLEX_BRACKET) { const re_charset_t *cset = node->opr.mbcset; # ifdef _LIBC const unsigned char *pin = ((char *) re_string_get_buffer (input) + str_idx); int j; uint32_t nrules; # endif /* _LIBC */ int match_len = 0; wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) ? re_string_wchar_at (input, str_idx) : 0); /* match with multibyte character? */ for (i = 0; i < cset->nmbchars; ++i) if (wc == cset->mbchars[i]) { match_len = char_len; goto check_node_accept_bytes_match; } /* match with character_class? */ for (i = 0; i < cset->nchar_classes; ++i) { wctype_t wt = cset->char_classes[i]; if (__iswctype (wc, wt)) { match_len = char_len; goto check_node_accept_bytes_match; } } # ifdef _LIBC nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) { unsigned int in_collseq = 0; const int32_t *table, *indirect; const unsigned char *weights, *extra; const char *collseqwc; int32_t idx; /* This #include defines a local function! */ # include /* match with collating_symbol? */ if (cset->ncoll_syms) extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); for (i = 0; i < cset->ncoll_syms; ++i) { const unsigned char *coll_sym = extra + cset->coll_syms[i]; /* Compare the length of input collating element and the length of current collating element. */ if (*coll_sym != elem_len) continue; /* Compare each bytes. */ for (j = 0; j < *coll_sym; j++) if (pin[j] != coll_sym[1 + j]) break; if (j == *coll_sym) { /* Match if every bytes is equal. */ match_len = j; goto check_node_accept_bytes_match; } } if (cset->nranges) { if (elem_len <= char_len) { collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); in_collseq = __collseq_table_lookup (collseqwc, wc); } else in_collseq = find_collation_sequence_value (pin, elem_len); } /* match with range expression? */ for (i = 0; i < cset->nranges; ++i) if (cset->range_starts[i] <= in_collseq && in_collseq <= cset->range_ends[i]) { match_len = elem_len; goto check_node_accept_bytes_match; } /* match with equivalence_class? */ if (cset->nequiv_classes) { const unsigned char *cp = pin; table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); idx = findidx (&cp); if (idx > 0) for (i = 0; i < cset->nequiv_classes; ++i) { int32_t equiv_class_idx = cset->equiv_classes[i]; size_t weight_len = weights[idx]; if (weight_len == weights[equiv_class_idx]) { int cnt = 0; while (cnt <= weight_len && (weights[equiv_class_idx + 1 + cnt] == weights[idx + 1 + cnt])) ++cnt; if (cnt > weight_len) { match_len = elem_len; goto check_node_accept_bytes_match; } } } } } else # endif /* _LIBC */ { /* match with range expression? */ #if __GNUC__ >= 2 wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; #else wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; cmp_buf[2] = wc; #endif for (i = 0; i < cset->nranges; ++i) { cmp_buf[0] = cset->range_starts[i]; cmp_buf[4] = cset->range_ends[i]; if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) { match_len = char_len; goto check_node_accept_bytes_match; } } } check_node_accept_bytes_match: if (!cset->non_match) return match_len; else { if (match_len > 0) return 0; else return (elem_len > char_len) ? elem_len : char_len; } } return 0; } # ifdef _LIBC static unsigned int find_collation_sequence_value (mbs, mbs_len) const unsigned char *mbs; size_t mbs_len; { uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules == 0) { if (mbs_len == 1) { /* No valid character. Match it as a single byte character. */ const unsigned char *collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); return collseq[mbs[0]]; } return UINT_MAX; } else { int32_t idx; const unsigned char *extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); int32_t extrasize = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; for (idx = 0; idx < extrasize;) { int mbs_cnt, found = 0; int32_t elem_mbs_len; /* Skip the name of collating element name. */ idx = idx + extra[idx] + 1; elem_mbs_len = extra[idx++]; if (mbs_len == elem_mbs_len) { for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) break; if (mbs_cnt == elem_mbs_len) /* Found the entry. */ found = 1; } /* Skip the byte sequence of the collating element. */ idx += elem_mbs_len; /* Adjust for the alignment. */ idx = (idx + 3) & ~3; /* Skip the collation sequence value. */ idx += sizeof (uint32_t); /* Skip the wide char sequence of the collating element. */ idx = idx + sizeof (uint32_t) * (extra[idx] + 1); /* If we found the entry, return the sequence value. */ if (found) return *(uint32_t *) (extra + idx); /* Skip the collation sequence value. */ idx += sizeof (uint32_t); } return UINT_MAX; } } # endif /* _LIBC */ #endif /* RE_ENABLE_I18N */ /* Check whether the node accepts the byte which is IDX-th byte of the INPUT. */ static int check_node_accept (mctx, node, idx) const re_match_context_t *mctx; const re_token_t *node; int idx; { unsigned char ch; ch = re_string_byte_at (&mctx->input, idx); switch (node->type) { case CHARACTER: if (node->opr.c != ch) return 0; break; case SIMPLE_BRACKET: if (!bitset_contain (node->opr.sbcset, ch)) return 0; break; #ifdef RE_ENABLE_I18N case OP_UTF8_PERIOD: if (ch >= 0x80) return 0; /* FALLTHROUGH */ #endif case OP_PERIOD: if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) return 0; break; default: return 0; } if (node->constraint) { /* The node has constraints. Check whether the current context satisfies the constraints. */ unsigned int context = re_string_context_at (&mctx->input, idx, mctx->eflags); if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) return 0; } return 1; } /* Extend the buffers, if the buffers have run out. */ static reg_errcode_t extend_buffers (mctx) re_match_context_t *mctx; { reg_errcode_t ret; re_string_t *pstr = &mctx->input; /* Double the lengthes of the buffers. */ ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); if (BE (ret != REG_NOERROR, 0)) return ret; if (mctx->state_log != NULL) { /* And double the length of state_log. */ /* XXX We have no indication of the size of this buffer. If this allocation fail we have no indication that the state_log array does not have the right size. */ re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, pstr->bufs_len + 1); if (BE (new_array == NULL, 0)) return REG_ESPACE; mctx->state_log = new_array; } /* Then reconstruct the buffers. */ if (pstr->icase) { #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { ret = build_wcs_upper_buffer (pstr); if (BE (ret != REG_NOERROR, 0)) return ret; } else #endif /* RE_ENABLE_I18N */ build_upper_buffer (pstr); } else { #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) build_wcs_buffer (pstr); else #endif /* RE_ENABLE_I18N */ { if (pstr->trans != NULL) re_string_translate_buffer (pstr); } } return REG_NOERROR; } /* Functions for matching context. */ /* Initialize MCTX. */ static reg_errcode_t match_ctx_init (mctx, eflags, n) re_match_context_t *mctx; int eflags, n; { mctx->eflags = eflags; mctx->match_last = -1; if (n > 0) { mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0)) return REG_ESPACE; } /* Already zero-ed by the caller. else mctx->bkref_ents = NULL; mctx->nbkref_ents = 0; mctx->nsub_tops = 0; */ mctx->abkref_ents = n; mctx->max_mb_elem_len = 1; mctx->asub_tops = n; return REG_NOERROR; } /* Clean the entries which depend on the current input in MCTX. This function must be invoked when the matcher changes the start index of the input, or changes the input string. */ static void match_ctx_clean (mctx) re_match_context_t *mctx; { int st_idx; for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) { int sl_idx; re_sub_match_top_t *top = mctx->sub_tops[st_idx]; for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) { re_sub_match_last_t *last = top->lasts[sl_idx]; re_free (last->path.array); re_free (last); } re_free (top->lasts); if (top->path) { re_free (top->path->array); re_free (top->path); } free (top); } mctx->nsub_tops = 0; mctx->nbkref_ents = 0; } /* Free all the memory associated with MCTX. */ static void match_ctx_free (mctx) re_match_context_t *mctx; { /* First, free all the memory associated with MCTX->SUB_TOPS. */ match_ctx_clean (mctx); re_free (mctx->sub_tops); re_free (mctx->bkref_ents); } /* Add a new backreference entry to MCTX. Note that we assume that caller never call this function with duplicate entry, and call with STR_IDX which isn't smaller than any existing entry. */ static reg_errcode_t match_ctx_add_entry (mctx, node, str_idx, from, to) re_match_context_t *mctx; int node, str_idx, from, to; { if (mctx->nbkref_ents >= mctx->abkref_ents) { struct re_backref_cache_entry* new_entry; new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, mctx->abkref_ents * 2); if (BE (new_entry == NULL, 0)) { re_free (mctx->bkref_ents); return REG_ESPACE; } mctx->bkref_ents = new_entry; memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); mctx->abkref_ents *= 2; } if (mctx->nbkref_ents > 0 && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; mctx->bkref_ents[mctx->nbkref_ents].node = node; mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; /* This is a cache that saves negative results of check_dst_limits_calc_pos. If bit N is clear, means that this entry won't epsilon-transition to an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If it is set, check_dst_limits_calc_pos_1 will recurse and try to find one such node. A backreference does not epsilon-transition unless it is empty, so set to all zeros if FROM != TO. */ mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map = (from == to ? ~0 : 0); mctx->bkref_ents[mctx->nbkref_ents++].more = 0; if (mctx->max_mb_elem_len < to - from) mctx->max_mb_elem_len = to - from; return REG_NOERROR; } /* Search for the first entry which has the same str_idx, or -1 if none is found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ static int search_cur_bkref_entry (mctx, str_idx) re_match_context_t *mctx; int str_idx; { int left, right, mid, last; last = right = mctx->nbkref_ents; for (left = 0; left < right;) { mid = (left + right) / 2; if (mctx->bkref_ents[mid].str_idx < str_idx) left = mid + 1; else right = mid; } if (left < last && mctx->bkref_ents[left].str_idx == str_idx) return left; else return -1; } /* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches at STR_IDX. */ static reg_errcode_t match_ctx_add_subtop (mctx, node, str_idx) re_match_context_t *mctx; int node, str_idx; { #ifdef DEBUG assert (mctx->sub_tops != NULL); assert (mctx->asub_tops > 0); #endif if (BE (mctx->nsub_tops == mctx->asub_tops, 0)) { int new_asub_tops = mctx->asub_tops * 2; re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, re_sub_match_top_t *, new_asub_tops); if (BE (new_array == NULL, 0)) return REG_ESPACE; mctx->sub_tops = new_array; mctx->asub_tops = new_asub_tops; } mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0)) return REG_ESPACE; mctx->sub_tops[mctx->nsub_tops]->node = node; mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; return REG_NOERROR; } /* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ static re_sub_match_last_t * match_ctx_add_sublast (subtop, node, str_idx) re_sub_match_top_t *subtop; int node, str_idx; { re_sub_match_last_t *new_entry; if (BE (subtop->nlasts == subtop->alasts, 0)) { int new_alasts = 2 * subtop->alasts + 1; re_sub_match_last_t **new_array = re_realloc (subtop->lasts, re_sub_match_last_t *, new_alasts); if (BE (new_array == NULL, 0)) return NULL; subtop->lasts = new_array; subtop->alasts = new_alasts; } new_entry = calloc (1, sizeof (re_sub_match_last_t)); if (BE (new_entry != NULL, 1)) { subtop->lasts[subtop->nlasts] = new_entry; new_entry->node = node; new_entry->str_idx = str_idx; ++subtop->nlasts; } return new_entry; } static void sift_ctx_init (sctx, sifted_sts, limited_sts, last_node, last_str_idx) re_sift_context_t *sctx; re_dfastate_t **sifted_sts, **limited_sts; int last_node, last_str_idx; { sctx->sifted_states = sifted_sts; sctx->limited_states = limited_sts; sctx->last_node = last_node; sctx->last_str_idx = last_str_idx; re_node_set_init_empty (&sctx->limits); } uqm-0.6.2/sc2/src/regex/regex.c0000600000175000017500000000655310543202107014660 0ustar joeyjoey/* Extended regular expression matching and search library. Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "port.h" #ifdef _AIX #pragma alloca #else # ifndef allocax /* predefined by HP cc +Olibcalls */ # ifdef __GNUC__ # define alloca(size) __builtin_alloca (size) # else # if HAVE_ALLOCA_H # include # else # ifdef __hpux void *alloca (); # else # if !defined __OS2__ && !defined WIN32 char *alloca (); # else # include /* OS/2 defines alloca in here */ # endif # endif # endif # endif # endif #endif #ifdef _LIBC /* We have to keep the namespace clean. */ # define regfree(preg) __regfree (preg) # define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) # define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) # define regerror(errcode, preg, errbuf, errbuf_size) \ __regerror(errcode, preg, errbuf, errbuf_size) # define re_set_registers(bu, re, nu, st, en) \ __re_set_registers (bu, re, nu, st, en) # define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) # define re_match(bufp, string, size, pos, regs) \ __re_match (bufp, string, size, pos, regs) # define re_search(bufp, string, size, startpos, range, regs) \ __re_search (bufp, string, size, startpos, range, regs) # define re_compile_pattern(pattern, length, bufp) \ __re_compile_pattern (pattern, length, bufp) # define re_set_syntax(syntax) __re_set_syntax (syntax) # define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) # define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) # include "../locale/localeinfo.h" #endif /* POSIX says that must be included (by the caller) before . */ #include /* On some systems, limits.h sets RE_DUP_MAX to a lower value than GNU regex allows. Include it before , which correctly #undefs RE_DUP_MAX and sets it to the right value. */ #include #include #include "regex_internal.h" #include "regex_internal.ci" #include "regcomp.ci" #include "regexec.ci" /* Binary backward compatibility. */ #if _LIBC # include # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") int re_max_failures = 2000; # endif #endif uqm-0.6.2/sc2/src/regex/regcomp.ci0000600000175000017500000033322510543202107015352 0ustar joeyjoey/* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, int length, reg_syntax_t syntax); static void re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, char *fastmap); static reg_errcode_t init_dfa (re_dfa_t *dfa, int pat_len); static void init_word_char (re_dfa_t *dfa); #ifdef RE_ENABLE_I18N static void free_charset (re_charset_t *cset); #endif /* RE_ENABLE_I18N */ static void free_workarea_compile (regex_t *preg); static reg_errcode_t create_initial_state (re_dfa_t *dfa); #ifdef RE_ENABLE_I18N static void optimize_utf8 (re_dfa_t *dfa); #endif struct subexp_optimize { re_dfa_t *dfa; re_token_t *nodes; int no_sub, re_nsub; }; static bin_tree_t *optimize_subexps (struct subexp_optimize *so, bin_tree_t *node, int sidx, int depth); static reg_errcode_t analyze (re_dfa_t *dfa); static reg_errcode_t analyze_tree (re_dfa_t *dfa, bin_tree_t *node); static void calc_first (re_dfa_t *dfa, bin_tree_t *node); static void calc_next (re_dfa_t *dfa, bin_tree_t *node); static void calc_epsdest (re_dfa_t *dfa, bin_tree_t *node); static reg_errcode_t duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node, int root_node, unsigned int constraint); static reg_errcode_t duplicate_node (int *new_idx, re_dfa_t *dfa, int org_idx, unsigned int constraint); static int search_duplicated_node (re_dfa_t *dfa, int org_node, unsigned int constraint); static reg_errcode_t calc_eclosure (re_dfa_t *dfa); static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root); static void calc_inveclosure (re_dfa_t *dfa); static int fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax); static void fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax); static int peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax); static int peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax); static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, reg_errcode_t *err); static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, reg_syntax_t syntax, int nest, reg_errcode_t *err); static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err); static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err); static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token, int token_len, re_dfa_t *dfa, reg_syntax_t syntax, int accept_hyphen); static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token); #ifndef _LIBC # ifdef RE_ENABLE_I18N static reg_errcode_t build_range_exp (re_bitset_ptr_t sbcset, re_charset_t *mbcset, int *range_alloc, bracket_elem_t *start_elem, bracket_elem_t *end_elem); static reg_errcode_t build_collating_symbol (re_bitset_ptr_t sbcset, re_charset_t *mbcset, int *coll_sym_alloc, const unsigned char *name); # else /* not RE_ENABLE_I18N */ static reg_errcode_t build_range_exp (re_bitset_ptr_t sbcset, bracket_elem_t *start_elem, bracket_elem_t *end_elem); static reg_errcode_t build_collating_symbol (re_bitset_ptr_t sbcset, const unsigned char *name); # endif /* not RE_ENABLE_I18N */ #endif /* not _LIBC */ #ifdef RE_ENABLE_I18N static reg_errcode_t build_equiv_class (re_bitset_ptr_t sbcset, re_charset_t *mbcset, int *equiv_class_alloc, const unsigned char *name); static reg_errcode_t build_charclass (unsigned RE_TRANSLATE_TYPE trans, re_bitset_ptr_t sbcset, re_charset_t *mbcset, int *char_class_alloc, const unsigned char *class_name, reg_syntax_t syntax); #else /* not RE_ENABLE_I18N */ static reg_errcode_t build_equiv_class (re_bitset_ptr_t sbcset, const unsigned char *name); static reg_errcode_t build_charclass (unsigned RE_TRANSLATE_TYPE trans, re_bitset_ptr_t sbcset, const unsigned char *class_name, reg_syntax_t syntax); #endif /* not RE_ENABLE_I18N */ static bin_tree_t *build_charclass_op (re_dfa_t *dfa, unsigned RE_TRANSLATE_TYPE trans, const unsigned char *class_name, const unsigned char *extra, int non_match, reg_errcode_t *err); static bin_tree_t *create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, re_token_type_t type, int index); static bin_tree_t *re_dfa_add_tree_node (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, const re_token_t *token) __attribute ((noinline)); static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); static void mark_opt_subexp (const bin_tree_t *src, re_dfa_t *dfa); static void mark_opt_subexp_iter (const bin_tree_t *src, re_dfa_t *dfa, int idx); /* This table gives an error message for each of the error codes listed in regex.h. Obviously the order here has to be same as there. POSIX doesn't require that we do anything for REG_NOERROR, but why not be nice? */ const char __re_error_msgid[] attribute_hidden = { #define REG_NOERROR_IDX 0 gettext_noop ("Success") /* REG_NOERROR */ "\0" #define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") gettext_noop ("No match") /* REG_NOMATCH */ "\0" #define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") gettext_noop ("Invalid regular expression") /* REG_BADPAT */ "\0" #define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ "\0" #define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") gettext_noop ("Invalid character class name") /* REG_ECTYPE */ "\0" #define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") gettext_noop ("Trailing backslash") /* REG_EESCAPE */ "\0" #define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") gettext_noop ("Invalid back reference") /* REG_ESUBREG */ "\0" #define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ "\0" #define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ "\0" #define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") gettext_noop ("Unmatched \\{") /* REG_EBRACE */ "\0" #define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ "\0" #define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") gettext_noop ("Invalid range end") /* REG_ERANGE */ "\0" #define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") gettext_noop ("Memory exhausted") /* REG_ESPACE */ "\0" #define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ "\0" #define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") gettext_noop ("Premature end of regular expression") /* REG_EEND */ "\0" #define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") gettext_noop ("Regular expression too big") /* REG_ESIZE */ "\0" #define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ }; const size_t __re_error_msgid_idx[] attribute_hidden = { REG_NOERROR_IDX, REG_NOMATCH_IDX, REG_BADPAT_IDX, REG_ECOLLATE_IDX, REG_ECTYPE_IDX, REG_EESCAPE_IDX, REG_ESUBREG_IDX, REG_EBRACK_IDX, REG_EPAREN_IDX, REG_EBRACE_IDX, REG_BADBR_IDX, REG_ERANGE_IDX, REG_ESPACE_IDX, REG_BADRPT_IDX, REG_EEND_IDX, REG_ESIZE_IDX, REG_ERPAREN_IDX }; /* Entry points for GNU code. */ /* re_compile_pattern is the GNU regular expression compiler: it compiles PATTERN (of length LENGTH) and puts the result in BUFP. Returns 0 if the pattern was valid, otherwise an error string. Assumes the `allocated' (and perhaps `buffer') and `translate' fields are set in BUFP on entry. */ const char * re_compile_pattern (pattern, length, bufp) const char *pattern; size_t length; struct re_pattern_buffer *bufp; { reg_errcode_t ret; /* And GNU code determines whether or not to get register information by passing null for the REGS argument to re_match, etc., not by setting no_sub, unless RE_NO_SUB is set. */ bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); /* Match anchors at newline. */ bufp->newline_anchor = 1; ret = re_compile_internal (bufp, pattern, length, re_syntax_options); if (!ret) return NULL; return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); } #ifdef _LIBC weak_alias (__re_compile_pattern, re_compile_pattern) #endif /* Set by `re_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own syntax, so it can be changed between regex compilations. */ /* This has no initializer because initialized variables in Emacs become read-only after dumping. */ reg_syntax_t re_syntax_options; /* Specify the precise syntax of regexps for compilation. This provides for compatibility for various utilities which historically have different, incompatible syntaxes. The argument SYNTAX is a bit mask comprised of the various bits defined in regex.h. We return the old syntax. */ reg_syntax_t re_set_syntax (syntax) reg_syntax_t syntax; { reg_syntax_t ret = re_syntax_options; re_syntax_options = syntax; return ret; } #ifdef _LIBC weak_alias (__re_set_syntax, re_set_syntax) #endif int re_compile_fastmap (bufp) struct re_pattern_buffer *bufp; { re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; char *fastmap = bufp->fastmap; memset (fastmap, '\0', sizeof (char) * SBC_MAX); re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); if (dfa->init_state != dfa->init_state_word) re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); if (dfa->init_state != dfa->init_state_nl) re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); if (dfa->init_state != dfa->init_state_begbuf) re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); bufp->fastmap_accurate = 1; return 0; } #ifdef _LIBC weak_alias (__re_compile_fastmap, re_compile_fastmap) #endif static inline void __attribute ((always_inline)) re_set_fastmap (char *fastmap, int icase, int ch) { fastmap[ch] = 1; if (icase) fastmap[tolower (ch)] = 1; } /* Helper function for re_compile_fastmap. Compile fastmap for the initial_state INIT_STATE. */ static void re_compile_fastmap_iter (bufp, init_state, fastmap) regex_t *bufp; const re_dfastate_t *init_state; char *fastmap; { re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; int node_cnt; int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) { int node = init_state->nodes.elems[node_cnt]; re_token_type_t type = dfa->nodes[node].type; if (type == CHARACTER) { re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); #ifdef RE_ENABLE_I18N if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) { unsigned char *buf = alloca (dfa->mb_cur_max), *p; wchar_t wc; mbstate_t state; p = buf; *p++ = dfa->nodes[node].opr.c; while (++node < dfa->nodes_len && dfa->nodes[node].type == CHARACTER && dfa->nodes[node].mb_partial) *p++ = dfa->nodes[node].opr.c; memset (&state, 0, sizeof (state)); if (mbrtowc (&wc, (const char *) buf, p - buf, &state) == p - buf && __wcrtomb ((char *) buf, towlower (wc), &state) > 0) re_set_fastmap (fastmap, 0, buf[0]); } #endif } else if (type == SIMPLE_BRACKET) { int i, j, ch; for (i = 0, ch = 0; i < BITSET_UINTS; ++i) for (j = 0; j < UINT_BITS; ++j, ++ch) if (dfa->nodes[node].opr.sbcset[i] & (1 << j)) re_set_fastmap (fastmap, icase, ch); } #ifdef RE_ENABLE_I18N else if (type == COMPLEX_BRACKET) { int i; re_charset_t *cset = dfa->nodes[node].opr.mbcset; if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes || cset->nranges || cset->nchar_classes) { # ifdef _LIBC if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0) { /* In this case we want to catch the bytes which are the first byte of any collation elements. e.g. In da_DK, we want to catch 'a' since "aa" is a valid collation element, and don't catch 'b' since 'b' is the only collation element which starts from 'b'. */ int j, ch; const int32_t *table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); for (i = 0, ch = 0; i < BITSET_UINTS; ++i) for (j = 0; j < UINT_BITS; ++j, ++ch) if (table[ch] < 0) re_set_fastmap (fastmap, icase, ch); } # else if (dfa->mb_cur_max > 1) for (i = 0; i < SBC_MAX; ++i) if (__btowc (i) == WEOF) re_set_fastmap (fastmap, icase, i); # endif /* not _LIBC */ } for (i = 0; i < cset->nmbchars; ++i) { char buf[256]; mbstate_t state; memset (&state, '\0', sizeof (state)); __wcrtomb (buf, cset->mbchars[i], &state); re_set_fastmap (fastmap, icase, *(unsigned char *) buf); if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) { __wcrtomb (buf, towlower (cset->mbchars[i]), &state); re_set_fastmap (fastmap, 0, *(unsigned char *) buf); } } } #endif /* RE_ENABLE_I18N */ else if (type == OP_PERIOD #ifdef RE_ENABLE_I18N || type == OP_UTF8_PERIOD #endif /* RE_ENABLE_I18N */ || type == END_OF_RE) { memset (fastmap, '\1', sizeof (char) * SBC_MAX); if (type == END_OF_RE) bufp->can_be_null = 1; return; } } } /* Entry point for POSIX code. */ /* regcomp takes a regular expression as a string and compiles it. PREG is a regex_t *. We do not expect any fields to be initialized, since POSIX says we shouldn't. Thus, we set `buffer' to the compiled pattern; `used' to the length of the compiled pattern; `syntax' to RE_SYNTAX_POSIX_EXTENDED if the REG_EXTENDED bit in CFLAGS is set; otherwise, to RE_SYNTAX_POSIX_BASIC; `newline_anchor' to REG_NEWLINE being set in CFLAGS; `fastmap' to an allocated space for the fastmap; `fastmap_accurate' to zero; `re_nsub' to the number of subexpressions in PATTERN. PATTERN is the address of the pattern string. CFLAGS is a series of bits which affect compilation. If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we use POSIX basic syntax. If REG_NEWLINE is set, then . and [^...] don't match newline. Also, regexec will try a match beginning after every newline. If REG_ICASE is set, then we considers upper- and lowercase versions of letters to be equivalent when matching. If REG_NOSUB is set, then when PREG is passed to regexec, that routine will report only success or failure, and nothing about the registers. It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for the return codes and their meanings.) */ int regcomp (preg, pattern, cflags) regex_t *__restrict preg; const char *__restrict pattern; int cflags; { reg_errcode_t ret; reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC); preg->buffer = NULL; preg->allocated = 0; preg->used = 0; /* Try to allocate space for the fastmap. */ preg->fastmap = re_malloc (char, SBC_MAX); if (BE (preg->fastmap == NULL, 0)) return REG_ESPACE; syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; /* If REG_NEWLINE is set, newlines are treated differently. */ if (cflags & REG_NEWLINE) { /* REG_NEWLINE implies neither . nor [^...] match newline. */ syntax &= ~RE_DOT_NEWLINE; syntax |= RE_HAT_LISTS_NOT_NEWLINE; /* It also changes the matching behavior. */ preg->newline_anchor = 1; } else preg->newline_anchor = 0; preg->no_sub = !!(cflags & REG_NOSUB); preg->translate = NULL; ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); /* POSIX doesn't distinguish between an unmatched open-group and an unmatched close-group: both are REG_EPAREN. */ if (ret == REG_ERPAREN) ret = REG_EPAREN; /* We have already checked preg->fastmap != NULL. */ if (BE (ret == REG_NOERROR, 1)) /* Compute the fastmap now, since regexec cannot modify the pattern buffer. This function never fails in this implementation. */ (void) re_compile_fastmap (preg); else { /* Some error occurred while compiling the expression. */ re_free (preg->fastmap); preg->fastmap = NULL; } return (int) ret; } #ifdef _LIBC weak_alias (__regcomp, regcomp) #endif /* Returns a message corresponding to an error code, ERRCODE, returned from either regcomp or regexec. We don't use PREG here. */ size_t regerror (err_code, preg, errbuf, errbuf_size) int err_code; const regex_t *preg; char *errbuf; size_t errbuf_size; { const char *msg; size_t msg_size; if (BE (err_code < 0 || err_code >= (int) (sizeof (__re_error_msgid_idx) / sizeof (__re_error_msgid_idx[0])), 0)) /* Only error codes returned by the rest of the code should be passed to this routine. If we are given anything else, or if other regex code generates an invalid error code, then the program has a bug. Dump core so we can fix it. */ abort (); msg = gettext (__re_error_msgid + __re_error_msgid_idx[err_code]); msg_size = strlen (msg) + 1; /* Includes the null. */ if (BE (errbuf_size != 0, 1)) { if (BE (msg_size > errbuf_size, 0)) { #if defined HAVE_MEMPCPY || defined _LIBC *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0'; #else memcpy (errbuf, msg, errbuf_size - 1); errbuf[errbuf_size - 1] = 0; #endif } else memcpy (errbuf, msg, msg_size); } return msg_size; } #ifdef _LIBC weak_alias (__regerror, regerror) #endif #ifdef RE_ENABLE_I18N /* This static array is used for the map to single-byte characters when UTF-8 is used. Otherwise we would allocate memory just to initialize it the same all the time. UTF-8 is the preferred encoding so this is a worthwhile optimization. */ static const bitset utf8_sb_map = { /* Set the first 128 bits. */ # if UINT_MAX == 0xffffffff 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff # else # error "Add case for new unsigned int size" # endif }; #endif static void free_dfa_content (re_dfa_t *dfa) { int i, j; if (dfa->nodes) for (i = 0; i < dfa->nodes_len; ++i) { re_token_t *node = dfa->nodes + i; #ifdef RE_ENABLE_I18N if (node->type == COMPLEX_BRACKET && node->duplicated == 0) free_charset (node->opr.mbcset); else #endif /* RE_ENABLE_I18N */ if (node->type == SIMPLE_BRACKET && node->duplicated == 0) re_free (node->opr.sbcset); } re_free (dfa->nexts); for (i = 0; i < dfa->nodes_len; ++i) { if (dfa->eclosures != NULL) re_node_set_free (dfa->eclosures + i); if (dfa->inveclosures != NULL) re_node_set_free (dfa->inveclosures + i); if (dfa->edests != NULL) re_node_set_free (dfa->edests + i); } re_free (dfa->edests); re_free (dfa->eclosures); re_free (dfa->inveclosures); re_free (dfa->nodes); if (dfa->state_table) for (i = 0; i <= dfa->state_hash_mask; ++i) { struct re_state_table_entry *entry = dfa->state_table + i; for (j = 0; j < entry->num; ++j) { re_dfastate_t *state = entry->array[j]; free_state (state); } re_free (entry->array); } re_free (dfa->state_table); #ifdef RE_ENABLE_I18N if (dfa->sb_char != utf8_sb_map) re_free (dfa->sb_char); #endif re_free (dfa->subexp_map); #ifdef DEBUG re_free (dfa->re_str); #endif re_free (dfa); } /* Free dynamically allocated space used by PREG. */ void regfree (preg) regex_t *preg; { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; if (BE (dfa != NULL, 1)) free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; re_free (preg->fastmap); preg->fastmap = NULL; re_free (preg->translate); preg->translate = NULL; } #ifdef _LIBC weak_alias (__regfree, regfree) #endif /* Entry points compatible with 4.2 BSD regex library. We don't define them unless specifically requested. */ #if defined _REGEX_RE_COMP || defined _LIBC /* BSD has one and only one pattern buffer. */ static struct re_pattern_buffer re_comp_buf; char * # ifdef _LIBC /* Make these definitions weak in libc, so POSIX programs can redefine these names if they don't use our functions, and still use regcomp/regexec above without link errors. */ weak_function # endif re_comp (s) const char *s; { reg_errcode_t ret; char *fastmap; if (!s) { if (!re_comp_buf.buffer) return gettext ("No previous regular expression"); return 0; } if (re_comp_buf.buffer) { fastmap = re_comp_buf.fastmap; re_comp_buf.fastmap = NULL; __regfree (&re_comp_buf); memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); re_comp_buf.fastmap = fastmap; } if (re_comp_buf.fastmap == NULL) { re_comp_buf.fastmap = (char *) malloc (SBC_MAX); if (re_comp_buf.fastmap == NULL) return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) REG_ESPACE]); } /* Since `re_exec' always passes NULL for the `regs' argument, we don't need to initialize the pattern buffer fields which affect it. */ /* Match anchors at newlines. */ re_comp_buf.newline_anchor = 1; ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); if (!ret) return NULL; /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); } #ifdef _LIBC libc_freeres_fn (free_mem) { __regfree (&re_comp_buf); } #endif #endif /* _REGEX_RE_COMP */ /* Internal entry point. Compile the regular expression PATTERN, whose length is LENGTH. SYNTAX indicate regular expression's syntax. */ static reg_errcode_t re_compile_internal (preg, pattern, length, syntax) regex_t *preg; const char * pattern; int length; reg_syntax_t syntax; { reg_errcode_t err = REG_NOERROR; re_dfa_t *dfa; re_string_t regexp; /* Initialize the pattern buffer. */ preg->fastmap_accurate = 0; preg->syntax = syntax; preg->not_bol = preg->not_eol = 0; preg->used = 0; preg->re_nsub = 0; preg->can_be_null = 0; preg->regs_allocated = REGS_UNALLOCATED; /* Initialize the dfa. */ dfa = (re_dfa_t *) preg->buffer; if (BE (preg->allocated < sizeof (re_dfa_t), 0)) { /* If zero allocated, but buffer is non-null, try to realloc enough space. This loses if buffer's address is bogus, but that is the user's responsibility. If ->buffer is NULL this is a simple allocation. */ dfa = re_realloc (preg->buffer, re_dfa_t, 1); if (dfa == NULL) return REG_ESPACE; preg->allocated = sizeof (re_dfa_t); preg->buffer = (unsigned char *) dfa; } preg->used = sizeof (re_dfa_t); err = init_dfa (dfa, length); if (BE (err != REG_NOERROR, 0)) { free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; return err; } #ifdef DEBUG dfa->re_str = re_malloc (char, length + 1); strncpy (dfa->re_str, pattern, length + 1); #endif err = re_string_construct (®exp, pattern, length, preg->translate, syntax & RE_ICASE, dfa); if (BE (err != REG_NOERROR, 0)) { re_compile_internal_free_return: free_workarea_compile (preg); re_string_destruct (®exp); free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; return err; } /* Parse the regular expression, and build a structure tree. */ preg->re_nsub = 0; dfa->str_tree = parse (®exp, preg, syntax, &err); if (BE (dfa->str_tree == NULL, 0)) goto re_compile_internal_free_return; #ifdef RE_ENABLE_I18N /* If possible, do searching in single byte encoding to speed things up. */ if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) optimize_utf8 (dfa); #endif if (preg->re_nsub > 0) { struct subexp_optimize so; so.dfa = dfa; so.nodes = dfa->nodes; so.no_sub = preg->no_sub; so.re_nsub = preg->re_nsub; dfa->str_tree = optimize_subexps (&so, dfa->str_tree, -1, 0); } /* Analyze the tree and collect information which is necessary to create the dfa. */ err = analyze (dfa); if (BE (err != REG_NOERROR, 0)) goto re_compile_internal_free_return; /* Then create the initial state of the dfa. */ err = create_initial_state (dfa); /* Release work areas. */ free_workarea_compile (preg); re_string_destruct (®exp); if (BE (err != REG_NOERROR, 0)) { free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; } return err; } /* Initialize DFA. We use the length of the regular expression PAT_LEN as the initial length of some arrays. */ static reg_errcode_t init_dfa (dfa, pat_len) re_dfa_t *dfa; int pat_len; { int table_size; #ifndef _LIBC char *codeset_name; #endif memset (dfa, '\0', sizeof (re_dfa_t)); /* Force allocation of str_tree_storage the first time. */ dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; dfa->nodes_alloc = pat_len + 1; dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); dfa->states_alloc = pat_len + 1; /* table_size = 2 ^ ceil(log pat_len) */ for (table_size = 1; table_size > 0; table_size <<= 1) if (table_size > pat_len) break; dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); dfa->state_hash_mask = table_size - 1; dfa->mb_cur_max = MB_CUR_MAX; #ifdef _LIBC if (dfa->mb_cur_max == 6 && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) dfa->is_utf8 = 1; dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) != 0); #else # ifdef HAVE_LANGINFO_CODESET codeset_name = nl_langinfo (CODESET); # else codeset_name = getenv ("LC_ALL"); if (codeset_name == NULL || codeset_name[0] == '\0') codeset_name = getenv ("LC_CTYPE"); if (codeset_name == NULL || codeset_name[0] == '\0') codeset_name = getenv ("LANG"); if (codeset_name == NULL) codeset_name = ""; else if (strchr (codeset_name, '.') != NULL) codeset_name = strchr (codeset_name, '.') + 1; # endif if (strcasecmp (codeset_name, "UTF-8") == 0 || strcasecmp (codeset_name, "UTF8") == 0) dfa->is_utf8 = 1; /* We check exhaustively in the loop below if this charset is a superset of ASCII. */ dfa->map_notascii = 0; #endif #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { if (dfa->is_utf8) dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; else { int i, j, ch; dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset), 1); if (BE (dfa->sb_char == NULL, 0)) return REG_ESPACE; /* Clear all bits by, then set those corresponding to single byte chars. */ bitset_empty (dfa->sb_char); for (i = 0, ch = 0; i < BITSET_UINTS; ++i) for (j = 0; j < UINT_BITS; ++j, ++ch) { wchar_t wch = __btowc (ch); if (wch != WEOF) dfa->sb_char[i] |= 1 << j; # ifndef _LIBC if (isascii (ch) && wch != (wchar_t) ch) dfa->map_notascii = 1; # endif } } } #endif if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0)) return REG_ESPACE; return REG_NOERROR; } /* Initialize WORD_CHAR table, which indicate which character is "word". In this case "word" means that it is the word construction character used by some operators like "\<", "\>", etc. */ static void init_word_char (dfa) re_dfa_t *dfa; { int i, j, ch; dfa->word_ops_used = 1; for (i = 0, ch = 0; i < BITSET_UINTS; ++i) for (j = 0; j < UINT_BITS; ++j, ++ch) if (isalnum (ch) || ch == '_') dfa->word_char[i] |= 1 << j; } /* Free the work area which are only used while compiling. */ static void free_workarea_compile (preg) regex_t *preg; { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_storage_t *storage, *next; for (storage = dfa->str_tree_storage; storage; storage = next) { next = storage->next; re_free (storage); } dfa->str_tree_storage = NULL; dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; dfa->str_tree = NULL; re_free (dfa->org_indices); dfa->org_indices = NULL; } /* Create initial states for all contexts. */ static reg_errcode_t create_initial_state (dfa) re_dfa_t *dfa; { int first, i; reg_errcode_t err; re_node_set init_nodes; /* Initial states have the epsilon closure of the node which is the first node of the regular expression. */ first = dfa->str_tree->first; dfa->init_node = first; err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); if (BE (err != REG_NOERROR, 0)) return err; /* The back-references which are in initial states can epsilon transit, since in this case all of the subexpressions can be null. Then we add epsilon closures of the nodes which are the next nodes of the back-references. */ if (dfa->nbackref > 0) for (i = 0; i < init_nodes.nelem; ++i) { int node_idx = init_nodes.elems[i]; re_token_type_t type = dfa->nodes[node_idx].type; int clexp_idx; if (type != OP_BACK_REF) continue; for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) { re_token_t *clexp_node; clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; if (clexp_node->type == OP_CLOSE_SUBEXP && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) break; } if (clexp_idx == init_nodes.nelem) continue; if (type == OP_BACK_REF) { int dest_idx = dfa->edests[node_idx].elems[0]; if (!re_node_set_contains (&init_nodes, dest_idx)) { re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); i = 0; } } } /* It must be the first time to invoke acquire_state. */ dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); /* We don't check ERR here, since the initial state must not be NULL. */ if (BE (dfa->init_state == NULL, 0)) return err; if (dfa->init_state->has_constraint) { dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_WORD); dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_NEWLINE); dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_NEWLINE | CONTEXT_BEGBUF); if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL || dfa->init_state_begbuf == NULL, 0)) return err; } else dfa->init_state_word = dfa->init_state_nl = dfa->init_state_begbuf = dfa->init_state; re_node_set_free (&init_nodes); return REG_NOERROR; } #ifdef RE_ENABLE_I18N /* If it is possible to do searching in single byte encoding instead of UTF-8 to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change DFA nodes where needed. */ static void optimize_utf8 (dfa) re_dfa_t *dfa; { int node, i, mb_chars = 0, has_period = 0; for (node = 0; node < dfa->nodes_len; ++node) switch (dfa->nodes[node].type) { case CHARACTER: if (dfa->nodes[node].opr.c >= 0x80) mb_chars = 1; break; case ANCHOR: switch (dfa->nodes[node].opr.idx) { case LINE_FIRST: case LINE_LAST: case BUF_FIRST: case BUF_LAST: break; default: /* Word anchors etc. cannot be handled. */ return; } break; case OP_PERIOD: has_period = 1; break; case OP_BACK_REF: case OP_ALT: case END_OF_RE: case OP_DUP_ASTERISK: case OP_DUP_QUESTION: case OP_OPEN_SUBEXP: case OP_CLOSE_SUBEXP: break; case SIMPLE_BRACKET: /* Just double check. */ for (i = 0x80 / UINT_BITS; i < BITSET_UINTS; ++i) if (dfa->nodes[node].opr.sbcset[i]) return; break; default: return; } if (mb_chars || has_period) for (node = 0; node < dfa->nodes_len; ++node) { if (dfa->nodes[node].type == CHARACTER && dfa->nodes[node].opr.c >= 0x80) dfa->nodes[node].mb_partial = 0; else if (dfa->nodes[node].type == OP_PERIOD) dfa->nodes[node].type = OP_UTF8_PERIOD; } /* The search can be in single byte locale. */ dfa->mb_cur_max = 1; dfa->is_utf8 = 0; dfa->has_mb_node = dfa->nbackref > 0 || has_period; } #endif static bin_tree_t * optimize_subexps (so, node, sidx, depth) struct subexp_optimize *so; bin_tree_t *node; int sidx, depth; { int idx, new_depth, new_sidx; bin_tree_t *ret; if (node == NULL) return NULL; new_depth = 0; new_sidx = sidx; if ((depth & 1) && node->type == CONCAT && node->right && node->right->type == 0 && so->nodes[idx = node->right->node_idx].type == OP_CLOSE_SUBEXP) { new_depth = depth + 1; if (new_depth == 2 || (so->nodes[idx].opr.idx < 8 * sizeof (so->dfa->used_bkref_map) && so->dfa->used_bkref_map & (1 << so->nodes[idx].opr.idx))) new_sidx = so->nodes[idx].opr.idx; } node->left = optimize_subexps (so, node->left, new_sidx, new_depth); new_depth = (depth & 1) == 0 && node->type == CONCAT && node->left && node->left->type == 0 && so->nodes[node->left->node_idx].type == OP_OPEN_SUBEXP ? depth + 1 : 0; node->right = optimize_subexps (so, node->right, sidx, new_depth); if (node->type != CONCAT) return node; if ((depth & 1) == 0 && node->left && node->left->type == 0 && so->nodes[idx = node->left->node_idx].type == OP_OPEN_SUBEXP) ret = node->right; else if ((depth & 1) && node->right && node->right->type == 0 && so->nodes[idx = node->right->node_idx].type == OP_CLOSE_SUBEXP) ret = node->left; else return node; if (so->nodes[idx].opr.idx < 8 * sizeof (so->dfa->used_bkref_map) && so->dfa->used_bkref_map & (1 << so->nodes[idx].opr.idx)) return node; if (!so->no_sub) { int i; if (depth < 2) return node; if (so->dfa->subexp_map == NULL) { so->dfa->subexp_map = re_malloc (int, so->re_nsub); if (so->dfa->subexp_map == NULL) return node; for (i = 0; i < so->re_nsub; i++) so->dfa->subexp_map[i] = i; } i = so->nodes[idx].opr.idx; assert (sidx < i); so->dfa->subexp_map[i] = sidx; } so->nodes[idx].type = OP_DELETED_SUBEXP; ret->parent = node->parent; return ret; } /* Analyze the structure tree, and calculate "first", "next", "edest", "eclosure", and "inveclosure". */ static reg_errcode_t analyze (dfa) re_dfa_t *dfa; { int i; reg_errcode_t ret; /* Allocate arrays. */ dfa->nexts = re_malloc (int, dfa->nodes_alloc); dfa->org_indices = re_malloc (int, dfa->nodes_alloc); dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_alloc); if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL || dfa->eclosures == NULL || dfa->inveclosures == NULL, 0)) return REG_ESPACE; /* Initialize them. */ for (i = 0; i < dfa->nodes_len; ++i) { dfa->nexts[i] = -1; re_node_set_init_empty (dfa->edests + i); re_node_set_init_empty (dfa->eclosures + i); re_node_set_init_empty (dfa->inveclosures + i); } ret = analyze_tree (dfa, dfa->str_tree); if (BE (ret == REG_NOERROR, 1)) { ret = calc_eclosure (dfa); if (ret == REG_NOERROR) calc_inveclosure (dfa); } return ret; } /* Helper functions for analyze. This function calculate "first", "next", and "edest" for the subtree whose root is NODE. */ static reg_errcode_t analyze_tree (dfa, node) re_dfa_t *dfa; bin_tree_t *node; { reg_errcode_t ret; if (node->first == -1) calc_first (dfa, node); if (node->next == -1) calc_next (dfa, node); calc_epsdest (dfa, node); /* Calculate "first" etc. for the left child. */ if (node->left != NULL) { ret = analyze_tree (dfa, node->left); if (BE (ret != REG_NOERROR, 0)) return ret; } /* Calculate "first" etc. for the right child. */ if (node->right != NULL) { ret = analyze_tree (dfa, node->right); if (BE (ret != REG_NOERROR, 0)) return ret; } return REG_NOERROR; } /* Calculate "first" for the node NODE. */ static void calc_first (dfa, node) re_dfa_t *dfa; bin_tree_t *node; { int idx, type; idx = node->node_idx; type = (node->type == 0) ? dfa->nodes[idx].type : node->type; switch (type) { #ifdef DEBUG case OP_OPEN_BRACKET: case OP_CLOSE_BRACKET: case OP_OPEN_DUP_NUM: case OP_CLOSE_DUP_NUM: case OP_DUP_PLUS: case OP_NON_MATCH_LIST: case OP_OPEN_COLL_ELEM: case OP_CLOSE_COLL_ELEM: case OP_OPEN_EQUIV_CLASS: case OP_CLOSE_EQUIV_CLASS: case OP_OPEN_CHAR_CLASS: case OP_CLOSE_CHAR_CLASS: /* These must not appear here. */ assert (0); #endif case END_OF_RE: case CHARACTER: case OP_PERIOD: case OP_DUP_ASTERISK: case OP_DUP_QUESTION: #ifdef RE_ENABLE_I18N case OP_UTF8_PERIOD: case COMPLEX_BRACKET: #endif /* RE_ENABLE_I18N */ case SIMPLE_BRACKET: case OP_BACK_REF: case ANCHOR: case OP_OPEN_SUBEXP: case OP_CLOSE_SUBEXP: node->first = idx; break; case OP_ALT: node->first = idx; break; /* else fall through */ default: #ifdef DEBUG assert (node->left != NULL); #endif if (node->left->first == -1) calc_first (dfa, node->left); node->first = node->left->first; break; } } /* Calculate "next" for the node NODE. */ static void calc_next (dfa, node) re_dfa_t *dfa; bin_tree_t *node; { int idx, type; bin_tree_t *parent = node->parent; if (parent == NULL) { node->next = -1; idx = node->node_idx; if (node->type == 0) dfa->nexts[idx] = node->next; return; } idx = parent->node_idx; type = (parent->type == 0) ? dfa->nodes[idx].type : parent->type; switch (type) { case OP_DUP_ASTERISK: node->next = idx; break; case CONCAT: if (parent->left == node) { if (parent->right->first == -1) calc_first (dfa, parent->right); node->next = parent->right->first; break; } /* else fall through */ default: if (parent->next == -1) calc_next (dfa, parent); node->next = parent->next; break; } idx = node->node_idx; if (node->type == 0) dfa->nexts[idx] = node->next; } /* Calculate "edest" for the node NODE. */ static void calc_epsdest (dfa, node) re_dfa_t *dfa; bin_tree_t *node; { int idx; idx = node->node_idx; if (node->type == 0) { if (dfa->nodes[idx].type == OP_DUP_ASTERISK || dfa->nodes[idx].type == OP_DUP_QUESTION) { if (node->left->first == -1) calc_first (dfa, node->left); if (node->next == -1) calc_next (dfa, node); re_node_set_init_2 (dfa->edests + idx, node->left->first, node->next); } else if (dfa->nodes[idx].type == OP_ALT) { int left, right; if (node->left != NULL) { if (node->left->first == -1) calc_first (dfa, node->left); left = node->left->first; } else { if (node->next == -1) calc_next (dfa, node); left = node->next; } if (node->right != NULL) { if (node->right->first == -1) calc_first (dfa, node->right); right = node->right->first; } else { if (node->next == -1) calc_next (dfa, node); right = node->next; } re_node_set_init_2 (dfa->edests + idx, left, right); } else if (dfa->nodes[idx].type == ANCHOR || dfa->nodes[idx].type == OP_OPEN_SUBEXP || dfa->nodes[idx].type == OP_CLOSE_SUBEXP || dfa->nodes[idx].type == OP_BACK_REF) re_node_set_init_1 (dfa->edests + idx, node->next); else assert (!IS_EPSILON_NODE (dfa->nodes[idx].type)); } } /* Duplicate the epsilon closure of the node ROOT_NODE. Note that duplicated nodes have constraint INIT_CONSTRAINT in addition to their own constraint. */ static reg_errcode_t duplicate_node_closure (dfa, top_org_node, top_clone_node, root_node, init_constraint) re_dfa_t *dfa; int top_org_node, top_clone_node, root_node; unsigned int init_constraint; { reg_errcode_t err; int org_node, clone_node, ret; unsigned int constraint = init_constraint; for (org_node = top_org_node, clone_node = top_clone_node;;) { int org_dest, clone_dest; if (dfa->nodes[org_node].type == OP_BACK_REF) { /* If the back reference epsilon-transit, its destination must also have the constraint. Then duplicate the epsilon closure of the destination of the back reference, and store it in edests of the back reference. */ org_dest = dfa->nexts[org_node]; re_node_set_empty (dfa->edests + clone_node); err = duplicate_node (&clone_dest, dfa, org_dest, constraint); if (BE (err != REG_NOERROR, 0)) return err; dfa->nexts[clone_node] = dfa->nexts[org_node]; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } else if (dfa->edests[org_node].nelem == 0) { /* In case of the node can't epsilon-transit, don't duplicate the destination and store the original destination as the destination of the node. */ dfa->nexts[clone_node] = dfa->nexts[org_node]; break; } else if (dfa->edests[org_node].nelem == 1) { /* In case of the node can epsilon-transit, and it has only one destination. */ org_dest = dfa->edests[org_node].elems[0]; re_node_set_empty (dfa->edests + clone_node); if (dfa->nodes[org_node].type == ANCHOR) { /* In case of the node has another constraint, append it. */ if (org_node == root_node && clone_node != org_node) { /* ...but if the node is root_node itself, it means the epsilon closure have a loop, then tie it to the destination of the root_node. */ ret = re_node_set_insert (dfa->edests + clone_node, org_dest); if (BE (ret < 0, 0)) return REG_ESPACE; break; } constraint |= dfa->nodes[org_node].opr.ctx_type; } err = duplicate_node (&clone_dest, dfa, org_dest, constraint); if (BE (err != REG_NOERROR, 0)) return err; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } else /* dfa->edests[org_node].nelem == 2 */ { /* In case of the node can epsilon-transit, and it has two destinations. E.g. '|', '*', '+', '?'. */ org_dest = dfa->edests[org_node].elems[0]; re_node_set_empty (dfa->edests + clone_node); /* Search for a duplicated node which satisfies the constraint. */ clone_dest = search_duplicated_node (dfa, org_dest, constraint); if (clone_dest == -1) { /* There are no such a duplicated node, create a new one. */ err = duplicate_node (&clone_dest, dfa, org_dest, constraint); if (BE (err != REG_NOERROR, 0)) return err; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; err = duplicate_node_closure (dfa, org_dest, clone_dest, root_node, constraint); if (BE (err != REG_NOERROR, 0)) return err; } else { /* There are a duplicated node which satisfy the constraint, use it to avoid infinite loop. */ ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } org_dest = dfa->edests[org_node].elems[1]; err = duplicate_node (&clone_dest, dfa, org_dest, constraint); if (BE (err != REG_NOERROR, 0)) return err; ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); if (BE (ret < 0, 0)) return REG_ESPACE; } org_node = org_dest; clone_node = clone_dest; } return REG_NOERROR; } /* Search for a node which is duplicated from the node ORG_NODE, and satisfies the constraint CONSTRAINT. */ static int search_duplicated_node (dfa, org_node, constraint) re_dfa_t *dfa; int org_node; unsigned int constraint; { int idx; for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) { if (org_node == dfa->org_indices[idx] && constraint == dfa->nodes[idx].constraint) return idx; /* Found. */ } return -1; /* Not found. */ } /* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. The new index will be stored in NEW_IDX and return REG_NOERROR if succeeded, otherwise return the error code. */ static reg_errcode_t duplicate_node (new_idx, dfa, org_idx, constraint) re_dfa_t *dfa; int *new_idx, org_idx; unsigned int constraint; { int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx], 1); if (BE (dup_idx == -1, 0)) return REG_ESPACE; dfa->nodes[dup_idx].constraint = constraint; if (dfa->nodes[org_idx].type == ANCHOR) dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type; dfa->nodes[dup_idx].duplicated = 1; re_node_set_init_empty (dfa->edests + dup_idx); re_node_set_init_empty (dfa->eclosures + dup_idx); re_node_set_init_empty (dfa->inveclosures + dup_idx); /* Store the index of the original node. */ dfa->org_indices[dup_idx] = org_idx; *new_idx = dup_idx; return REG_NOERROR; } static void calc_inveclosure (dfa) re_dfa_t *dfa; { int src, idx, dest; for (src = 0; src < dfa->nodes_len; ++src) { if (dfa->nodes[src].type == OP_DELETED_SUBEXP) continue; for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) { dest = dfa->eclosures[src].elems[idx]; re_node_set_insert_last (dfa->inveclosures + dest, src); } } } /* Calculate "eclosure" for all the node in DFA. */ static reg_errcode_t calc_eclosure (dfa) re_dfa_t *dfa; { int node_idx, incomplete; #ifdef DEBUG assert (dfa->nodes_len > 0); #endif incomplete = 0; /* For each nodes, calculate epsilon closure. */ for (node_idx = 0; ; ++node_idx) { reg_errcode_t err; re_node_set eclosure_elem; if (node_idx == dfa->nodes_len) { if (!incomplete) break; incomplete = 0; node_idx = 0; } #ifdef DEBUG assert (dfa->eclosures[node_idx].nelem != -1); #endif if (dfa->nodes[node_idx].type == OP_DELETED_SUBEXP) continue; /* If we have already calculated, skip it. */ if (dfa->eclosures[node_idx].nelem != 0) continue; /* Calculate epsilon closure of `node_idx'. */ err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1); if (BE (err != REG_NOERROR, 0)) return err; if (dfa->eclosures[node_idx].nelem == 0) { incomplete = 1; re_node_set_free (&eclosure_elem); } } return REG_NOERROR; } /* Calculate epsilon closure of NODE. */ static reg_errcode_t calc_eclosure_iter (new_set, dfa, node, root) re_node_set *new_set; re_dfa_t *dfa; int node, root; { reg_errcode_t err; unsigned int constraint; int i, incomplete; re_node_set eclosure; incomplete = 0; err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); if (BE (err != REG_NOERROR, 0)) return err; /* This indicates that we are calculating this node now. We reference this value to avoid infinite loop. */ dfa->eclosures[node].nelem = -1; constraint = ((dfa->nodes[node].type == ANCHOR) ? dfa->nodes[node].opr.ctx_type : 0); /* If the current node has constraints, duplicate all nodes. Since they must inherit the constraints. */ if (constraint && dfa->edests[node].nelem && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) { int org_node, cur_node; org_node = cur_node = node; err = duplicate_node_closure (dfa, node, node, node, constraint); if (BE (err != REG_NOERROR, 0)) return err; } /* Expand each epsilon destination nodes. */ if (IS_EPSILON_NODE(dfa->nodes[node].type)) for (i = 0; i < dfa->edests[node].nelem; ++i) { re_node_set eclosure_elem; int edest = dfa->edests[node].elems[i]; /* If calculating the epsilon closure of `edest' is in progress, return intermediate result. */ if (dfa->eclosures[edest].nelem == -1) { incomplete = 1; continue; } /* If we haven't calculated the epsilon closure of `edest' yet, calculate now. Otherwise use calculated epsilon closure. */ if (dfa->eclosures[edest].nelem == 0) { err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0); if (BE (err != REG_NOERROR, 0)) return err; } else eclosure_elem = dfa->eclosures[edest]; /* Merge the epsilon closure of `edest'. */ re_node_set_merge (&eclosure, &eclosure_elem); /* If the epsilon closure of `edest' is incomplete, the epsilon closure of this node is also incomplete. */ if (dfa->eclosures[edest].nelem == 0) { incomplete = 1; re_node_set_free (&eclosure_elem); } } /* Epsilon closures include itself. */ re_node_set_insert (&eclosure, node); if (incomplete && !root) dfa->eclosures[node].nelem = 0; else dfa->eclosures[node] = eclosure; *new_set = eclosure; return REG_NOERROR; } /* Functions for token which are used in the parser. */ /* Fetch a token from INPUT. We must not use this function inside bracket expressions. */ static void fetch_token (result, input, syntax) re_token_t *result; re_string_t *input; reg_syntax_t syntax; { re_string_skip_bytes (input, peek_token (result, input, syntax)); } /* Peek a token from INPUT, and return the length of the token. We must not use this function inside bracket expressions. */ static int peek_token (token, input, syntax) re_token_t *token; re_string_t *input; reg_syntax_t syntax; { unsigned char c; if (re_string_eoi (input)) { token->type = END_OF_RE; return 0; } c = re_string_peek_byte (input, 0); token->opr.c = c; token->word_char = 0; #ifdef RE_ENABLE_I18N token->mb_partial = 0; if (input->mb_cur_max > 1 && !re_string_first_byte (input, re_string_cur_idx (input))) { token->type = CHARACTER; token->mb_partial = 1; return 1; } #endif if (c == '\\') { unsigned char c2; if (re_string_cur_idx (input) + 1 >= re_string_length (input)) { token->type = BACK_SLASH; return 1; } c2 = re_string_peek_byte_case (input, 1); token->opr.c = c2; token->type = CHARACTER; #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input) + 1); token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; } else #endif token->word_char = IS_WORD_CHAR (c2) != 0; switch (c2) { case '|': if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) token->type = OP_ALT; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (!(syntax & RE_NO_BK_REFS)) { token->type = OP_BACK_REF; token->opr.idx = c2 - '1'; } break; case '<': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = WORD_FIRST; } break; case '>': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = WORD_LAST; } break; case 'b': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = WORD_DELIM; } break; case 'B': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = NOT_WORD_DELIM; } break; case 'w': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_WORD; break; case 'W': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_NOTWORD; break; case 's': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_SPACE; break; case 'S': if (!(syntax & RE_NO_GNU_OPS)) token->type = OP_NOTSPACE; break; case '`': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = BUF_FIRST; } break; case '\'': if (!(syntax & RE_NO_GNU_OPS)) { token->type = ANCHOR; token->opr.ctx_type = BUF_LAST; } break; case '(': if (!(syntax & RE_NO_BK_PARENS)) token->type = OP_OPEN_SUBEXP; break; case ')': if (!(syntax & RE_NO_BK_PARENS)) token->type = OP_CLOSE_SUBEXP; break; case '+': if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_PLUS; break; case '?': if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_QUESTION; break; case '{': if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) token->type = OP_OPEN_DUP_NUM; break; case '}': if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) token->type = OP_CLOSE_DUP_NUM; break; default: break; } return 2; } token->type = CHARACTER; #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; } else #endif token->word_char = IS_WORD_CHAR (token->opr.c); switch (c) { case '\n': if (syntax & RE_NEWLINE_ALT) token->type = OP_ALT; break; case '|': if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) token->type = OP_ALT; break; case '*': token->type = OP_DUP_ASTERISK; break; case '+': if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_PLUS; break; case '?': if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) token->type = OP_DUP_QUESTION; break; case '{': if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) token->type = OP_OPEN_DUP_NUM; break; case '}': if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) token->type = OP_CLOSE_DUP_NUM; break; case '(': if (syntax & RE_NO_BK_PARENS) token->type = OP_OPEN_SUBEXP; break; case ')': if (syntax & RE_NO_BK_PARENS) token->type = OP_CLOSE_SUBEXP; break; case '[': token->type = OP_OPEN_BRACKET; break; case '.': token->type = OP_PERIOD; break; case '^': if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) && re_string_cur_idx (input) != 0) { char prev = re_string_peek_byte (input, -1); if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') break; } token->type = ANCHOR; token->opr.ctx_type = LINE_FIRST; break; case '$': if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) && re_string_cur_idx (input) + 1 != re_string_length (input)) { re_token_t next; re_string_skip_bytes (input, 1); peek_token (&next, input, syntax); re_string_skip_bytes (input, -1); if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) break; } token->type = ANCHOR; token->opr.ctx_type = LINE_LAST; break; default: break; } return 1; } /* Peek a token from INPUT, and return the length of the token. We must not use this function out of bracket expressions. */ static int peek_token_bracket (token, input, syntax) re_token_t *token; re_string_t *input; reg_syntax_t syntax; { unsigned char c; if (re_string_eoi (input)) { token->type = END_OF_RE; return 0; } c = re_string_peek_byte (input, 0); token->opr.c = c; #ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1 && !re_string_first_byte (input, re_string_cur_idx (input))) { token->type = CHARACTER; return 1; } #endif /* RE_ENABLE_I18N */ if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && re_string_cur_idx (input) + 1 < re_string_length (input)) { /* In this case, '\' escape a character. */ unsigned char c2; re_string_skip_bytes (input, 1); c2 = re_string_peek_byte (input, 0); token->opr.c = c2; token->type = CHARACTER; return 1; } if (c == '[') /* '[' is a special char in a bracket exps. */ { unsigned char c2; int token_len; if (re_string_cur_idx (input) + 1 < re_string_length (input)) c2 = re_string_peek_byte (input, 1); else c2 = 0; token->opr.c = c2; token_len = 2; switch (c2) { case '.': token->type = OP_OPEN_COLL_ELEM; break; case '=': token->type = OP_OPEN_EQUIV_CLASS; break; case ':': if (syntax & RE_CHAR_CLASSES) { token->type = OP_OPEN_CHAR_CLASS; break; } /* else fall through. */ default: token->type = CHARACTER; token->opr.c = c; token_len = 1; break; } return token_len; } switch (c) { case '-': token->type = OP_CHARSET_RANGE; break; case ']': token->type = OP_CLOSE_BRACKET; break; case '^': token->type = OP_NON_MATCH_LIST; break; default: token->type = CHARACTER; } return 1; } /* Functions for parser. */ /* Entry point of the parser. Parse the regular expression REGEXP and return the structure tree. If an error is occured, ERR is set by error code, and return NULL. This function build the following tree, from regular expression : CAT / \ / \ EOR CAT means concatenation. EOR means end of regular expression. */ static bin_tree_t * parse (regexp, preg, syntax, err) re_string_t *regexp; regex_t *preg; reg_syntax_t syntax; reg_errcode_t *err; { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree, *eor, *root; re_token_t current_token; dfa->syntax = syntax; fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; eor = re_dfa_add_tree_node (dfa, NULL, NULL, ¤t_token); if (tree != NULL) root = create_tree (dfa, tree, eor, CONCAT, 0); else root = eor; if (BE (eor == NULL || root == NULL, 0)) { *err = REG_ESPACE; return NULL; } return root; } /* This function build the following tree, from regular expression |: ALT / \ / \ ALT means alternative, which represents the operator `|'. */ static bin_tree_t * parse_reg_exp (regexp, preg, token, syntax, nest, err) re_string_t *regexp; regex_t *preg; re_token_t *token; reg_syntax_t syntax; int nest; reg_errcode_t *err; { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree, *branch = NULL; tree = parse_branch (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; while (token->type == OP_ALT) { re_token_t alt_token = *token; fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); if (token->type != OP_ALT && token->type != END_OF_RE && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) { branch = parse_branch (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && branch == NULL, 0)) return NULL; } else branch = NULL; tree = re_dfa_add_tree_node (dfa, tree, branch, &alt_token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } dfa->has_plural_match = 1; } return tree; } /* This function build the following tree, from regular expression : CAT / \ / \ CAT means concatenation. */ static bin_tree_t * parse_branch (regexp, preg, token, syntax, nest, err) re_string_t *regexp; regex_t *preg; re_token_t *token; reg_syntax_t syntax; int nest; reg_errcode_t *err; { bin_tree_t *tree, *exp; re_dfa_t *dfa = (re_dfa_t *) preg->buffer; tree = parse_expression (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; while (token->type != OP_ALT && token->type != END_OF_RE && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) { exp = parse_expression (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && exp == NULL, 0)) { return NULL; } if (tree != NULL && exp != NULL) { tree = create_tree (dfa, tree, exp, CONCAT, 0); if (tree == NULL) { *err = REG_ESPACE; return NULL; } } else if (tree == NULL) tree = exp; /* Otherwise exp == NULL, we don't need to create new tree. */ } return tree; } /* This function build the following tree, from regular expression a*: * | a */ static bin_tree_t * parse_expression (regexp, preg, token, syntax, nest, err) re_string_t *regexp; regex_t *preg; re_token_t *token; reg_syntax_t syntax; int nest; reg_errcode_t *err; { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree; switch (token->type) { case CHARACTER: tree = re_dfa_add_tree_node (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { while (!re_string_eoi (regexp) && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) { bin_tree_t *mbc_remain; fetch_token (token, regexp, syntax); mbc_remain = re_dfa_add_tree_node (dfa, NULL, NULL, token); tree = create_tree (dfa, tree, mbc_remain, CONCAT, 0); if (BE (mbc_remain == NULL || tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } } #endif break; case OP_OPEN_SUBEXP: tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_OPEN_BRACKET: tree = parse_bracket_exp (regexp, dfa, token, syntax, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_BACK_REF: if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1)) { *err = REG_ESUBREG; return NULL; } dfa->used_bkref_map |= 1 << token->opr.idx; tree = re_dfa_add_tree_node (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } ++dfa->nbackref; dfa->has_mb_node = 1; break; case OP_OPEN_DUP_NUM: if (syntax & RE_CONTEXT_INVALID_DUP) { *err = REG_BADRPT; return NULL; } /* FALLTHROUGH */ case OP_DUP_ASTERISK: case OP_DUP_PLUS: case OP_DUP_QUESTION: if (syntax & RE_CONTEXT_INVALID_OPS) { *err = REG_BADRPT; return NULL; } else if (syntax & RE_CONTEXT_INDEP_OPS) { fetch_token (token, regexp, syntax); return parse_expression (regexp, preg, token, syntax, nest, err); } /* else fall through */ case OP_CLOSE_SUBEXP: if ((token->type == OP_CLOSE_SUBEXP) && !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) { *err = REG_ERPAREN; return NULL; } /* else fall through */ case OP_CLOSE_DUP_NUM: /* We treat it as a normal character. */ /* Then we can these characters as normal characters. */ token->type = CHARACTER; /* mb_partial and word_char bits should be initialized already by peek_token. */ tree = re_dfa_add_tree_node (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } break; case ANCHOR: if ((token->opr.ctx_type & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) && dfa->word_ops_used == 0) init_word_char (dfa); if (token->opr.ctx_type == WORD_DELIM || token->opr.ctx_type == NOT_WORD_DELIM) { bin_tree_t *tree_first, *tree_last; if (token->opr.ctx_type == WORD_DELIM) { token->opr.ctx_type = WORD_FIRST; tree_first = re_dfa_add_tree_node (dfa, NULL, NULL, token); token->opr.ctx_type = WORD_LAST; } else { token->opr.ctx_type = INSIDE_WORD; tree_first = re_dfa_add_tree_node (dfa, NULL, NULL, token); token->opr.ctx_type = INSIDE_NOTWORD; } tree_last = re_dfa_add_tree_node (dfa, NULL, NULL, token); token->type = OP_ALT; tree = re_dfa_add_tree_node (dfa, tree_first, tree_last, token); if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } else { tree = re_dfa_add_tree_node (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } } /* We must return here, since ANCHORs can't be followed by repetition operators. eg. RE"^*" is invalid or "", it must not be "". */ fetch_token (token, regexp, syntax); return tree; case OP_PERIOD: tree = re_dfa_add_tree_node (dfa, NULL, NULL, token); if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } if (dfa->mb_cur_max > 1) dfa->has_mb_node = 1; break; case OP_WORD: case OP_NOTWORD: tree = build_charclass_op (dfa, regexp->trans, (const unsigned char *) "alnum", (const unsigned char *) "_", token->type == OP_NOTWORD, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_SPACE: case OP_NOTSPACE: tree = build_charclass_op (dfa, regexp->trans, (const unsigned char *) "space", (const unsigned char *) "", token->type == OP_NOTSPACE, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; break; case OP_ALT: case END_OF_RE: return NULL; case BACK_SLASH: *err = REG_EESCAPE; return NULL; default: /* Must not happen? */ #ifdef DEBUG assert (0); #endif return NULL; } fetch_token (token, regexp, syntax); while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) { tree = parse_dup_op (tree, regexp, dfa, token, syntax, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; /* In BRE consecutive duplications are not allowed. */ if ((syntax & RE_CONTEXT_INVALID_DUP) && (token->type == OP_DUP_ASTERISK || token->type == OP_OPEN_DUP_NUM)) { *err = REG_BADRPT; return NULL; } dfa->has_plural_match = 1; } return tree; } /* This function build the following tree, from regular expression (): SUBEXP | */ static bin_tree_t * parse_sub_exp (regexp, preg, token, syntax, nest, err) re_string_t *regexp; regex_t *preg; re_token_t *token; reg_syntax_t syntax; int nest; reg_errcode_t *err; { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; bin_tree_t *tree, *left_par, *right_par; size_t cur_nsub; cur_nsub = preg->re_nsub++; left_par = re_dfa_add_tree_node (dfa, NULL, NULL, token); if (BE (left_par == NULL, 0)) { *err = REG_ESPACE; return NULL; } dfa->nodes[left_par->node_idx].opr.idx = cur_nsub; fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); /* The subexpression may be a null string. */ if (token->type == OP_CLOSE_SUBEXP) tree = NULL; else { tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; } if (BE (token->type != OP_CLOSE_SUBEXP, 0)) { *err = REG_EPAREN; return NULL; } right_par = re_dfa_add_tree_node (dfa, NULL, NULL, token); dfa->completed_bkref_map |= 1 << cur_nsub; tree = ((tree == NULL) ? right_par : create_tree (dfa, tree, right_par, CONCAT, 0)); tree = create_tree (dfa, left_par, tree, CONCAT, 0); if (BE (right_par == NULL || tree == NULL, 0)) { *err = REG_ESPACE; return NULL; } dfa->nodes[right_par->node_idx].opr.idx = cur_nsub; return tree; } /* This function parse repetition operators like "*", "+", "{1,3}" etc. */ static bin_tree_t * parse_dup_op (elem, regexp, dfa, token, syntax, err) bin_tree_t *elem; re_string_t *regexp; re_dfa_t *dfa; re_token_t *token; reg_syntax_t syntax; reg_errcode_t *err; { re_token_t dup_token; bin_tree_t *tree = NULL, *old_tree = NULL; int i, start, end, start_idx = re_string_cur_idx (regexp); re_token_t start_token = *token; if (token->type == OP_OPEN_DUP_NUM) { end = 0; start = fetch_number (regexp, token, syntax); if (start == -1) { if (token->type == CHARACTER && token->opr.c == ',') start = 0; /* We treat "{,m}" as "{0,m}". */ else { *err = REG_BADBR; /* {} is invalid. */ return NULL; } } if (BE (start != -2, 1)) { /* We treat "{n}" as "{n,n}". */ end = ((token->type == OP_CLOSE_DUP_NUM) ? start : ((token->type == CHARACTER && token->opr.c == ',') ? fetch_number (regexp, token, syntax) : -2)); } if (BE (start == -2 || end == -2, 0)) { /* Invalid sequence. */ if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0)) { if (token->type == END_OF_RE) *err = REG_EBRACE; else *err = REG_BADBR; return NULL; } /* If the syntax bit is set, rollback. */ re_string_set_index (regexp, start_idx); *token = start_token; token->type = CHARACTER; /* mb_partial and word_char bits should be already initialized by peek_token. */ return elem; } if (BE (end != -1 && start > end, 0)) { /* First number greater than second. */ *err = REG_BADBR; return NULL; } } else { start = (token->type == OP_DUP_PLUS) ? 1 : 0; end = (token->type == OP_DUP_QUESTION) ? 1 : -1; } fetch_token (token, regexp, syntax); /* Treat "{0}*" etc. as "{0}". */ if (BE (elem == NULL || (start == 0 && end == 0), 0)) return NULL; /* Extract "{n,m}" to "...{0,}". */ if (BE (start > 0, 0)) { tree = elem; for (i = 2; i <= start; ++i) { elem = duplicate_tree (elem, dfa); tree = create_tree (dfa, tree, elem, CONCAT, 0); if (BE (elem == NULL || tree == NULL, 0)) goto parse_dup_op_espace; } if (start == end) return tree; /* Duplicate ELEM before it is marked optional. */ elem = duplicate_tree (elem, dfa); old_tree = tree; } else old_tree = NULL; mark_opt_subexp (elem, dfa); dup_token.type = (end == -1 ? OP_DUP_ASTERISK : OP_DUP_QUESTION); tree = re_dfa_add_tree_node (dfa, elem, NULL, &dup_token); if (BE (tree == NULL, 0)) goto parse_dup_op_espace; /* This loop is actually executed only when end != -1, to rewrite {0,n} as ((...?)?)?... We have already created the start+1-th copy. */ for (i = start + 2; i <= end; ++i) { elem = duplicate_tree (elem, dfa); tree = create_tree (dfa, tree, elem, CONCAT, 0); if (BE (elem == NULL || tree == NULL, 0)) goto parse_dup_op_espace; tree = re_dfa_add_tree_node (dfa, tree, NULL, &dup_token); if (BE (tree == NULL, 0)) goto parse_dup_op_espace; } if (old_tree) tree = create_tree (dfa, old_tree, tree, CONCAT, 0); return tree; parse_dup_op_espace: *err = REG_ESPACE; return NULL; } /* Size of the names for collating symbol/equivalence_class/character_class. I'm not sure, but maybe enough. */ #define BRACKET_NAME_BUF_SIZE 32 #ifndef _LIBC /* Local function for parse_bracket_exp only used in case of NOT _LIBC. Build the range expression which starts from START_ELEM, and ends at END_ELEM. The result are written to MBCSET and SBCSET. RANGE_ALLOC is the allocated size of mbcset->range_starts, and mbcset->range_ends, is a pointer argument sinse we may update it. */ static reg_errcode_t # ifdef RE_ENABLE_I18N build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) re_charset_t *mbcset; int *range_alloc; # else /* not RE_ENABLE_I18N */ build_range_exp (sbcset, start_elem, end_elem) # endif /* not RE_ENABLE_I18N */ re_bitset_ptr_t sbcset; bracket_elem_t *start_elem, *end_elem; { unsigned int start_ch, end_ch; /* Equivalence Classes and Character Classes can't be a range start/end. */ if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, 0)) return REG_ERANGE; /* We can handle no multi character collating elements without libc support. */ if (BE ((start_elem->type == COLL_SYM && strlen ((char *) start_elem->opr.name) > 1) || (end_elem->type == COLL_SYM && strlen ((char *) end_elem->opr.name) > 1), 0)) return REG_ECOLLATE; # ifdef RE_ENABLE_I18N { wchar_t wc, start_wc, end_wc; wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] : 0)); end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] : 0)); start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) ? __btowc (start_ch) : start_elem->opr.wch); end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) ? __btowc (end_ch) : end_elem->opr.wch); if (start_wc == WEOF || end_wc == WEOF) return REG_ECOLLATE; cmp_buf[0] = start_wc; cmp_buf[4] = end_wc; if (wcscoll (cmp_buf, cmp_buf + 4) > 0) return REG_ERANGE; /* Got valid collation sequence values, add them as a new entry. However, for !_LIBC we have no collation elements: if the character set is single byte, the single byte character set that we build below suffices. parse_bracket_exp passes no MBCSET if dfa->mb_cur_max == 1. */ if (mbcset) { /* Check the space of the arrays. */ if (BE (*range_alloc == mbcset->nranges, 0)) { /* There is not enough space, need realloc. */ wchar_t *new_array_start, *new_array_end; int new_nranges; /* +1 in case of mbcset->nranges is 0. */ new_nranges = 2 * mbcset->nranges + 1; /* Use realloc since mbcset->range_starts and mbcset->range_ends are NULL if *range_alloc == 0. */ new_array_start = re_realloc (mbcset->range_starts, wchar_t, new_nranges); new_array_end = re_realloc (mbcset->range_ends, wchar_t, new_nranges); if (BE (new_array_start == NULL || new_array_end == NULL, 0)) return REG_ESPACE; mbcset->range_starts = new_array_start; mbcset->range_ends = new_array_end; *range_alloc = new_nranges; } mbcset->range_starts[mbcset->nranges] = start_wc; mbcset->range_ends[mbcset->nranges++] = end_wc; } /* Build the table for single byte characters. */ for (wc = 0; wc < SBC_MAX; ++wc) { cmp_buf[2] = wc; if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) bitset_set (sbcset, wc); } } # else /* not RE_ENABLE_I18N */ { unsigned int ch; start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] : 0)); end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] : 0)); if (start_ch > end_ch) return REG_ERANGE; /* Build the table for single byte characters. */ for (ch = 0; ch < SBC_MAX; ++ch) if (start_ch <= ch && ch <= end_ch) bitset_set (sbcset, ch); } # endif /* not RE_ENABLE_I18N */ return REG_NOERROR; } #endif /* not _LIBC */ #ifndef _LIBC /* Helper function for parse_bracket_exp only used in case of NOT _LIBC.. Build the collating element which is represented by NAME. The result are written to MBCSET and SBCSET. COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a pointer argument since we may update it. */ static reg_errcode_t # ifdef RE_ENABLE_I18N build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) re_charset_t *mbcset; int *coll_sym_alloc; # else /* not RE_ENABLE_I18N */ build_collating_symbol (sbcset, name) # endif /* not RE_ENABLE_I18N */ re_bitset_ptr_t sbcset; const unsigned char *name; { size_t name_len = strlen ((const char *) name); if (BE (name_len != 1, 0)) return REG_ECOLLATE; else { bitset_set (sbcset, name[0]); return REG_NOERROR; } } #endif /* not _LIBC */ /* This function parse bracket expression like "[abc]", "[a-c]", "[[.a-a.]]" etc. */ static bin_tree_t * parse_bracket_exp (regexp, dfa, token, syntax, err) re_string_t *regexp; re_dfa_t *dfa; re_token_t *token; reg_syntax_t syntax; reg_errcode_t *err; { #ifdef _LIBC const unsigned char *collseqmb; const char *collseqwc; uint32_t nrules; int32_t table_size; const int32_t *symb_table; const unsigned char *extra; /* Local function for parse_bracket_exp used in _LIBC environement. Seek the collating symbol entry correspondings to NAME. Return the index of the symbol in the SYMB_TABLE. */ auto inline int32_t __attribute ((always_inline)) seek_collating_symbol_entry (name, name_len) const unsigned char *name; size_t name_len; { int32_t hash = elem_hash ((const char *) name, name_len); int32_t elem = hash % table_size; int32_t second = hash % (table_size - 2); while (symb_table[2 * elem] != 0) { /* First compare the hashing value. */ if (symb_table[2 * elem] == hash /* Compare the length of the name. */ && name_len == extra[symb_table[2 * elem + 1]] /* Compare the name. */ && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], name_len) == 0) { /* Yep, this is the entry. */ break; } /* Next entry. */ elem += second; } return elem; } /* Local function for parse_bracket_exp used in _LIBC environement. Look up the collation sequence value of BR_ELEM. Return the value if succeeded, UINT_MAX otherwise. */ auto inline unsigned int __attribute ((always_inline)) lookup_collation_sequence_value (br_elem) bracket_elem_t *br_elem; { if (br_elem->type == SB_CHAR) { /* if (MB_CUR_MAX == 1) */ if (nrules == 0) return collseqmb[br_elem->opr.ch]; else { wint_t wc = __btowc (br_elem->opr.ch); return __collseq_table_lookup (collseqwc, wc); } } else if (br_elem->type == MB_CHAR) { return __collseq_table_lookup (collseqwc, br_elem->opr.wch); } else if (br_elem->type == COLL_SYM) { size_t sym_name_len = strlen ((char *) br_elem->opr.name); if (nrules != 0) { int32_t elem, idx; elem = seek_collating_symbol_entry (br_elem->opr.name, sym_name_len); if (symb_table[2 * elem] != 0) { /* We found the entry. */ idx = symb_table[2 * elem + 1]; /* Skip the name of collating element name. */ idx += 1 + extra[idx]; /* Skip the byte sequence of the collating element. */ idx += 1 + extra[idx]; /* Adjust for the alignment. */ idx = (idx + 3) & ~3; /* Skip the multibyte collation sequence value. */ idx += sizeof (unsigned int); /* Skip the wide char sequence of the collating element. */ idx += sizeof (unsigned int) * (1 + *(unsigned int *) (extra + idx)); /* Return the collation sequence value. */ return *(unsigned int *) (extra + idx); } else if (symb_table[2 * elem] == 0 && sym_name_len == 1) { /* No valid character. Match it as a single byte character. */ return collseqmb[br_elem->opr.name[0]]; } } else if (sym_name_len == 1) return collseqmb[br_elem->opr.name[0]]; } return UINT_MAX; } /* Local function for parse_bracket_exp used in _LIBC environement. Build the range expression which starts from START_ELEM, and ends at END_ELEM. The result are written to MBCSET and SBCSET. RANGE_ALLOC is the allocated size of mbcset->range_starts, and mbcset->range_ends, is a pointer argument sinse we may update it. */ auto inline reg_errcode_t __attribute ((always_inline)) build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) re_charset_t *mbcset; int *range_alloc; re_bitset_ptr_t sbcset; bracket_elem_t *start_elem, *end_elem; { unsigned int ch; uint32_t start_collseq; uint32_t end_collseq; /* Equivalence Classes and Character Classes can't be a range start/end. */ if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, 0)) return REG_ERANGE; start_collseq = lookup_collation_sequence_value (start_elem); end_collseq = lookup_collation_sequence_value (end_elem); /* Check start/end collation sequence values. */ if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0)) return REG_ECOLLATE; if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0)) return REG_ERANGE; /* Got valid collation sequence values, add them as a new entry. However, if we have no collation elements, and the character set is single byte, the single byte character set that we build below suffices. */ if (nrules > 0 || dfa->mb_cur_max > 1) { /* Check the space of the arrays. */ if (BE (*range_alloc == mbcset->nranges, 0)) { /* There is not enough space, need realloc. */ uint32_t *new_array_start; uint32_t *new_array_end; int new_nranges; /* +1 in case of mbcset->nranges is 0. */ new_nranges = 2 * mbcset->nranges + 1; new_array_start = re_realloc (mbcset->range_starts, uint32_t, new_nranges); new_array_end = re_realloc (mbcset->range_ends, uint32_t, new_nranges); if (BE (new_array_start == NULL || new_array_end == NULL, 0)) return REG_ESPACE; mbcset->range_starts = new_array_start; mbcset->range_ends = new_array_end; *range_alloc = new_nranges; } mbcset->range_starts[mbcset->nranges] = start_collseq; mbcset->range_ends[mbcset->nranges++] = end_collseq; } /* Build the table for single byte characters. */ for (ch = 0; ch < SBC_MAX; ch++) { uint32_t ch_collseq; /* if (MB_CUR_MAX == 1) */ if (nrules == 0) ch_collseq = collseqmb[ch]; else ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) bitset_set (sbcset, ch); } return REG_NOERROR; } /* Local function for parse_bracket_exp used in _LIBC environement. Build the collating element which is represented by NAME. The result are written to MBCSET and SBCSET. COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a pointer argument sinse we may update it. */ auto inline reg_errcode_t __attribute ((always_inline)) build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) re_charset_t *mbcset; int *coll_sym_alloc; re_bitset_ptr_t sbcset; const unsigned char *name; { int32_t elem, idx; size_t name_len = strlen ((const char *) name); if (nrules != 0) { elem = seek_collating_symbol_entry (name, name_len); if (symb_table[2 * elem] != 0) { /* We found the entry. */ idx = symb_table[2 * elem + 1]; /* Skip the name of collating element name. */ idx += 1 + extra[idx]; } else if (symb_table[2 * elem] == 0 && name_len == 1) { /* No valid character, treat it as a normal character. */ bitset_set (sbcset, name[0]); return REG_NOERROR; } else return REG_ECOLLATE; /* Got valid collation sequence, add it as a new entry. */ /* Check the space of the arrays. */ if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0)) { /* Not enough, realloc it. */ /* +1 in case of mbcset->ncoll_syms is 0. */ int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; /* Use realloc since mbcset->coll_syms is NULL if *alloc == 0. */ int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, new_coll_sym_alloc); if (BE (new_coll_syms == NULL, 0)) return REG_ESPACE; mbcset->coll_syms = new_coll_syms; *coll_sym_alloc = new_coll_sym_alloc; } mbcset->coll_syms[mbcset->ncoll_syms++] = idx; return REG_NOERROR; } else { if (BE (name_len != 1, 0)) return REG_ECOLLATE; else { bitset_set (sbcset, name[0]); return REG_NOERROR; } } } #endif re_token_t br_token; re_bitset_ptr_t sbcset; #ifdef RE_ENABLE_I18N re_charset_t *mbcset; int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; int equiv_class_alloc = 0, char_class_alloc = 0; #endif /* not RE_ENABLE_I18N */ int non_match = 0; bin_tree_t *work_tree; int token_len; int first_round = 1; #ifdef _LIBC collseqmb = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules) { /* if (MB_CUR_MAX > 1) */ collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_TABLEMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); } #endif sbcset = (re_bitset_ptr_t) calloc (sizeof (unsigned int), BITSET_UINTS); #ifdef RE_ENABLE_I18N mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); #endif /* RE_ENABLE_I18N */ #ifdef RE_ENABLE_I18N if (BE (sbcset == NULL || mbcset == NULL, 0)) #else if (BE (sbcset == NULL, 0)) #endif /* RE_ENABLE_I18N */ { *err = REG_ESPACE; return NULL; } token_len = peek_token_bracket (token, regexp, syntax); if (BE (token->type == END_OF_RE, 0)) { *err = REG_BADPAT; goto parse_bracket_exp_free_return; } if (token->type == OP_NON_MATCH_LIST) { #ifdef RE_ENABLE_I18N mbcset->non_match = 1; #endif /* not RE_ENABLE_I18N */ non_match = 1; if (syntax & RE_HAT_LISTS_NOT_NEWLINE) bitset_set (sbcset, '\0'); re_string_skip_bytes (regexp, token_len); /* Skip a token. */ token_len = peek_token_bracket (token, regexp, syntax); if (BE (token->type == END_OF_RE, 0)) { *err = REG_BADPAT; goto parse_bracket_exp_free_return; } } /* We treat the first ']' as a normal character. */ if (token->type == OP_CLOSE_BRACKET) token->type = CHARACTER; while (1) { bracket_elem_t start_elem, end_elem; unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; reg_errcode_t ret; int token_len2 = 0, is_range_exp = 0; re_token_t token2; start_elem.opr.name = start_name_buf; ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, syntax, first_round); if (BE (ret != REG_NOERROR, 0)) { *err = ret; goto parse_bracket_exp_free_return; } first_round = 0; /* Get information about the next token. We need it in any case. */ token_len = peek_token_bracket (token, regexp, syntax); /* Do not check for ranges if we know they are not allowed. */ if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) { if (BE (token->type == END_OF_RE, 0)) { *err = REG_EBRACK; goto parse_bracket_exp_free_return; } if (token->type == OP_CHARSET_RANGE) { re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ token_len2 = peek_token_bracket (&token2, regexp, syntax); if (BE (token2.type == END_OF_RE, 0)) { *err = REG_EBRACK; goto parse_bracket_exp_free_return; } if (token2.type == OP_CLOSE_BRACKET) { /* We treat the last '-' as a normal character. */ re_string_skip_bytes (regexp, -token_len); token->type = CHARACTER; } else is_range_exp = 1; } } if (is_range_exp == 1) { end_elem.opr.name = end_name_buf; ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, dfa, syntax, 1); if (BE (ret != REG_NOERROR, 0)) { *err = ret; goto parse_bracket_exp_free_return; } token_len = peek_token_bracket (token, regexp, syntax); #ifdef _LIBC *err = build_range_exp (sbcset, mbcset, &range_alloc, &start_elem, &end_elem); #else # ifdef RE_ENABLE_I18N *err = build_range_exp (sbcset, dfa->mb_cur_max > 1 ? mbcset : NULL, &range_alloc, &start_elem, &end_elem); # else *err = build_range_exp (sbcset, &start_elem, &end_elem); # endif #endif /* RE_ENABLE_I18N */ if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; } else { switch (start_elem.type) { case SB_CHAR: bitset_set (sbcset, start_elem.opr.ch); break; #ifdef RE_ENABLE_I18N case MB_CHAR: /* Check whether the array has enough space. */ if (BE (mbchar_alloc == mbcset->nmbchars, 0)) { wchar_t *new_mbchars; /* Not enough, realloc it. */ /* +1 in case of mbcset->nmbchars is 0. */ mbchar_alloc = 2 * mbcset->nmbchars + 1; /* Use realloc since array is NULL if *alloc == 0. */ new_mbchars = re_realloc (mbcset->mbchars, wchar_t, mbchar_alloc); if (BE (new_mbchars == NULL, 0)) goto parse_bracket_exp_espace; mbcset->mbchars = new_mbchars; } mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; break; #endif /* RE_ENABLE_I18N */ case EQUIV_CLASS: *err = build_equiv_class (sbcset, #ifdef RE_ENABLE_I18N mbcset, &equiv_class_alloc, #endif /* RE_ENABLE_I18N */ start_elem.opr.name); if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; break; case COLL_SYM: *err = build_collating_symbol (sbcset, #ifdef RE_ENABLE_I18N mbcset, &coll_sym_alloc, #endif /* RE_ENABLE_I18N */ start_elem.opr.name); if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; break; case CHAR_CLASS: *err = build_charclass (regexp->trans, sbcset, #ifdef RE_ENABLE_I18N mbcset, &char_class_alloc, #endif /* RE_ENABLE_I18N */ start_elem.opr.name, syntax); if (BE (*err != REG_NOERROR, 0)) goto parse_bracket_exp_free_return; break; default: assert (0); break; } } if (BE (token->type == END_OF_RE, 0)) { *err = REG_EBRACK; goto parse_bracket_exp_free_return; } if (token->type == OP_CLOSE_BRACKET) break; } re_string_skip_bytes (regexp, token_len); /* Skip a token. */ /* If it is non-matching list. */ if (non_match) bitset_not (sbcset); #ifdef RE_ENABLE_I18N /* Ensure only single byte characters are set. */ if (dfa->mb_cur_max > 1) bitset_mask (sbcset, dfa->sb_char); #endif /* RE_ENABLE_I18N */ /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; br_token.opr.sbcset = sbcset; work_tree = re_dfa_add_tree_node (dfa, NULL, NULL, &br_token); if (BE (work_tree == NULL, 0)) goto parse_bracket_exp_espace; #ifdef RE_ENABLE_I18N if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes || mbcset->non_match))) { re_token_t alt_token; bin_tree_t *mbc_tree; int sbc_idx; /* Build a tree for complex bracket. */ dfa->has_mb_node = 1; for (sbc_idx = 0; sbc_idx < BITSET_UINTS; ++sbc_idx) if (sbcset[sbc_idx]) break; /* If there are no bits set in sbcset, there is no point of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ if (sbc_idx == BITSET_UINTS) { re_free (sbcset); dfa->nodes[work_tree->node_idx].type = COMPLEX_BRACKET; dfa->nodes[work_tree->node_idx].opr.mbcset = mbcset; return work_tree; } br_token.type = COMPLEX_BRACKET; br_token.opr.mbcset = mbcset; mbc_tree = re_dfa_add_tree_node (dfa, NULL, NULL, &br_token); if (BE (mbc_tree == NULL, 0)) goto parse_bracket_exp_espace; /* Then join them by ALT node. */ alt_token.type = OP_ALT; dfa->has_plural_match = 1; work_tree = re_dfa_add_tree_node (dfa, work_tree, mbc_tree, &alt_token); if (BE (mbc_tree != NULL, 1)) return work_tree; } else { free_charset (mbcset); return work_tree; } #else /* not RE_ENABLE_I18N */ return work_tree; #endif /* not RE_ENABLE_I18N */ parse_bracket_exp_espace: *err = REG_ESPACE; parse_bracket_exp_free_return: re_free (sbcset); #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* RE_ENABLE_I18N */ return NULL; } /* Parse an element in the bracket expression. */ static reg_errcode_t parse_bracket_element (elem, regexp, token, token_len, dfa, syntax, accept_hyphen) bracket_elem_t *elem; re_string_t *regexp; re_token_t *token; int token_len; re_dfa_t *dfa; reg_syntax_t syntax; int accept_hyphen; { #ifdef RE_ENABLE_I18N int cur_char_size; cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); if (cur_char_size > 1) { elem->type = MB_CHAR; elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); re_string_skip_bytes (regexp, cur_char_size); return REG_NOERROR; } #endif /* RE_ENABLE_I18N */ re_string_skip_bytes (regexp, token_len); /* Skip a token. */ if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS || token->type == OP_OPEN_EQUIV_CLASS) return parse_bracket_symbol (elem, regexp, token); if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen) { /* A '-' must only appear as anything but a range indicator before the closing bracket. Everything else is an error. */ re_token_t token2; (void) peek_token_bracket (&token2, regexp, syntax); if (token2.type != OP_CLOSE_BRACKET) /* The actual error value is not standardized since this whole case is undefined. But ERANGE makes good sense. */ return REG_ERANGE; } elem->type = SB_CHAR; elem->opr.ch = token->opr.c; return REG_NOERROR; } /* Parse a bracket symbol in the bracket expression. Bracket symbols are such as [::], [..], and [==]. */ static reg_errcode_t parse_bracket_symbol (elem, regexp, token) bracket_elem_t *elem; re_string_t *regexp; re_token_t *token; { unsigned char ch, delim = token->opr.c; int i = 0; if (re_string_eoi(regexp)) return REG_EBRACK; for (;; ++i) { if (i >= BRACKET_NAME_BUF_SIZE) return REG_EBRACK; if (token->type == OP_OPEN_CHAR_CLASS) ch = re_string_fetch_byte_case (regexp); else ch = re_string_fetch_byte (regexp); if (re_string_eoi(regexp)) return REG_EBRACK; if (ch == delim && re_string_peek_byte (regexp, 0) == ']') break; elem->opr.name[i] = ch; } re_string_skip_bytes (regexp, 1); elem->opr.name[i] = '\0'; switch (token->type) { case OP_OPEN_COLL_ELEM: elem->type = COLL_SYM; break; case OP_OPEN_EQUIV_CLASS: elem->type = EQUIV_CLASS; break; case OP_OPEN_CHAR_CLASS: elem->type = CHAR_CLASS; break; default: break; } return REG_NOERROR; } /* Helper function for parse_bracket_exp. Build the equivalence class which is represented by NAME. The result are written to MBCSET and SBCSET. EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, is a pointer argument sinse we may update it. */ static reg_errcode_t #ifdef RE_ENABLE_I18N build_equiv_class (sbcset, mbcset, equiv_class_alloc, name) re_charset_t *mbcset; int *equiv_class_alloc; #else /* not RE_ENABLE_I18N */ build_equiv_class (sbcset, name) #endif /* not RE_ENABLE_I18N */ re_bitset_ptr_t sbcset; const unsigned char *name; { #if defined _LIBC uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) { const int32_t *table, *indirect; const unsigned char *weights, *extra, *cp; unsigned char char_buf[2]; int32_t idx1, idx2; unsigned int ch; size_t len; /* This #include defines a local function! */ # include /* Calculate the index for equivalence class. */ cp = name; table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); idx1 = findidx (&cp); if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) /* This isn't a valid character. */ return REG_ECOLLATE; /* Build single byte matcing table for this equivalence class. */ char_buf[1] = (unsigned char) '\0'; len = weights[idx1]; for (ch = 0; ch < SBC_MAX; ++ch) { char_buf[0] = ch; cp = char_buf; idx2 = findidx (&cp); /* idx2 = table[ch]; */ if (idx2 == 0) /* This isn't a valid character. */ continue; if (len == weights[idx2]) { int cnt = 0; while (cnt <= len && weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt]) ++cnt; if (cnt > len) bitset_set (sbcset, ch); } } /* Check whether the array has enough space. */ if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0)) { /* Not enough, realloc it. */ /* +1 in case of mbcset->nequiv_classes is 0. */ int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; /* Use realloc since the array is NULL if *alloc == 0. */ int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, int32_t, new_equiv_class_alloc); if (BE (new_equiv_classes == NULL, 0)) return REG_ESPACE; mbcset->equiv_classes = new_equiv_classes; *equiv_class_alloc = new_equiv_class_alloc; } mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; } else #endif /* _LIBC */ { if (BE (strlen ((const char *) name) != 1, 0)) return REG_ECOLLATE; bitset_set (sbcset, *name); } return REG_NOERROR; } /* Helper function for parse_bracket_exp. Build the character class which is represented by NAME. The result are written to MBCSET and SBCSET. CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, is a pointer argument sinse we may update it. */ static reg_errcode_t #ifdef RE_ENABLE_I18N build_charclass (trans, sbcset, mbcset, char_class_alloc, class_name, syntax) re_charset_t *mbcset; int *char_class_alloc; #else /* not RE_ENABLE_I18N */ build_charclass (trans, sbcset, class_name, syntax) #endif /* not RE_ENABLE_I18N */ unsigned RE_TRANSLATE_TYPE trans; re_bitset_ptr_t sbcset; const unsigned char *class_name; reg_syntax_t syntax; { int i; const char *name = (const char *) class_name; /* In case of REG_ICASE "upper" and "lower" match the both of upper and lower cases. */ if ((syntax & RE_ICASE) && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) name = "alpha"; #ifdef RE_ENABLE_I18N /* Check the space of the arrays. */ if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) { /* Not enough, realloc it. */ /* +1 in case of mbcset->nchar_classes is 0. */ int new_char_class_alloc = 2 * mbcset->nchar_classes + 1; /* Use realloc since array is NULL if *alloc == 0. */ wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, new_char_class_alloc); if (BE (new_char_classes == NULL, 0)) return REG_ESPACE; mbcset->char_classes = new_char_classes; *char_class_alloc = new_char_class_alloc; } mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); #endif /* RE_ENABLE_I18N */ #define BUILD_CHARCLASS_LOOP(ctype_func) \ for (i = 0; i < SBC_MAX; ++i) \ { \ if (ctype_func (i)) \ { \ int ch = trans ? trans[i] : i; \ bitset_set (sbcset, ch); \ } \ } if (strcmp (name, "alnum") == 0) BUILD_CHARCLASS_LOOP (isalnum) else if (strcmp (name, "cntrl") == 0) BUILD_CHARCLASS_LOOP (iscntrl) else if (strcmp (name, "lower") == 0) BUILD_CHARCLASS_LOOP (islower) else if (strcmp (name, "space") == 0) BUILD_CHARCLASS_LOOP (isspace) else if (strcmp (name, "alpha") == 0) BUILD_CHARCLASS_LOOP (isalpha) else if (strcmp (name, "digit") == 0) BUILD_CHARCLASS_LOOP (isdigit) else if (strcmp (name, "print") == 0) BUILD_CHARCLASS_LOOP (isprint) else if (strcmp (name, "upper") == 0) BUILD_CHARCLASS_LOOP (isupper) else if (strcmp (name, "blank") == 0) BUILD_CHARCLASS_LOOP (isblank) else if (strcmp (name, "graph") == 0) BUILD_CHARCLASS_LOOP (isgraph) else if (strcmp (name, "punct") == 0) BUILD_CHARCLASS_LOOP (ispunct) else if (strcmp (name, "xdigit") == 0) BUILD_CHARCLASS_LOOP (isxdigit) else return REG_ECTYPE; return REG_NOERROR; } static bin_tree_t * build_charclass_op (dfa, trans, class_name, extra, non_match, err) re_dfa_t *dfa; unsigned RE_TRANSLATE_TYPE trans; const unsigned char *class_name; const unsigned char *extra; int non_match; reg_errcode_t *err; { re_bitset_ptr_t sbcset; #ifdef RE_ENABLE_I18N re_charset_t *mbcset; int alloc = 0; #endif /* not RE_ENABLE_I18N */ reg_errcode_t ret; re_token_t br_token; bin_tree_t *tree; sbcset = (re_bitset_ptr_t) calloc (sizeof (unsigned int), BITSET_UINTS); #ifdef RE_ENABLE_I18N mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); #endif /* RE_ENABLE_I18N */ #ifdef RE_ENABLE_I18N if (BE (sbcset == NULL || mbcset == NULL, 0)) #else /* not RE_ENABLE_I18N */ if (BE (sbcset == NULL, 0)) #endif /* not RE_ENABLE_I18N */ { *err = REG_ESPACE; return NULL; } if (non_match) { #ifdef RE_ENABLE_I18N /* if (syntax & RE_HAT_LISTS_NOT_NEWLINE) bitset_set(cset->sbcset, '\0'); */ mbcset->non_match = 1; #endif /* not RE_ENABLE_I18N */ } /* We don't care the syntax in this case. */ ret = build_charclass (trans, sbcset, #ifdef RE_ENABLE_I18N mbcset, &alloc, #endif /* RE_ENABLE_I18N */ class_name, 0); if (BE (ret != REG_NOERROR, 0)) { re_free (sbcset); #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* RE_ENABLE_I18N */ *err = ret; return NULL; } /* \w match '_' also. */ for (; *extra; extra++) bitset_set (sbcset, *extra); /* If it is non-matching list. */ if (non_match) bitset_not (sbcset); #ifdef RE_ENABLE_I18N /* Ensure only single byte characters are set. */ if (dfa->mb_cur_max > 1) bitset_mask (sbcset, dfa->sb_char); #endif /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; br_token.opr.sbcset = sbcset; tree = re_dfa_add_tree_node (dfa, NULL, NULL, &br_token); if (BE (tree == NULL, 0)) goto build_word_op_espace; #ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { re_token_t alt_token; bin_tree_t *mbc_tree; /* Build a tree for complex bracket. */ br_token.type = COMPLEX_BRACKET; br_token.opr.mbcset = mbcset; dfa->has_mb_node = 1; mbc_tree = re_dfa_add_tree_node (dfa, NULL, NULL, &br_token); if (BE (mbc_tree == NULL, 0)) goto build_word_op_espace; /* Then join them by ALT node. */ alt_token.type = OP_ALT; dfa->has_plural_match = 1; tree = re_dfa_add_tree_node (dfa, tree, mbc_tree, &alt_token); if (BE (mbc_tree != NULL, 1)) return tree; } else { free_charset (mbcset); return tree; } #else /* not RE_ENABLE_I18N */ return tree; #endif /* not RE_ENABLE_I18N */ build_word_op_espace: re_free (sbcset); #ifdef RE_ENABLE_I18N free_charset (mbcset); #endif /* RE_ENABLE_I18N */ *err = REG_ESPACE; return NULL; } /* This is intended for the expressions like "a{1,3}". Fetch a number from `input', and return the number. Return -1, if the number field is empty like "{,1}". Return -2, If an error is occured. */ static int fetch_number (input, token, syntax) re_string_t *input; re_token_t *token; reg_syntax_t syntax; { int num = -1; unsigned char c; while (1) { fetch_token (token, input, syntax); c = token->opr.c; if (BE (token->type == END_OF_RE, 0)) return -2; if (token->type == OP_CLOSE_DUP_NUM || c == ',') break; num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0')); num = (num > RE_DUP_MAX) ? -2 : num; } return num; } #ifdef RE_ENABLE_I18N static void free_charset (re_charset_t *cset) { re_free (cset->mbchars); # ifdef _LIBC re_free (cset->coll_syms); re_free (cset->equiv_classes); re_free (cset->range_starts); re_free (cset->range_ends); # endif re_free (cset->char_classes); re_free (cset); } #endif /* RE_ENABLE_I18N */ /* Functions for binary tree operation. */ /* Create a tree node. */ static bin_tree_t * create_tree (dfa, left, right, type, index) re_dfa_t *dfa; bin_tree_t *left; bin_tree_t *right; re_token_type_t type; int index; { bin_tree_t *tree; if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0)) { bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); if (storage == NULL) return NULL; storage->next = dfa->str_tree_storage; dfa->str_tree_storage = storage; dfa->str_tree_storage_idx = 0; } tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; tree->parent = NULL; tree->left = left; tree->right = right; tree->type = type; tree->node_idx = index; tree->first = -1; tree->next = -1; re_node_set_init_empty (&tree->eclosure); if (left != NULL) left->parent = tree; if (right != NULL) right->parent = tree; return tree; } /* Create both a DFA node and a tree for it. */ static bin_tree_t * re_dfa_add_tree_node (dfa, left, right, token) re_dfa_t *dfa; bin_tree_t *left; bin_tree_t *right; const re_token_t *token; { int new_idx = re_dfa_add_node (dfa, *token, 0); if (new_idx == -1) return NULL; return create_tree (dfa, left, right, 0, new_idx); } /* Mark the tree SRC as an optional subexpression. */ static void mark_opt_subexp (src, dfa) const bin_tree_t *src; re_dfa_t *dfa; { /* Pass an OPT_SUBEXP_IDX which is != 1 if the duplicated tree is a subexpression. */ if (src->type == CONCAT && src->left->type == NON_TYPE && dfa->nodes[src->left->node_idx].type == OP_OPEN_SUBEXP) mark_opt_subexp_iter (src, dfa, dfa->nodes[src->left->node_idx].opr.idx); } /* Recursive tree walker for mark_opt_subexp. */ static void mark_opt_subexp_iter (src, dfa, idx) const bin_tree_t *src; re_dfa_t *dfa; int idx; { int node_idx; if (src->type == NON_TYPE) { node_idx = src->node_idx; if ((dfa->nodes[node_idx].type == OP_OPEN_SUBEXP || dfa->nodes[node_idx].type == OP_CLOSE_SUBEXP) && dfa->nodes[node_idx].opr.idx == idx) dfa->nodes[node_idx].opt_subexp = 1; } if (src->left != NULL) mark_opt_subexp_iter (src->left, dfa, idx); if (src->right != NULL) mark_opt_subexp_iter (src->right, dfa, idx); } /* Duplicate the node SRC, and return new node. */ static bin_tree_t * duplicate_tree (src, dfa) const bin_tree_t *src; re_dfa_t *dfa; { bin_tree_t *left = NULL, *right = NULL, *new_tree; int new_node_idx; /* Since node indies must be according to Post-order of the tree, we must duplicate the left at first. */ if (src->left != NULL) { left = duplicate_tree (src->left, dfa); if (left == NULL) return NULL; } /* Secondaly, duplicate the right. */ if (src->right != NULL) { right = duplicate_tree (src->right, dfa); if (right == NULL) return NULL; } /* At last, duplicate itself. */ if (src->type == NON_TYPE) { new_node_idx = re_dfa_add_node (dfa, dfa->nodes[src->node_idx], 0); dfa->nodes[new_node_idx].duplicated = 1; if (BE (new_node_idx == -1, 0)) return NULL; } else new_node_idx = src->type; new_tree = create_tree (dfa, left, right, src->type, new_node_idx); return new_tree; } uqm-0.6.2/sc2/src/regex/Makeinfo0000600000175000017500000000002610543202107015043 0ustar joeyjoeyuqm_CFILES="regex.c" uqm-0.6.2/sc2/src/regex/regex_internal.h0000600000175000017500000005637110543202107016564 0ustar joeyjoey/* Extended regular expression matching and search library. Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _REGEX_INTERNAL_H #define _REGEX_INTERNAL_H 1 #include #include #include #include #include #if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC # include #endif #if defined HAVE_LOCALE_H || defined _LIBC # include #endif #if defined HAVE_WCHAR_H || defined _LIBC # include #endif /* HAVE_WCHAR_H || _LIBC */ #if defined HAVE_WCTYPE_H || defined _LIBC # include #endif /* HAVE_WCTYPE_H || _LIBC */ /* In case that the system doesn't have isblank(). */ #if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank # define isblank(ch) ((ch) == ' ' || (ch) == '\t') #endif #ifdef _LIBC # ifndef _RE_DEFINE_LOCALE_FUNCTIONS # define _RE_DEFINE_LOCALE_FUNCTIONS 1 # include # include # include # endif #endif /* This is for other GNU distributions with internationalized messages. */ #if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC # include # ifdef _LIBC # undef gettext # define gettext(msgid) \ INTUSE(__dcgettext) (INTUSE(_libc_intl_domainname), msgid, LC_MESSAGES) # endif #else # define gettext(msgid) (msgid) #endif #ifndef gettext_noop /* This define is so xgettext can find the internationalizable strings. */ # define gettext_noop(String) String #endif #if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC # define RE_ENABLE_I18N #endif #if __GNUC__ >= 3 # define BE(expr, val) __builtin_expect (expr, val) #else # define BE(expr, val) (expr) # define inline #endif /* Number of bits in a byte. */ #define BYTE_BITS 8 /* Number of single byte character. */ #define SBC_MAX 256 #define COLL_ELEM_LEN_MAX 8 /* The character which represents newline. */ #define NEWLINE_CHAR '\n' #define WIDE_NEWLINE_CHAR L'\n' /* Rename to standard API for using out of glibc. */ #ifndef _LIBC # define __wctype wctype # define __iswctype iswctype # define __btowc btowc # define __mempcpy mempcpy # define __wcrtomb wcrtomb # define __regfree regfree # define attribute_hidden #endif /* not _LIBC */ #ifdef __GNUC__ # define __attribute(arg) __attribute__ (arg) #else # define __attribute(arg) #endif extern const char __re_error_msgid[] attribute_hidden; extern const size_t __re_error_msgid_idx[] attribute_hidden; /* Number of bits in an unsinged int. */ #define UINT_BITS (sizeof (unsigned int) * BYTE_BITS) /* Number of unsigned int in an bit_set. */ #define BITSET_UINTS ((SBC_MAX + UINT_BITS - 1) / UINT_BITS) typedef unsigned int bitset[BITSET_UINTS]; typedef unsigned int *re_bitset_ptr_t; typedef const unsigned int *re_const_bitset_ptr_t; #define bitset_set(set,i) (set[i / UINT_BITS] |= 1 << i % UINT_BITS) #define bitset_clear(set,i) (set[i / UINT_BITS] &= ~(1 << i % UINT_BITS)) #define bitset_contain(set,i) (set[i / UINT_BITS] & (1 << i % UINT_BITS)) #define bitset_empty(set) memset (set, 0, sizeof (unsigned int) * BITSET_UINTS) #define bitset_set_all(set) \ memset (set, 255, sizeof (unsigned int) * BITSET_UINTS) #define bitset_copy(dest,src) \ memcpy (dest, src, sizeof (unsigned int) * BITSET_UINTS) static inline void bitset_not (bitset set); static inline void bitset_merge (bitset dest, const bitset src); static inline void bitset_not_merge (bitset dest, const bitset src); static inline void bitset_mask (bitset dest, const bitset src); #define PREV_WORD_CONSTRAINT 0x0001 #define PREV_NOTWORD_CONSTRAINT 0x0002 #define NEXT_WORD_CONSTRAINT 0x0004 #define NEXT_NOTWORD_CONSTRAINT 0x0008 #define PREV_NEWLINE_CONSTRAINT 0x0010 #define NEXT_NEWLINE_CONSTRAINT 0x0020 #define PREV_BEGBUF_CONSTRAINT 0x0040 #define NEXT_ENDBUF_CONSTRAINT 0x0080 #define WORD_DELIM_CONSTRAINT 0x0100 #define NOT_WORD_DELIM_CONSTRAINT 0x0200 typedef enum { INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, LINE_FIRST = PREV_NEWLINE_CONSTRAINT, LINE_LAST = NEXT_NEWLINE_CONSTRAINT, BUF_FIRST = PREV_BEGBUF_CONSTRAINT, BUF_LAST = NEXT_ENDBUF_CONSTRAINT, WORD_DELIM = WORD_DELIM_CONSTRAINT, NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT } re_context_type; typedef struct { int alloc; int nelem; int *elems; } re_node_set; typedef enum { NON_TYPE = 0, /* Node type, These are used by token, node, tree. */ CHARACTER = 1, END_OF_RE = 2, SIMPLE_BRACKET = 3, OP_BACK_REF = 4, OP_PERIOD = 5, #ifdef RE_ENABLE_I18N COMPLEX_BRACKET = 6, OP_UTF8_PERIOD = 7, #endif /* RE_ENABLE_I18N */ /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used when the debugger shows values of this enum type. */ #define EPSILON_BIT 8 OP_OPEN_SUBEXP = EPSILON_BIT | 0, OP_CLOSE_SUBEXP = EPSILON_BIT | 1, OP_ALT = EPSILON_BIT | 2, OP_DUP_ASTERISK = EPSILON_BIT | 3, OP_DUP_PLUS = EPSILON_BIT | 4, OP_DUP_QUESTION = EPSILON_BIT | 5, ANCHOR = EPSILON_BIT | 6, OP_DELETED_SUBEXP = EPSILON_BIT | 7, /* Tree type, these are used only by tree. */ CONCAT = 16, /* Token type, these are used only by token. */ OP_OPEN_BRACKET = 17, OP_CLOSE_BRACKET, OP_CHARSET_RANGE, OP_OPEN_DUP_NUM, OP_CLOSE_DUP_NUM, OP_NON_MATCH_LIST, OP_OPEN_COLL_ELEM, OP_CLOSE_COLL_ELEM, OP_OPEN_EQUIV_CLASS, OP_CLOSE_EQUIV_CLASS, OP_OPEN_CHAR_CLASS, OP_CLOSE_CHAR_CLASS, OP_WORD, OP_NOTWORD, OP_SPACE, OP_NOTSPACE, BACK_SLASH } re_token_type_t; #ifdef RE_ENABLE_I18N typedef struct { /* Multibyte characters. */ wchar_t *mbchars; /* Collating symbols. */ # ifdef _LIBC int32_t *coll_syms; # endif /* Equivalence classes. */ # ifdef _LIBC int32_t *equiv_classes; # endif /* Range expressions. */ # ifdef _LIBC uint32_t *range_starts; uint32_t *range_ends; # else /* not _LIBC */ wchar_t *range_starts; wchar_t *range_ends; # endif /* not _LIBC */ /* Character classes. */ wctype_t *char_classes; /* If this character set is the non-matching list. */ unsigned int non_match : 1; /* # of multibyte characters. */ int nmbchars; /* # of collating symbols. */ int ncoll_syms; /* # of equivalence classes. */ int nequiv_classes; /* # of range expressions. */ int nranges; /* # of character classes. */ int nchar_classes; } re_charset_t; #endif /* RE_ENABLE_I18N */ typedef struct { union { unsigned char c; /* for CHARACTER */ re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ #ifdef RE_ENABLE_I18N re_charset_t *mbcset; /* for COMPLEX_BRACKET */ #endif /* RE_ENABLE_I18N */ int idx; /* for BACK_REF */ re_context_type ctx_type; /* for ANCHOR */ } opr; #if __GNUC__ >= 2 re_token_type_t type : 8; #else re_token_type_t type; #endif unsigned int constraint : 10; /* context constraint */ unsigned int duplicated : 1; unsigned int opt_subexp : 1; #ifdef RE_ENABLE_I18N /* These 2 bits can be moved into the union if needed (e.g. if running out of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ unsigned int mb_partial : 1; #endif unsigned int word_char : 1; } re_token_t; #define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) #define ACCEPT_MB_NODE(type) \ ((type) >= OP_PERIOD && (type) <= OP_UTF8_PERIOD) struct re_string_t { /* Indicate the raw buffer which is the original string passed as an argument of regexec(), re_search(), etc.. */ const unsigned char *raw_mbs; /* Store the multibyte string. In case of "case insensitive mode" like REG_ICASE, upper cases of the string are stored, otherwise MBS points the same address that RAW_MBS points. */ unsigned char *mbs; #ifdef RE_ENABLE_I18N /* Store the wide character string which is corresponding to MBS. */ wint_t *wcs; int *offsets; mbstate_t cur_state; #endif /* Index in RAW_MBS. Each character mbs[i] corresponds to raw_mbs[raw_mbs_idx + i]. */ int raw_mbs_idx; /* The length of the valid characters in the buffers. */ int valid_len; /* The corresponding number of bytes in raw_mbs array. */ int valid_raw_len; /* The length of the buffers MBS and WCS. */ int bufs_len; /* The index in MBS, which is updated by re_string_fetch_byte. */ int cur_idx; /* length of RAW_MBS array. */ int raw_len; /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ int len; /* End of the buffer may be shorter than its length in the cases such as re_match_2, re_search_2. Then, we use STOP for end of the buffer instead of LEN. */ int raw_stop; /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ int stop; /* The context of mbs[0]. We store the context independently, since the context of mbs[0] may be different from raw_mbs[0], which is the beginning of the input string. */ unsigned int tip_context; /* The translation passed as a part of an argument of re_compile_pattern. */ unsigned RE_TRANSLATE_TYPE trans; /* Copy of re_dfa_t's word_char. */ re_const_bitset_ptr_t word_char; /* 1 if REG_ICASE. */ unsigned char icase; unsigned char is_utf8; unsigned char map_notascii; unsigned char mbs_allocated; unsigned char offsets_needed; unsigned char newline_anchor; unsigned char word_ops_used; int mb_cur_max; }; typedef struct re_string_t re_string_t; struct re_dfa_t; typedef struct re_dfa_t re_dfa_t; #ifndef _LIBC # ifdef __i386__ # define internal_function __attribute ((regparm (3), stdcall)) # else # define internal_function # endif #endif #ifndef RE_NO_INTERNAL_PROTOTYPES static reg_errcode_t re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) internal_function; static reg_errcode_t re_string_construct (re_string_t *pstr, const char *str, int len, RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) internal_function; static reg_errcode_t re_string_reconstruct (re_string_t *pstr, int idx, int eflags) internal_function; static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) internal_function; # ifdef RE_ENABLE_I18N static void build_wcs_buffer (re_string_t *pstr) internal_function; static int build_wcs_upper_buffer (re_string_t *pstr) internal_function; # endif /* RE_ENABLE_I18N */ static void build_upper_buffer (re_string_t *pstr) internal_function; static void re_string_translate_buffer (re_string_t *pstr) internal_function; static void re_string_destruct (re_string_t *pstr) internal_function; # ifdef RE_ENABLE_I18N static int re_string_elem_size_at (const re_string_t *pstr, int idx) internal_function __attribute ((pure)); static inline int re_string_char_size_at (const re_string_t *pstr, int idx) internal_function __attribute ((pure)); static inline wint_t re_string_wchar_at (const re_string_t *pstr, int idx) internal_function __attribute ((pure)); # endif /* RE_ENABLE_I18N */ static unsigned int re_string_context_at (const re_string_t *input, int idx, int eflags) internal_function __attribute ((pure)); static unsigned char re_string_peek_byte_case (const re_string_t *pstr, int idx) internal_function __attribute ((pure)); static unsigned char re_string_fetch_byte_case (re_string_t *pstr) internal_function __attribute ((pure)); #endif #define re_string_peek_byte(pstr, offset) \ ((pstr)->mbs[(pstr)->cur_idx + offset]) #define re_string_fetch_byte(pstr) \ ((pstr)->mbs[(pstr)->cur_idx++]) #define re_string_first_byte(pstr, idx) \ ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) #define re_string_is_single_byte_char(pstr, idx) \ ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ || (pstr)->wcs[(idx) + 1] != WEOF)) #define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) #define re_string_cur_idx(pstr) ((pstr)->cur_idx) #define re_string_get_buffer(pstr) ((pstr)->mbs) #define re_string_length(pstr) ((pstr)->len) #define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) #define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) #define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) #define re_free(p) free (p) struct bin_tree_t { struct bin_tree_t *parent; struct bin_tree_t *left; struct bin_tree_t *right; /* `node_idx' is the index in dfa->nodes, if `type' == 0. Otherwise `type' indicate the type of this node. */ re_token_type_t type; int node_idx; int first; int next; re_node_set eclosure; }; typedef struct bin_tree_t bin_tree_t; #define BIN_TREE_STORAGE_SIZE \ ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) struct bin_tree_storage_t { struct bin_tree_storage_t *next; bin_tree_t data[BIN_TREE_STORAGE_SIZE]; }; typedef struct bin_tree_storage_t bin_tree_storage_t; #define CONTEXT_WORD 1 #define CONTEXT_NEWLINE (CONTEXT_WORD << 1) #define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) #define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) #define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) #define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) #define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) #define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) #define IS_ORDINARY_CONTEXT(c) ((c) == 0) #define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') #define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) #define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_') #define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) #define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) #define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) struct re_dfastate_t { unsigned int hash; re_node_set nodes; re_node_set non_eps_nodes; re_node_set inveclosure; re_node_set *entrance_nodes; struct re_dfastate_t **trtable; unsigned int context : 4; unsigned int halt : 1; /* If this state can accept `multi byte'. Note that we refer to multibyte characters, and multi character collating elements as `multi byte'. */ unsigned int accept_mb : 1; /* If this state has backreference node(s). */ unsigned int has_backref : 1; unsigned int has_constraint : 1; unsigned int word_trtable : 1; }; typedef struct re_dfastate_t re_dfastate_t; struct re_state_table_entry { int num; int alloc; re_dfastate_t **array; }; /* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ typedef struct { int next_idx; int alloc; re_dfastate_t **array; } state_array_t; /* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ typedef struct { int node; int str_idx; /* The position NODE match at. */ state_array_t path; } re_sub_match_last_t; /* Store information about the node NODE whose type is OP_OPEN_SUBEXP. And information about the node, whose type is OP_CLOSE_SUBEXP, corresponding to NODE is stored in LASTS. */ typedef struct { int str_idx; int node; int next_last_offset; state_array_t *path; int alasts; /* Allocation size of LASTS. */ int nlasts; /* The number of LASTS. */ re_sub_match_last_t **lasts; } re_sub_match_top_t; struct re_backref_cache_entry { int node; int str_idx; int subexp_from; int subexp_to; char more; char unused; unsigned short int eps_reachable_subexps_map; }; typedef struct { /* The string object corresponding to the input string. */ re_string_t input; #if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) re_dfa_t *const dfa; #else re_dfa_t *dfa; #endif /* EFLAGS of the argument of regexec. */ int eflags; /* Where the matching ends. */ int match_last; int last_node; /* The state log used by the matcher. */ re_dfastate_t **state_log; int state_log_top; /* Back reference cache. */ int nbkref_ents; int abkref_ents; struct re_backref_cache_entry *bkref_ents; int max_mb_elem_len; int nsub_tops; int asub_tops; re_sub_match_top_t **sub_tops; } re_match_context_t; typedef struct { re_dfastate_t **sifted_states; re_dfastate_t **limited_states; int last_node; int last_str_idx; re_node_set limits; } re_sift_context_t; struct re_fail_stack_ent_t { int idx; int node; regmatch_t *regs; re_node_set eps_via_nodes; }; struct re_fail_stack_t { int num; int alloc; struct re_fail_stack_ent_t *stack; }; struct re_dfa_t { re_token_t *nodes; int nodes_alloc; int nodes_len; int *nexts; int *org_indices; re_node_set *edests; re_node_set *eclosures; re_node_set *inveclosures; struct re_state_table_entry *state_table; re_dfastate_t *init_state; re_dfastate_t *init_state_word; re_dfastate_t *init_state_nl; re_dfastate_t *init_state_begbuf; bin_tree_t *str_tree; bin_tree_storage_t *str_tree_storage; re_bitset_ptr_t sb_char; int str_tree_storage_idx; /* number of subexpressions `re_nsub' is in regex_t. */ unsigned int state_hash_mask; int states_alloc; int init_node; int nbackref; /* The number of backreference in this dfa. */ /* Bitmap expressing which backreference is used. */ unsigned int used_bkref_map; unsigned int completed_bkref_map; unsigned int has_plural_match : 1; /* If this dfa has "multibyte node", which is a backreference or a node which can accept multibyte character or multi character collating element. */ unsigned int has_mb_node : 1; unsigned int is_utf8 : 1; unsigned int map_notascii : 1; unsigned int word_ops_used : 1; int mb_cur_max; bitset word_char; reg_syntax_t syntax; int *subexp_map; #ifdef DEBUG char* re_str; #endif }; #ifndef RE_NO_INTERNAL_PROTOTYPES static reg_errcode_t re_node_set_alloc (re_node_set *set, int size) internal_function; static reg_errcode_t re_node_set_init_1 (re_node_set *set, int elem) internal_function; static reg_errcode_t re_node_set_init_2 (re_node_set *set, int elem1, int elem2) internal_function; #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) static reg_errcode_t re_node_set_init_copy (re_node_set *dest, const re_node_set *src) internal_function; static reg_errcode_t re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, const re_node_set *src2) internal_function; static reg_errcode_t re_node_set_init_union (re_node_set *dest, const re_node_set *src1, const re_node_set *src2) internal_function; static reg_errcode_t re_node_set_merge (re_node_set *dest, const re_node_set *src) internal_function; static int re_node_set_insert (re_node_set *set, int elem) internal_function; static int re_node_set_insert_last (re_node_set *set, int elem) internal_function; static int re_node_set_compare (const re_node_set *set1, const re_node_set *set2) internal_function __attribute ((pure)); static int re_node_set_contains (const re_node_set *set, int elem) internal_function __attribute ((pure)); static void re_node_set_remove_at (re_node_set *set, int idx) internal_function; #define re_node_set_remove(set,id) \ (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) #define re_node_set_empty(p) ((p)->nelem = 0) #define re_node_set_free(set) re_free ((set)->elems) static int re_dfa_add_node (re_dfa_t *dfa, re_token_t token, int mode) internal_function; static re_dfastate_t *re_acquire_state (reg_errcode_t *err, re_dfa_t *dfa, const re_node_set *nodes) internal_function; static re_dfastate_t *re_acquire_state_context (reg_errcode_t *err, re_dfa_t *dfa, const re_node_set *nodes, unsigned int context) internal_function; static void free_state (re_dfastate_t *state) internal_function; #endif typedef enum { SB_CHAR, MB_CHAR, EQUIV_CLASS, COLL_SYM, CHAR_CLASS } bracket_elem_type; typedef struct { bracket_elem_type type; union { unsigned char ch; unsigned char *name; wchar_t wch; } opr; } bracket_elem_t; /* Inline functions for bitset operation. */ static inline void bitset_not (bitset set) { int bitset_i; for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i) set[bitset_i] = ~set[bitset_i]; } static inline void bitset_merge (bitset dest, const bitset src) { int bitset_i; for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i) dest[bitset_i] |= src[bitset_i]; } static inline void bitset_not_merge (bitset dest, const bitset src) { int i; for (i = 0; i < BITSET_UINTS; ++i) dest[i] |= ~src[i]; } static inline void bitset_mask (bitset dest, const bitset src) { int bitset_i; for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i) dest[bitset_i] &= src[bitset_i]; } #if defined RE_ENABLE_I18N && !defined RE_NO_INTERNAL_PROTOTYPES /* Inline functions for re_string. */ static inline int internal_function re_string_char_size_at (const re_string_t *pstr, int idx) { int byte_idx; if (pstr->mb_cur_max == 1) return 1; for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) if (pstr->wcs[idx + byte_idx] != WEOF) break; return byte_idx; } static inline wint_t internal_function re_string_wchar_at (const re_string_t *pstr, int idx) { if (pstr->mb_cur_max == 1) return (wint_t) pstr->mbs[idx]; return (wint_t) pstr->wcs[idx]; } static int internal_function re_string_elem_size_at (const re_string_t *pstr, int idx) { #ifdef _LIBC const unsigned char *p, *extra; const int32_t *table, *indirect; int32_t tmp; # include uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) { table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); p = pstr->mbs + idx; tmp = findidx (&p); return p - pstr->mbs - idx; } else #endif /* _LIBC */ return 1; } #endif /* RE_ENABLE_I18N */ #endif /* _REGEX_INTERNAL_H */ uqm-0.6.2/sc2/src/regex/regex.h0000600000175000017500000005347710543202107014674 0ustar joeyjoey/* Definitions for data structures and routines for the regular expression library. Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _REGEX_H #define _REGEX_H 1 #include /* Allow the use in C++ code. */ #ifdef __cplusplus extern "C" { #endif /* POSIX says that must be included (by the caller) before . */ #if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS /* VMS doesn't have `size_t' in , even though POSIX says it should be there. */ # include #endif /* The following two types have to be signed and unsigned integer type wide enough to hold a value of a pointer. For most ANSI compilers ptrdiff_t and size_t should be likely OK. Still size of these two types is 2 for Microsoft C. Ugh... */ typedef long int s_reg_t; typedef unsigned long int active_reg_t; /* The following bits are used to determine the regexp syntax we recognize. The set/not-set meanings are chosen so that Emacs syntax remains the value 0. The bits are given in alphabetical order, and the definitions shifted by one from the previous bit; thus, when we add or remove a bit, only one other definition need change. */ typedef unsigned long int reg_syntax_t; /* If this bit is not set, then \ inside a bracket expression is literal. If set, then such a \ quotes the following character. */ #define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) /* If this bit is not set, then + and ? are operators, and \+ and \? are literals. If set, then \+ and \? are operators and + and ? are literals. */ #define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) /* If this bit is set, then character classes are supported. They are: [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. If not set, then character classes are not supported. */ #define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) /* If this bit is set, then ^ and $ are always anchors (outside bracket expressions, of course). If this bit is not set, then it depends: ^ is an anchor if it is at the beginning of a regular expression or after an open-group or an alternation operator; $ is an anchor if it is at the end of a regular expression, or before a close-group or an alternation operator. This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because POSIX draft 11.2 says that * etc. in leading positions is undefined. We already implemented a previous draft which made those constructs invalid, though, so we haven't changed the code back. */ #define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) /* If this bit is set, then special characters are always special regardless of where they are in the pattern. If this bit is not set, then special characters are special only in some contexts; otherwise they are ordinary. Specifically, * + ? and intervals are only special when not after the beginning, open-group, or alternation operator. */ #define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) /* If this bit is set, then *, +, ?, and { cannot be first in an re or immediately after an alternation or begin-group operator. */ #define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) /* If this bit is set, then . matches newline. If not set, then it doesn't. */ #define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) /* If this bit is set, then . doesn't match NUL. If not set, then it does. */ #define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) /* If this bit is set, nonmatching lists [^...] do not match newline. If not set, they do. */ #define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) /* If this bit is set, either \{...\} or {...} defines an interval, depending on RE_NO_BK_BRACES. If not set, \{, \}, {, and } are literals. */ #define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) /* If this bit is set, +, ? and | aren't recognized as operators. If not set, they are. */ #define RE_LIMITED_OPS (RE_INTERVALS << 1) /* If this bit is set, newline is an alternation operator. If not set, newline is literal. */ #define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) /* If this bit is set, then `{...}' defines an interval, and \{ and \} are literals. If not set, then `\{...\}' defines an interval. */ #define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) /* If this bit is set, (...) defines a group, and \( and \) are literals. If not set, \(...\) defines a group, and ( and ) are literals. */ #define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) /* If this bit is set, then \ matches . If not set, then \ is a back-reference. */ #define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) /* If this bit is set, then | is an alternation operator, and \| is literal. If not set, then \| is an alternation operator, and | is literal. */ #define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) /* If this bit is set, then an ending range point collating higher than the starting range point, as in [z-a], is invalid. If not set, then when ending range point collates higher than the starting range point, the range is ignored. */ #define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) /* If this bit is set, then an unmatched ) is ordinary. If not set, then an unmatched ) is invalid. */ #define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) /* If this bit is set, succeed as soon as we match the whole pattern, without further backtracking. */ #define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) /* If this bit is set, do not process the GNU regex operators. If not set, then the GNU regex operators are recognized. */ #define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) /* If this bit is set, turn on internal regex debugging. If not set, and debugging was on, turn it off. This only works if regex.c is compiled -DDEBUG. We define this bit always, so that all that's needed to turn on debugging is to recompile regex.c; the calling code can always have this bit set, and it won't affect anything in the normal case. */ #define RE_DEBUG (RE_NO_GNU_OPS << 1) /* If this bit is set, a syntactically invalid interval is treated as a string of ordinary characters. For example, the ERE 'a{1' is treated as 'a\{1'. */ #define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) /* If this bit is set, then ignore case when matching. If not set, then case is significant. */ #define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) /* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only for ^, because it is difficult to scan the regex backwards to find whether ^ should be special. */ #define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) /* If this bit is set, then \{ cannot be first in an bre or immediately after an alternation or begin-group operator. */ #define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) /* If this bit is set, then no_sub will be set to 1 during re_compile_pattern. */ #define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) /* This global variable defines the particular regexp syntax to use (for some interfaces). When a regexp is compiled, the syntax used is stored in the pattern buffer, so changing this does not affect already-compiled regexps. */ extern reg_syntax_t re_syntax_options; /* Define combinations of the above bits for the standard possibilities. (The [[[ comments delimit what gets put into the Texinfo file, so don't delete them!) */ /* [[[begin syntaxes]]] */ #define RE_SYNTAX_EMACS 0 #define RE_SYNTAX_AWK \ (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) #define RE_SYNTAX_GNU_AWK \ ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ | RE_CONTEXT_INVALID_OPS )) #define RE_SYNTAX_POSIX_AWK \ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ | RE_INTERVALS | RE_NO_GNU_OPS) #define RE_SYNTAX_GREP \ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ | RE_NEWLINE_ALT) #define RE_SYNTAX_EGREP \ (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ | RE_NO_BK_VBAR) #define RE_SYNTAX_POSIX_EGREP \ (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ | RE_INVALID_INTERVAL_ORD) /* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ #define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC #define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC /* Syntax bits common to both basic and extended POSIX regex syntax. */ #define _RE_SYNTAX_POSIX_COMMON \ (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ | RE_INTERVALS | RE_NO_EMPTY_RANGES) #define RE_SYNTAX_POSIX_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this isn't minimal, since other operators, such as \`, aren't disabled. */ #define RE_SYNTAX_POSIX_MINIMAL_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) #define RE_SYNTAX_POSIX_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) /* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is removed and RE_NO_BK_REFS is added. */ #define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) /* [[[end syntaxes]]] */ /* Maximum number of duplicates an interval can allow. Some systems (erroneously) define this in other header files, but we want our value, so remove any previous define. */ #ifdef RE_DUP_MAX # undef RE_DUP_MAX #endif /* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ #define RE_DUP_MAX (0x7fff) /* POSIX `cflags' bits (i.e., information for `regcomp'). */ /* If this bit is set, then use extended regular expression syntax. If not set, then use basic regular expression syntax. */ #define REG_EXTENDED 1 /* If this bit is set, then ignore case when matching. If not set, then case is significant. */ #define REG_ICASE (REG_EXTENDED << 1) /* If this bit is set, then anchors do not match at newline characters in the string. If not set, then anchors do match at newlines. */ #define REG_NEWLINE (REG_ICASE << 1) /* If this bit is set, then report only success or fail in regexec. If not set, then returns differ between not matching and errors. */ #define REG_NOSUB (REG_NEWLINE << 1) /* POSIX `eflags' bits (i.e., information for regexec). */ /* If this bit is set, then the beginning-of-line operator doesn't match the beginning of the string (presumably because it's not the beginning of a line). If not set, then the beginning-of-line operator does match the beginning of the string. */ #define REG_NOTBOL 1 /* Like REG_NOTBOL, except for the end-of-line. */ #define REG_NOTEOL (1 << 1) /* Use PMATCH[0] to delimit the start and end of the search in the buffer. */ #define REG_STARTEND (1 << 2) /* If any error codes are removed, changed, or added, update the `re_error_msg' table in regex.c. */ typedef enum { #ifdef _XOPEN_SOURCE REG_ENOSYS = -1, /* This will never happen for this implementation. */ #endif REG_NOERROR = 0, /* Success. */ REG_NOMATCH, /* Didn't find a match (for regexec). */ /* POSIX regcomp return error codes. (In the order listed in the standard.) */ REG_BADPAT, /* Invalid pattern. */ REG_ECOLLATE, /* Inalid collating element. */ REG_ECTYPE, /* Invalid character class name. */ REG_EESCAPE, /* Trailing backslash. */ REG_ESUBREG, /* Invalid back reference. */ REG_EBRACK, /* Unmatched left bracket. */ REG_EPAREN, /* Parenthesis imbalance. */ REG_EBRACE, /* Unmatched \{. */ REG_BADBR, /* Invalid contents of \{\}. */ REG_ERANGE, /* Invalid range end. */ REG_ESPACE, /* Ran out of memory. */ REG_BADRPT, /* No preceding re for repetition op. */ /* Error codes we've added. */ REG_EEND, /* Premature end. */ REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ } reg_errcode_t; /* This data structure represents a compiled pattern. Before calling the pattern compiler, the fields `buffer', `allocated', `fastmap', `translate', and `no_sub' can be set. After the pattern has been compiled, the `re_nsub' field is available. All other fields are private to the regex routines. */ #ifndef RE_TRANSLATE_TYPE # define RE_TRANSLATE_TYPE char * #endif struct re_pattern_buffer { /* [[[begin pattern_buffer]]] */ /* Space that holds the compiled pattern. It is declared as `unsigned char *' because its elements are sometimes used as array indexes. */ unsigned char *buffer; /* Number of bytes to which `buffer' points. */ unsigned long int allocated; /* Number of bytes actually used in `buffer'. */ unsigned long int used; /* Syntax setting with which the pattern was compiled. */ reg_syntax_t syntax; /* Pointer to a fastmap, if any, otherwise zero. re_search uses the fastmap, if there is one, to skip over impossible starting points for matches. */ char *fastmap; /* Either a translate table to apply to all characters before comparing them, or zero for no translation. The translation is applied to a pattern when it is compiled and to a string when it is matched. */ RE_TRANSLATE_TYPE translate; /* Number of subexpressions found by the compiler. */ size_t re_nsub; /* Zero if this pattern cannot match the empty string, one else. Well, in truth it's used only in `re_search_2', to see whether or not we should use the fastmap, so we don't set this absolutely perfectly; see `re_compile_fastmap' (the `duplicate' case). */ unsigned can_be_null : 1; /* If REGS_UNALLOCATED, allocate space in the `regs' structure for `max (RE_NREGS, re_nsub + 1)' groups. If REGS_REALLOCATE, reallocate space if necessary. If REGS_FIXED, use what's there. */ #define REGS_UNALLOCATED 0 #define REGS_REALLOCATE 1 #define REGS_FIXED 2 unsigned regs_allocated : 2; /* Set to zero when `regex_compile' compiles a pattern; set to one by `re_compile_fastmap' if it updates the fastmap. */ unsigned fastmap_accurate : 1; /* If set, `re_match_2' does not return information about subexpressions. */ unsigned no_sub : 1; /* If set, a beginning-of-line anchor doesn't match at the beginning of the string. */ unsigned not_bol : 1; /* Similarly for an end-of-line anchor. */ unsigned not_eol : 1; /* If true, an anchor at a newline matches. */ unsigned newline_anchor : 1; /* [[[end pattern_buffer]]] */ }; typedef struct re_pattern_buffer regex_t; /* Type for byte offsets within the string. POSIX mandates this. */ typedef int regoff_t; /* This is the structure we store register match data in. See regex.texinfo for a full description of what registers match. */ struct re_registers { unsigned num_regs; regoff_t *start; regoff_t *end; }; /* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, `re_match_2' returns information about at least this many registers the first time a `regs' structure is passed. */ #ifndef RE_NREGS # define RE_NREGS 30 #endif /* POSIX specification for registers. Aside from the different names than `re_registers', POSIX uses an array of structures, instead of a structure of arrays. */ typedef struct { regoff_t rm_so; /* Byte offset from string's start to substring's start. */ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ } regmatch_t; /* Declarations for routines. */ /* To avoid duplicating every routine declaration -- once with a prototype (if we are ANSI), and once without (if we aren't) -- we use the following macro to declare argument types. This unfortunately clutters up the declarations a bit, but I think it's worth it. */ #if __STDC__ # define _RE_ARGS(args) args #else /* not __STDC__ */ # define _RE_ARGS(args) () #endif /* not __STDC__ */ /* Sets the current default syntax to SYNTAX, and return the old syntax. You can also simply assign to the `re_syntax_options' variable. */ extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); /* Compile the regular expression PATTERN, with length LENGTH and syntax given by the global `re_syntax_options', into the buffer BUFFER. Return NULL if successful, and an error string if not. */ extern const char *re_compile_pattern _RE_ARGS ((const char *pattern, size_t length, struct re_pattern_buffer *buffer)); /* Compile a fastmap for the compiled pattern in BUFFER; used to accelerate searches. Return 0 if successful and -2 if was an internal error. */ extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); /* Search in the string STRING (with length LENGTH) for the pattern compiled into BUFFER. Start searching at position START, for RANGE characters. Return the starting position of the match, -1 for no match, or -2 for an internal error. Also return register information in REGS (if REGS and BUFFER->no_sub are nonzero). */ extern int re_search _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, int length, int start, int range, struct re_registers *regs)); /* Like `re_search', but search in the concatenation of STRING1 and STRING2. Also, stop searching at index START + STOP. */ extern int re_search_2 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, int length1, const char *string2, int length2, int start, int range, struct re_registers *regs, int stop)); /* Like `re_search', but return how many characters in STRING the regexp in BUFFER matched, starting at position START. */ extern int re_match _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, int length, int start, struct re_registers *regs)); /* Relates to `re_match' as `re_search_2' relates to `re_search'. */ extern int re_match_2 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, int length1, const char *string2, int length2, int start, struct re_registers *regs, int stop)); /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated with malloc, and must each be at least `NUM_REGS * sizeof (regoff_t)' bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ extern void re_set_registers _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, unsigned num_regs, regoff_t *starts, regoff_t *ends)); #if defined _REGEX_RE_COMP || defined _LIBC # ifndef _CRAY /* 4.2 bsd compatibility. */ extern char *re_comp _RE_ARGS ((const char *)); extern int re_exec _RE_ARGS ((const char *)); # endif #endif /* GCC 2.95 and later have "__restrict"; C99 compilers have "restrict", and "configure" may have defined "restrict". */ #ifndef __restrict # if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) # if defined restrict || 199901L <= __STDC_VERSION__ # define __restrict restrict # else # define __restrict # endif # endif #endif /* gcc 3.1 and up support the [restrict] syntax. */ #ifndef __restrict_arr # if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) # define __restrict_arr __restrict # else # define __restrict_arr # endif #endif /* POSIX compatibility. */ extern int regcomp _RE_ARGS ((regex_t *__restrict __preg, const char *__restrict __pattern, int __cflags)); extern int regexec _RE_ARGS ((const regex_t *__restrict __preg, const char *__restrict __string, size_t __nmatch, regmatch_t __pmatch[__restrict_arr], int __eflags)); extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg, char *__errbuf, size_t __errbuf_size)); extern void regfree _RE_ARGS ((regex_t *__preg)); #ifdef __cplusplus } #endif /* C++ */ #endif /* regex.h */ /* Local variables: make-backup-files: t version-control: t trim-versions-without-asking: nil End: */ uqm-0.6.2/sc2/src/starcon2.c0000600000175000017500000006712210543202107014166 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_GETOPT_LONG # include #else # include "getopt/getopt.h" #endif #include "libs/graphics/gfx_common.h" #include "libs/sound/sound.h" #include "libs/input/input_common.h" #include "libs/tasklib.h" #include "controls.h" #include "file.h" #include "port.h" #include "libs/platform.h" #include "libs/log.h" #include "options.h" #include "uqmversion.h" #include "comm.h" #ifdef NETPLAY # include "libs/callback.h" # include "libs/alarm.h" # include "libs/net.h" # include "netplay/netoptions.h" # include "netplay/netplay.h" #endif #include "setup.h" #include "starcon.h" #if defined (GFXMODULE_SDL) # include SDL_INCLUDE(SDL.h) // Including this is actually necessary on OSX. #endif struct options_struct { const char *logFile; enum { runMode_normal, runMode_usage, runMode_version, } runMode; int gfxDriver; int gfxFlags; int soundDriver; int soundFlags; int width; int height; const char *configDir; const char *contentDir; const char **addons; int numAddons; int gammaSet; float gamma; int whichMusic; int whichCoarseScan; int whichMenu; int whichFonts; int whichIntro; int whichShield; int smoothScroll; int meleeScale; BOOLEAN subTitles; BOOLEAN stereoSFX; float musicVolumeScale; float sfxVolumeScale; float speechVolumeScale; }; static int preParseOptions (int argc, char *argv[], struct options_struct *options); static int parseOptions (int argc, char *argv[], struct options_struct *options); static void usage (FILE *out, const struct options_struct *defaultOptions); static int parseIntOption (const char *str, int *result, const char *optName); static int parseFloatOption (const char *str, float *f, const char *optName); static int parseVolume (const char *str, float *vol, const char *optName); static int InvalidArgument (const char *supplied, const char *opt_name); static int Check_PC_3DO_opt (const char *value, DWORD mask, const char *opt, int *result); static const char *PC_3DO_optString (DWORD optMask); int main (int argc, char *argv[]) { struct options_struct options = { /* .logFile = */ NULL, /* .runMode = */ runMode_normal, /* .gfxdriver = */ TFB_GFXDRIVER_SDL_PURE, /* .gfxflags = */ 0, /* .soundDriver = */ audio_DRIVER_MIXSDL, /* .soundFlags = */ audio_QUALITY_MEDIUM, /* .width = */ 640, /* .height = */ 480, /* .configDir = */ NULL, /* .contentDir = */ NULL, /* .addons = */ NULL, /* .numAddons = */ 0, /* .gammaSet = */ 0, /* .gamma = */ 0.0f, /* .whichMusic = */ OPT_3DO, /* .whichCoarseScan = */ OPT_PC, /* .whichMenu = */ OPT_PC, /* .whichFont = */ OPT_PC, /* .whichIntro = */ OPT_3DO, /* .whichShield = */ OPT_PC, /* .smoothScroll = */ OPT_PC, /* .meleeScale = */ TFB_SCALE_TRILINEAR, /* .subtitles = */ TRUE, /* .stereoSFX = */ FALSE, /* .musicVolumeScale = */ 1.0f, /* .sfxVolumeScale = */ 1.0f, /* .speechVolumeScale = */ 1.0f, }; int optionsResult; log_init (15); optionsResult = preParseOptions (argc, argv, &options); if (optionsResult != 0) { // TODO: various uninitialisations return optionsResult; } if (options.logFile != NULL) { int i; freopen (options.logFile, "w", stderr); for (i = 0; i < argc; ++i) log_add (log_User, "argv[%d] = [%s]", i, argv[i]); } if (options.runMode == runMode_version) { printf ("%d.%d.%d%s\n", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION); log_showBox (false, false); return EXIT_SUCCESS; } log_add (log_User, "The Ur-Quan Masters v%d.%d.%d%s (compiled %s %s)\n" "This software comes with ABSOLUTELY NO WARRANTY;\n" "for details see the included 'COPYING' file.\n", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION, __DATE__, __TIME__); #ifdef NETPLAY log_add (log_User, "Netplay protocol version %d.%d. Requiring remote " "UQM version %d.%d.%d.", NETPLAY_PROTOCOL_VERSION_MAJOR, NETPLAY_PROTOCOL_VERSION_MINOR, NETPLAY_MIN_UQM_VERSION_MAJOR, NETPLAY_MIN_UQM_VERSION_MINOR, NETPLAY_MIN_UQM_VERSION_PATCH); #endif if (options.runMode == runMode_usage) { usage (stdout, &options); log_showBox (true, false); return EXIT_SUCCESS; } /* mem_init () uses mutexes. Mutex creation cannot use the memory system until the memory system is rewritten to rely on a thread-safe allocator. */ TFB_PreInit (); mem_init (); InitThreadSystem (); log_initThreads (); initIO (); prepareConfigDir (options.configDir); PlayerOne = CONTROL_TEMPLATE_KB_1; PlayerTwo = CONTROL_TEMPLATE_JOY_1; // Fill in the options struct based on uqm.cfg res_LoadFilename (configDir, "uqm.cfg"); if (res_HasKey ("config.reswidth")) { options.width = res_GetInteger ("config.reswidth"); } if (res_HasKey ("config.resheight")) { options.height = res_GetInteger ("config.resheight"); } if (res_HasKey ("config.alwaysgl")) { if (res_GetBoolean ("config.alwaysgl")) { options.gfxDriver = TFB_GFXDRIVER_SDL_OPENGL; } } if (res_HasKey ("config.usegl")) { options.gfxDriver = res_GetBoolean ("config.usegl") ? TFB_GFXDRIVER_SDL_OPENGL : TFB_GFXDRIVER_SDL_PURE; } if (res_HasKey ("config.scaler")) { const char *optarg = res_GetString ("config.scaler"); if (!strcmp (optarg, "bilinear")) options.gfxFlags |= TFB_GFXFLAGS_SCALE_BILINEAR; else if (!strcmp (optarg, "biadapt")) options.gfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPT; else if (!strcmp (optarg, "biadv")) options.gfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPTADV; else if (!strcmp (optarg, "triscan")) options.gfxFlags |= TFB_GFXFLAGS_SCALE_TRISCAN; else if (!strcmp (optarg, "hq")) options.gfxFlags |= TFB_GFXFLAGS_SCALE_HQXX; } if (res_HasKey ("config.scanlines") && res_GetBoolean ("config.scanlines")) { options.gfxFlags |= TFB_GFXFLAGS_SCANLINES; } if (res_HasKey ("config.fullscreen") && res_GetBoolean ("config.fullscreen")) { options.gfxFlags |= TFB_GFXFLAGS_FULLSCREEN; } if (res_HasKey ("config.subtitles")) { options.subTitles = res_GetBoolean ("config.subtitles"); } if (res_HasKey ("config.textmenu")) { options.whichMenu = res_GetBoolean ("config.textmenu") ? OPT_PC : OPT_3DO; } if (res_HasKey ("config.textgradients")) { options.whichFonts = res_GetBoolean ("config.textgradients") ? OPT_PC : OPT_3DO; } if (res_HasKey ("config.iconicscan")) { options.whichCoarseScan = res_GetBoolean ("config.iconicscan") ? OPT_3DO : OPT_PC; } if (res_HasKey ("config.smoothscroll")) { options.smoothScroll = res_GetBoolean ("config.smoothscroll") ? OPT_3DO : OPT_PC; } if (res_HasKey ("config.3domusic")) { options.whichMusic = res_GetBoolean ("config.3domusic") ? OPT_3DO : OPT_PC; } if (res_HasKey ("config.3domovies")) { options.whichIntro = res_GetBoolean ("config.3domovies") ? OPT_3DO : OPT_PC; } if (res_HasKey ("config.showfps") && res_GetBoolean ("config.showfps")) { options.gfxFlags |= TFB_GFXFLAGS_SHOWFPS; } if (res_HasKey ("config.smoothmelee")) { options.meleeScale = res_GetBoolean ("config.smoothmelee") ? TFB_SCALE_TRILINEAR : TFB_SCALE_STEP; } if (res_HasKey ("config.positionalsfx")) { options.stereoSFX = res_GetBoolean ("config.positionalsfx"); } if (res_HasKey ("config.audiodriver")) { const char *driverstr = res_GetString ("config.audiodriver"); if (!strcmp (driverstr, "openal")) { options.soundDriver = audio_DRIVER_OPENAL; } else if (!strcmp (driverstr, "none")) { options.soundDriver = audio_DRIVER_NOSOUND; options.speechVolumeScale = 0.0f; } else if (!strcmp (driverstr, "mixsdl")) { options.soundDriver = audio_DRIVER_MIXSDL; } else { /* Can't figure it out, leave as initial default */ } } if (res_HasKey ("config.audioquality")) { const char *qstr = res_GetString ("config.audioquality"); if (!strcmp (qstr, "low")) { options.soundFlags &= ~(audio_QUALITY_MEDIUM | audio_QUALITY_HIGH); options.soundFlags |= audio_QUALITY_LOW; } else if (!strcmp (qstr, "medium")) { options.soundFlags &= ~(audio_QUALITY_HIGH | audio_QUALITY_LOW); options.soundFlags |= audio_QUALITY_MEDIUM; } else if (!strcmp (qstr, "high")) { options.soundFlags &= ~(audio_QUALITY_MEDIUM | audio_QUALITY_LOW); options.soundFlags |= audio_QUALITY_HIGH; } else { /* Can't figure it out, leave as initial default */ } } if (res_HasKey ("config.pulseshield")) { options.whichShield = res_GetBoolean ("config.pulseshield") ? OPT_3DO : OPT_PC; } if (res_HasKey ("config.player1control")) { PlayerOne = res_GetInteger ("config.player1control"); /* This is an unsigned, so no < 0 check is necessary */ if (PlayerOne >= NUM_TEMPLATES) { log_add (log_Error, "Illegal control template '%d' for Player One.", PlayerOne); PlayerOne = CONTROL_TEMPLATE_KB_1; } } if (res_HasKey ("config.player2control")) { /* This is an unsigned, so no < 0 check is necessary */ PlayerTwo = res_GetInteger ("config.player2control"); if (PlayerTwo >= NUM_TEMPLATES) { log_add (log_Error, "Illegal control template '%d' for Player Two.", PlayerTwo); PlayerTwo = CONTROL_TEMPLATE_JOY_1; } } if (res_HasKey ("config.musicvol")) { parseVolume (res_GetString ("config.musicvol"), &options.musicVolumeScale, "music volume"); } if (res_HasKey ("config.sfxvol")) { parseVolume (res_GetString ("config.sfxvol"), &options.sfxVolumeScale, "SFX volume"); } if (res_HasKey ("config.speechvol")) { parseVolume (res_GetString ("config.speechvol"), &options.speechVolumeScale, "speech volume"); } { /* init control template names */ static const char* defaultNames[] = { "Arrows", "WASD", "Arrows (2)", "ESDF", "Joystick 1", "Joystick 2" }; int i; for (i = 0; i < 6; ++i) { char cfgkey[64]; snprintf(cfgkey, sizeof(cfgkey), "config.keys.%d.name", i + 1); cfgkey[sizeof(cfgkey) - 1] = '\0'; if (res_HasKey (cfgkey)) { strncpy (input_templates[i].name, res_GetString (cfgkey), 30); input_templates[i].name[29] = 0; } else { strcpy (input_templates[i].name, defaultNames[i]); res_PutString (cfgkey, input_templates[i].name); } } } optionsResult = parseOptions (argc, argv, &options); if (optionsResult != 0) { // TODO: various uninitialisations return optionsResult; } /* TODO: Once threading is gone, these become local variables again. In the meantime, they must be global so that initAudio (in StarCon2Main) can see them. initAudio needed to be moved there because calling AssignTask in the main thread doesn't work */ snddriver = options.soundDriver; soundflags = options.soundFlags; // Fill in global variables: optWhichMusic = options.whichMusic; optWhichCoarseScan = options.whichCoarseScan; optWhichMenu = options.whichMenu; optWhichFonts = options.whichFonts; optWhichIntro = options.whichIntro; optWhichShield = options.whichShield; optSmoothScroll = options.smoothScroll; optMeleeScale = options.meleeScale; optSubtitles = options.subTitles; optStereoSFX = options.stereoSFX; musicVolumeScale = options.musicVolumeScale; sfxVolumeScale = options.sfxVolumeScale; speechVolumeScale = options.speechVolumeScale; prepareContentDir (options.contentDir, options.addons); HFree ((void *) options.addons); prepareMeleeDir (); prepareSaveDir (); initTempDir (); InitTimeSystem (); InitTaskSystem (); #ifdef NETPLAY Network_init (); Alarm_init (); Callback_init (); NetManager_init (); #endif GraphicsLock = CreateMutex ("Graphics", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); TFB_InitGraphics (options.gfxDriver, options.gfxFlags, options.width, options.height); if (options.gammaSet) TFB_SetGamma (options.gamma); InitColorMaps (); init_communication (); /* TODO: Once threading is gone, restore initAudio here. initAudio calls AssignTask, which currently blocks on ProcessThreadLifecycles... */ // initAudio (snddriver, soundflags); TFB_InitInput (TFB_INPUTDRIVER_SDL, 0); StartThread (Starcon2Main, NULL, 1024, "Starcon2Main"); for (;;) { TFB_ProcessEvents (); ProcessThreadLifecycles (); TFB_FlushGraphics (); } unInitTempDir (); uninitIO (); #ifdef NETPLAY Network_uninit (); #endif return EXIT_SUCCESS; } enum { CSCAN_OPT = 1000, MENU_OPT, FONT_OPT, SHIELD_OPT, SCROLL_OPT, SOUND_OPT, STEREOSFX_OPT, ADDON_OPT, ACCEL_OPT, #ifdef NETPLAY NETHOST1_OPT, NETPORT1_OPT, NETHOST2_OPT, NETPORT2_OPT, NETDELAY_OPT, #endif }; static const char *optString = "+r:d:foc:b:spC:n:?hM:S:T:m:q:ug:l:i:v"; static struct option longOptions[] = { {"res", 1, NULL, 'r'}, {"fullscreen", 0, NULL, 'f'}, {"opengl", 0, NULL, 'o'}, {"scale", 1, NULL, 'c'}, {"meleezoom", 1, NULL, 'b'}, {"scanlines", 0, NULL, 's'}, {"fps", 0, NULL, 'p'}, {"configdir", 1, NULL, 'C'}, {"contentdir", 1, NULL, 'n'}, {"help", 0, NULL, 'h'}, {"musicvol", 1, NULL, 'M'}, {"sfxvol", 1, NULL, 'S'}, {"speechvol", 1, NULL, 'T'}, {"audioquality", 1, NULL, 'q'}, {"nosubtitles", 0, NULL, 'u'}, {"music", 1, NULL, 'm'}, {"gamma", 1, NULL, 'g'}, {"logfile", 1, NULL, 'l'}, {"intro", 1, NULL, 'i'}, {"version", 0, NULL, 'v'}, // options with no short equivalent: {"cscan", 1, NULL, CSCAN_OPT}, {"menu", 1, NULL, MENU_OPT}, {"font", 1, NULL, FONT_OPT}, {"shield", 1, NULL, SHIELD_OPT}, {"scroll", 1, NULL, SCROLL_OPT}, {"sound", 1, NULL, SOUND_OPT}, {"stereosfx", 0, NULL, STEREOSFX_OPT}, {"addon", 1, NULL, ADDON_OPT}, {"accel", 1, NULL, ACCEL_OPT}, #ifdef NETPLAY {"nethost1", 1, NULL, NETHOST1_OPT}, {"netport1", 1, NULL, NETPORT1_OPT}, {"nethost2", 1, NULL, NETHOST2_OPT}, {"netport2", 1, NULL, NETPORT2_OPT}, {"netdelay", 1, NULL, NETDELAY_OPT}, #endif {0, 0, 0, 0} }; static int preParseOptions (int argc, char *argv[], struct options_struct *options) { /* * "pre-process" the cmdline args looking for a -l ("logfile") * option. If it was given, redirect stderr to the named file. * Also handle the switches were normal operation is inhibited. */ opterr = 0; for (;;) { int c = getopt_long (argc, argv, optString, longOptions, 0); if (c == -1) break; switch (c) { case 'l': { options->logFile = optarg; break; } case 'C': { options->configDir = optarg; break; } case '?': case 'h': options->runMode = runMode_usage; return EXIT_SUCCESS; case 'v': options->runMode = runMode_version; return EXIT_SUCCESS; } } optind = 1; return 0; } static int parseOptions (int argc, char *argv[], struct options_struct *options) { int optionIndex; BOOLEAN badArg = FALSE; options->addons = HMalloc (1 * sizeof (const char *)); options->addons[0] = NULL; options->numAddons = 0; if (argc == 0) { log_add (log_Fatal, "Error: Bad command line."); return EXIT_FAILURE; } while (!badArg) { int c; optionIndex = -1; c = getopt_long (argc, argv, optString, longOptions, &optionIndex); if (c == -1) break; switch (c) { case 'r': { int width, height; if (sscanf (optarg, "%dx%d", &width, &height) != 2) { log_add (log_Fatal, "Error: invalid argument specified " "as resolution."); badArg = TRUE; break; } options->width = width; options->height = height; break; } case 'f': options->gfxFlags |= TFB_GFXFLAGS_FULLSCREEN; break; case 'o': options->gfxDriver = TFB_GFXDRIVER_SDL_OPENGL; break; case 'c': // make sure whatever was set by saved config is cleared options->gfxFlags &= ~TFB_GFXFLAGS_SCALE_ANY; if (!strcmp (optarg, "bilinear")) options->gfxFlags |= TFB_GFXFLAGS_SCALE_BILINEAR; else if (!strcmp (optarg, "biadapt")) options->gfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPT; else if (!strcmp (optarg, "biadv")) options->gfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPTADV; else if (!strcmp (optarg, "triscan")) options->gfxFlags |= TFB_GFXFLAGS_SCALE_TRISCAN; else if (!strcmp (optarg, "hq")) options->gfxFlags |= TFB_GFXFLAGS_SCALE_HQXX; else if (strcmp (optarg, "none") != 0) { InvalidArgument (optarg, "--scale or -c"); badArg = TRUE; } break; case 'b': if (!strcmp (optarg, "smooth") || !strcmp (optarg, "3do")) options->meleeScale = TFB_SCALE_TRILINEAR; else if (!strcmp (optarg, "step") || !strcmp (optarg, "pc")) options->meleeScale = TFB_SCALE_STEP; else { InvalidArgument (optarg, "--meleezoom or -b"); badArg = TRUE; } break; case 's': options->gfxFlags |= TFB_GFXFLAGS_SCANLINES; break; case 'p': options->gfxFlags |= TFB_GFXFLAGS_SHOWFPS; break; case 'n': options->contentDir = optarg; break; case 'M': { int err = parseVolume (optarg, &options->musicVolumeScale, "music volume"); if (err) badArg = TRUE; break; } case 'S': { int err = parseVolume (optarg, &options->sfxVolumeScale, "sfx volume"); if (err) badArg = TRUE; break; } case 'T': { int err = parseVolume (optarg, &options->speechVolumeScale, "speech volume"); if (err) badArg = TRUE; break; } case 'q': if (!strcmp (optarg, "high")) { options->soundFlags &= ~(audio_QUALITY_MEDIUM | audio_QUALITY_LOW); options->soundFlags |= audio_QUALITY_HIGH; } else if (!strcmp (optarg, "medium")) { options->soundFlags &= ~(audio_QUALITY_MEDIUM | audio_QUALITY_LOW); options->soundFlags |= audio_QUALITY_MEDIUM; } else if (!strcmp (optarg, "low")) { options->soundFlags &= ~(audio_QUALITY_MEDIUM | audio_QUALITY_LOW); options->soundFlags |= audio_QUALITY_LOW; } else { InvalidArgument (optarg, "--audioquality or -q"); badArg = TRUE; } break; case 'u': options->subTitles = FALSE; break; case 'm': { if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO, optionIndex >= 0 ? longOptions[optionIndex].name : "m", &options->whichMusic) == -1) badArg = TRUE; break; } case 'g': { int result = parseFloatOption (optarg, &options->gamma, "gamma correction"); if (result == -1) badArg = TRUE; else options->gammaSet = TRUE; break; } case 'l': case 'C': // -l and -C are no-ops on the second pass. break; case 'i': { if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO, optionIndex >= 0 ? longOptions[optionIndex].name : "i", &options->whichIntro) == -1) badArg = TRUE; break; } case CSCAN_OPT: if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO, longOptions[optionIndex].name, &options->whichCoarseScan) == -1) badArg = TRUE; break; case MENU_OPT: if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO, longOptions[optionIndex].name, &options->whichMenu) == -1) badArg = TRUE; break; case FONT_OPT: if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO, longOptions[optionIndex].name, &options->whichFonts) == -1) badArg = TRUE; break; case SHIELD_OPT: if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO, longOptions[optionIndex].name, &options->whichShield) == -1) badArg = TRUE; break; case SCROLL_OPT: if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO, longOptions[optionIndex].name, &options->smoothScroll) == -1) badArg = TRUE; break; case SOUND_OPT: if (!strcmp (optarg, "openal")) options->soundDriver = audio_DRIVER_OPENAL; else if (!strcmp (optarg, "mixsdl")) options->soundDriver = audio_DRIVER_MIXSDL; else if (!strcmp (optarg, "none")) { options->soundDriver = audio_DRIVER_NOSOUND; options->speechVolumeScale = 0.0f; } else { log_add (log_Fatal, "Error: Invalid sound driver " "specified."); badArg = TRUE; } break; case STEREOSFX_OPT: options->stereoSFX = TRUE; break; case ADDON_OPT: options->numAddons++; options->addons = HRealloc ((void *) options->addons, (options->numAddons + 1) * sizeof (const char *)); options->addons[options->numAddons - 1] = optarg; options->addons[options->numAddons] = NULL; break; case ACCEL_OPT: force_platform = PLATFORM_NULL; if (!strcmp (optarg, "mmx")) force_platform = PLATFORM_MMX; else if (!strcmp (optarg, "sse")) force_platform = PLATFORM_SSE; else if (!strcmp (optarg, "3dnow")) force_platform = PLATFORM_3DNOW; else if (!strcmp (optarg, "none")) force_platform = PLATFORM_C; else if (strcmp (optarg, "detect") != 0) { InvalidArgument (optarg, "--accel"); badArg = TRUE; } break; #ifdef NETPLAY case NETHOST1_OPT: netplayOptions.peer[0].isServer = false; netplayOptions.peer[0].host = optarg; break; case NETPORT1_OPT: netplayOptions.peer[0].port = optarg; break; case NETHOST2_OPT: netplayOptions.peer[1].isServer = false; netplayOptions.peer[1].host = optarg; break; case NETPORT2_OPT: netplayOptions.peer[1].port = optarg; break; case NETDELAY_OPT: { if (parseIntOption (optarg, &netplayOptions.inputDelay, "network input delay") == -1) { badArg = TRUE; break; } if (netplayOptions.inputDelay > 60 * BATTLE_FRAME_RATE) { log_add (log_Fatal, "Network input delay is absurdly " "large."); badArg = TRUE; } break; } #endif default: log_add (log_Fatal, "Error: Invalid option '%s' not found.", longOptions[optionIndex].name); badArg = TRUE; break; } } if (optind != argc) { log_add (log_Fatal, "\nError: Extra arguments found on the command " "line."); badArg = TRUE; } if (badArg) { log_add (log_Fatal, "Run with -h to see the allowed arguments."); return EXIT_FAILURE; } return EXIT_SUCCESS; } static int parseVolume (const char *str, float *vol, const char *optName) { char *endPtr; int intVol; if (str[0] == '\0') { log_add (log_Error, "Error: Invalid value for '%s'.", optName); return -1; } intVol = (int) strtol (str, &endPtr, 10); if (*endPtr != '\0') { log_add (log_Error, "Error: Junk characters in volume specified " "for '%s'.", optName); return -1; } if (intVol < 0) { *vol = 0.0f; return 0; } if (intVol > 100) { *vol = 1.0f; return 0; } *vol = intVol / 100.0f; return 0; } static int parseIntOption (const char *str, int *result, const char *optName) { char *endPtr; int temp; if (str[0] == '\0') { log_add (log_Error, "Error: Invalid value for '%s'.", optName); return -1; } temp = (int) strtol (str, &endPtr, 10); if (*endPtr != '\0') { log_add (log_Error, "Error: Junk characters in argument '%s'.", optName); return -1; } *result = temp; return 0; } static int parseFloatOption (const char *str, float *f, const char *optName) { char *endPtr; float temp; if (str[0] == '\0') { log_add (log_Error, "Error: Invalid value for '%s'.", optName); return -1; } temp = (float) strtod (str, &endPtr); if (*endPtr != '\0') { log_add (log_Error, "Error: Junk characters in argument '%s'.", optName); return -1; } *f = temp; return 0; } static void usage (FILE *out, const struct options_struct *defaultOptions) { FILE *old = log_setOutput (out); log_captureLines (LOG_CAPTURE_ALL); log_add (log_User, "Options:"); log_add (log_User, " -r, --res=WIDTHxHEIGHT (default 640x480, bigger " "works only with --opengl)"); log_add (log_User, " -f, --fullscreen (default off)"); log_add (log_User, " -o, --opengl (default off)"); log_add (log_User, " -c, --scale=MODE (bilinear, biadapt, biadv, triscan, " "hq or none (default) )"); log_add (log_User, " -b, --meleezoom=MODE (step, aka pc, or smooth, aka 3do; " "default is 3do)"); log_add (log_User, " -s, --scanlines (default off)"); log_add (log_User, " -p, --fps (default off)"); log_add (log_User, " -g, --gamma=CORRECTIONVALUE (default 1.0, which " "causes no change)"); log_add (log_User, " -C, --configdir=CONFIGDIR"); log_add (log_User, " -n, --contentdir=CONTENTDIR"); log_add (log_User, " -M, --musicvol=VOLUME (0-100, default 100)"); log_add (log_User, " -S, --sfxvol=VOLUME (0-100, default 100)"); log_add (log_User, " -T, --speechvol=VOLUME (0-100, default 100)"); log_add (log_User, " -q, --audioquality=QUALITY (high, medium or low, " "default medium)"); log_add (log_User, " -u, --nosubtitles"); log_add (log_User, " -l, --logfile=FILE (sends console output to logfile " "FILE)"); log_add (log_User, " --addon ADDON (using a specific addon; " "may be specified multiple times)"); log_add (log_User, " --sound=DRIVER (openal, mixsdl, none; default " "mixsdl)"); log_add (log_User, " --stereosfx (enables positional sound effects, " "currently only for openal)"); #ifdef NETPLAY log_add (log_User, " --nethostN=HOSTNAME (server to connect to for " "player N (1=bottom, 2=top)"); log_add (log_User, " --netportN=PORT (port to connect to/listen on for " "player N (1=bottom, 2=top)"); log_add (log_User, " --netdelay=FRAMES (number of frames to " "buffer/delay network input for"); #endif log_add (log_User, "The following options can take either '3do' or 'pc' " "as an option:"); log_add (log_User, " -m, --music : Music version (default %s)", PC_3DO_optString (defaultOptions->whichMusic)); log_add (log_User, " -i, --intro : Intro/ending version (default %s)", PC_3DO_optString (defaultOptions->whichIntro)); log_add (log_User, " --cscan : coarse-scan display, pc=text, " "3do=hieroglyphs (default %s)", PC_3DO_optString (defaultOptions->whichCoarseScan)); log_add (log_User, " --menu : menu type, pc=text, 3do=graphical " "(default %s)", PC_3DO_optString(defaultOptions->whichMenu)); log_add (log_User, " --font : font types and colors (default %s)", PC_3DO_optString (defaultOptions->whichFonts)); log_add (log_User, " --shield : slave shield type; pc=static, " "3do=throbbing (default %s)", PC_3DO_optString (defaultOptions->whichShield)); log_add (log_User, " --scroll : ff/frev during comm. pc=per-page, " "3do=smooth (default %s)", PC_3DO_optString (defaultOptions->smoothScroll)); log_setOutput (old); } static int InvalidArgument (const char *supplied, const char *opt_name) { log_add (log_Fatal, "Invalid argument '%s' to option %s.", supplied, opt_name); return EXIT_FAILURE; } static int Check_PC_3DO_opt (const char *value, DWORD mask, const char *optName, int *result) { if (value == NULL) { log_add (log_Error, "Error: option '%s' requires a value.", optName); return -1; } if ((mask & OPT_3DO) && strcmp (value, "3do") == 0) { *result = OPT_3DO; return 0; } if ((mask & OPT_PC) && strcmp (value, "pc") == 0) { *result = OPT_PC; return 0; } log_add (log_Error, "Error: Invalid option '%s %s' found.", optName, value); return -1; } static const char * PC_3DO_optString (DWORD optMask) { if (optMask & OPT_3DO) { if (optMask & OPT_PC) return "both"; return "3do"; } else { if (optMask & OPT_PC) return "pc"; return "none"; } } uqm-0.6.2/sc2/src/abxadec/0000755000175000017500000000000010552600273013664 5ustar joeyjoeyuqm-0.6.2/sc2/src/abxadec/abxaud.def0000600000175000017500000000061310543202105015570 0ustar joeyjoey;//////////////////////////////////////////////////////////////////// ;// abxaud.def ;// ;// MODULE : abxadec.dll ;// PURPOSE : Declaration of DLL exports ;// ;// This file is a part of Abx Decoder sample CDP module ;// It is only necessary if you do not name your ;// (only) exported symbol "cdpmodinfo" ;// GPL applies. ;// LIBRARY "abxadec.dll" EXPORTS cdpmodinfo = abxa_mod_info @1 DATA uqm-0.6.2/sc2/src/abxadec/abxaud.h0000600000175000017500000000200710543202105015260 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* CDP module sample * .abx speech track decoder */ #ifndef _ABXAUD_H #define _ABXAUD_H typedef enum { // positive values are the same as in errno abxa_ErrNone = 0, abxa_ErrUnknown = -1, abxa_ErrBadFile = -2, abxa_ErrBadArg = -3, abxa_ErrOther = -1000, } abxa_Error; #endif // _ABXAUD_H uqm-0.6.2/sc2/src/abxadec/Makefile0000600000175000017500000000034610543202105015307 0ustar joeyjoeyuqm_CFLAGS=-W -Wall -g -O0 -fPIC uqm_INCLUDE=-I .. -I ../sc2code -I ../sc2code/libs uqm_LDFLAGS=-shared abxadec.so: abxaud.c abxaud.h gcc $(uqm_CFLAGS) $(uqm_INCLUDE) $(uqm_LDFLAGS) abxaud.c -o abxadec.so clean: rm abxadec.so uqm-0.6.2/sc2/src/abxadec/abxaud.c0000600000175000017500000003767210543202105015273 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* CDP module sample * .abx speech track decoder */ /* * Derived from decoder by Serge van den Boom (svdb@stack.nl), * The actual conversion code (somewhat moded) is from Toys for Bob. * So far, it ignores sample rates, so it will work ok as long as all * the frames have the same frequency. This is probably * enough for our purposes. */ #include #include #include //#include "libs/misc.h" //#include "port.h" #include "types.h" #include "port.h" #include "libs/cdp/cdp_imem.h" #include "libs/cdp/cdp_iio.h" #include "libs/cdp/cdp_isnd.h" #include "libs/cdp/cdpmod.h" #include "abxaud.h" #include "endian_uqm.h" #define DATA_BUF_SIZE 0x8000 #define DUCK_GENERAL_FPS 14.622f #define THIS_PTR TFB_SoundDecoder* This static const char* abxa_GetName (void); static bool abxa_InitModule (int flags, const TFB_DecoderFormats*); static void abxa_TermModule (); static uint32 abxa_GetStructSize (void); static int abxa_GetError (THIS_PTR); static bool abxa_Init (THIS_PTR); static void abxa_Term (THIS_PTR); static bool abxa_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); static void abxa_Close (THIS_PTR); static int abxa_Decode (THIS_PTR, void* buf, sint32 bufsize); static uint32 abxa_Seek (THIS_PTR, uint32 pcm_pos); static uint32 abxa_GetFrame (THIS_PTR); static TFB_SoundDecoderFuncs abxa_DecoderVtbl = { abxa_GetName, abxa_InitModule, abxa_TermModule, abxa_GetStructSize, abxa_GetError, abxa_Init, abxa_Term, abxa_Open, abxa_Close, abxa_Decode, abxa_Seek, abxa_GetFrame, }; static bool abxa_module_init (cdp_Module* module, cdp_Itf_Host* hostitf); static void abxa_module_term (); // The one and only "cdpmodinfo" symbol // on win32, it does not have to be named like so // the exported name can be overridden with .def file cdp_ModuleInfo CDPEXPORT CDP_INFO_SYM = { sizeof (cdp_ModuleInfo), // size of struct for version control CDPAPI_VERSION, // API version we are using 1, 0, 2, // our module version 0, 3, 0, // host version required, purely informational CDP_MODINFO_RESERVED1, // reserved "UQM", // CDP context name (we can use UQM) "Abx Decoder", // CDP mod name "1.0", // CDP mod version "Alex Volkov", // CDP mod author "http://sc2.sf.net", // CDP mod URL (do not have any yet) "Sample CDP-based decoder", // CDP mod comment CDP_MODINFO_RESERVED2, // reserved abxa_module_init, // init entrypoint abxa_module_term, // term entrypoint }; typedef struct { uint16 num_frames; // total number of frame uint32 tot_size; // total size of decoded stream uint16 frame_samps; // samples per frame uint16 freq; // general sampling frequency } abxa_Header; typedef struct { uint32 ofs; // file offset of frame uint16 fsize; // compressed file size uint16 usize; // uncompressed file size } abxa_FrameInfo; #define SQLCH 0x40 // Squelch byte flag #define RESYNC 0x80 // Resync byte flag. #define DELTAMOD 0x30 // Delta modulation bits. #define ONEBIT 0x10 // One bit delta modulate #define TWOBIT 0x20 // Two bit delta modulate #define FOURBIT 0x30 // four bit delta modulate #define MULTIPLIER 0x0F // Bottom nibble contains multiplier value. #define SQUELCHCNT 0x3F // Bits for squelching. typedef struct { uint16 usize; uint16 freq; uint8 frame_size; uint8 sqelch; uint16 max_error; } abxa_FrameHeader; typedef struct { // always the first member TFB_SoundDecoder decoder; // public read-only uint32 iframe; // current frame index uint32 cframes; // total count of frames uint32 channels; // number of channels uint32 pcm_frame; // samples per frame // private sint32 last_error; uio_Stream* abx; abxa_FrameInfo* frames; // buffer void* data; uint32 maxdata; uint32 cbdata; uint32 dataofs; } abxa_SoundDecoder; // interfaces our decoder needs cdp_ItfDef game_itfs[] = { {CDPITF_KIND_MEMORY}, {CDPITF_KIND_IO}, {CDPITF_KIND_SOUND}, {CDPITF_KIND_INVALID} // term }; static cdp_Module* abxa_mod = NULL; // our module handle static cdp_Itf_Host* abxa_ihost = NULL; // HOST interface ptr static cdp_Itf_Memory* abxa_imem = NULL; // MEMORY interface ptr static cdp_Itf_Io* abxa_iio = NULL; // IO interface ptr static cdp_Itf_Sound* abxa_isnd = NULL; // SOUND interface ptr static const TFB_DecoderFormats* abxa_formats = NULL; static TFB_RegSoundDecoder* abxa_regdec = NULL; // registered decoder static bool abxa_module_init (cdp_Module* module, cdp_Itf_Host* hostitf) { abxa_mod = module; abxa_ihost = hostitf; if (!hostitf->GetItfs (game_itfs)) return false; abxa_imem = game_itfs[0].itf; abxa_iio = game_itfs[1].itf; abxa_isnd = game_itfs[2].itf; abxa_regdec = abxa_isnd->RegisterDecoder ("abx", &abxa_DecoderVtbl); if (!abxa_regdec) { fprintf (stderr, "abxa_module_init(): " "Could not register audio decoder\n"); return false; } return true; } static void abxa_module_term () { if (abxa_regdec) abxa_isnd->UnregisterDecoder (abxa_regdec); // do nothing loop for 1 trillion iterations } static sint32 abxa_readHeader (abxa_SoundDecoder* abxa, abxa_Header* hdr) { if (1 != abxa_iio->fread (&hdr->num_frames, sizeof (hdr->num_frames), 1, abxa->abx) || 1 != abxa_iio->fread (&hdr->tot_size, sizeof (hdr->tot_size), 1, abxa->abx) || 1 != abxa_iio->fread (&hdr->frame_samps, sizeof (hdr->frame_samps), 1, abxa->abx) || 1 != abxa_iio->fread (&hdr->freq, sizeof (hdr->freq), 1, abxa->abx)) { abxa->last_error = errno; return abxa_ErrBadFile; } // byte swap when necessary hdr->num_frames = UQM_SwapLE16 (hdr->num_frames); hdr->tot_size = UQM_SwapLE32 (hdr->tot_size); hdr->frame_samps = UQM_SwapLE16 (hdr->frame_samps); hdr->freq = UQM_SwapLE16 (hdr->freq); return 0; } static signed char abxa_trans[16 * 16] = { -8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8, // Multiplier of 1 -16,-14,-12,-10,-8,-6,-4,-2,2,4,6,8,10,12,14,16, // Multiplier of 2 -24,-21,-18,-15,-12,-9,-6,-3,3,6,9,12,15,18,21,24, // Multiplier of 3 -32,-28,-24,-20,-16,-12,-8,-4,4,8,12,16,20,24,28,32, // Multiplier of 4 -40,-35,-30,-25,-20,-15,-10,-5,5,10,15,20,25,30,35,40, // Multiplier of 5 -48,-42,-36,-30,-24,-18,-12,-6,6,12,18,24,30,36,42,48, // Multiplier of 6 -56,-49,-42,-35,-28,-21,-14,-7,7,14,21,28,35,42,49,56, // Multiplier of 7 -64,-56,-48,-40,-32,-24,-16,-8,8,16,24,32,40,48,56,64, // Multiplier of 8 -72,-63,-54,-45,-36,-27,-18,-9,9,18,27,36,45,54,63,72, // Multiplier of 9 -80,-70,-60,-50,-40,-30,-20,-10,10,20,30,40,50,60,70,80, // Multiplier of 10 -88,-77,-66,-55,-44,-33,-22,-11,11,22,33,44,55,66,77,88, // Multiplier of 11 -96,-84,-72,-60,-48,-36,-24,-12,12,24,36,48,60,72,84,96, // Multiplier of 12 -104,-91,-78,-65,-52,-39,-26,-13,13,26,39,52,65,78,91,104, // Multiplier of 13 -112,-98,-84,-70,-56,-42,-28,-14,14,28,42,56,70,84,98,112, // Multiplier of 14 -120,-105,-90,-75,-60,-45,-30,-15,15,30,45,60,75,90,105,120,// Multiplier of 15 -128,-112,-96,-80,-64,-48,-32,-16,16,32,48,64,80,96,112,127,// Multiplier of 16 }; static sint32 abxa_decodeFrame (abxa_SoundDecoder* abxa, abxa_FrameHeader* hdr, uint8* input, uint32 inputsize) { uint8* inend; uint8* output; uint8* outptr; sint16 prev; sint32 outputsize; output = outptr = abxa->data; inend = input + inputsize; prev = *input++; // Get initial previous data point. *output++ = prev; while (input < inend) { uint16 bytes; uint8 sample; sample = *input++; // Get sample. if (sample & RESYNC) // Is it a resync byte? { //--slen; // Decrement output sample length. prev = (sample & 0x7F) << 1; // Store resync byte. *output++ = prev; } else if (sample & SQLCH) // Is it a squelch byte? { bytes = sample & SQUELCHCNT; // And off the number of squelch bytes // ?? the following makes no sense, should be --slen; //slen -= bytes; // Decrement total samples remaining count. memset (output, prev, bytes); output += bytes; } else // Must be a delta modulate byte!! { sint8 *base; //slen -= hdr->frame_size; // Pulling one frame out. // Compute base address to multiplier table. base = abxa_trans + (sample & MULTIPLIER) * 16; switch (sample & DELTAMOD) // Delta mod resolution. { case ONEBIT: { sint16 up; up = base[8]; // Go up 1 bit. for (bytes = hdr->frame_size / 8; bytes; bytes--) { uint8 mask; sample = *input++; for (mask = 0x80; mask; mask >>= 1) { if ( sample & mask ) prev += up; else prev -= up; if ( prev < 0 ) prev = 0; else if ( prev > 255 ) prev = 255; *output++ = prev; } } break; } case TWOBIT: base += 6; // Base address of two bit delta's. for (bytes = hdr->frame_size / 4; bytes; bytes--) { sample = *input++; prev += base[sample>>6]; if ( prev < 0 ) prev = 0; else if ( prev > 255 ) prev = 255; *output++ = prev; prev += base[(sample>>4)&0x3]; if ( prev < 0 ) prev = 0; else if ( prev > 255 ) prev = 255; *output++ = prev; prev += base[(sample>>2)&0x3]; if ( prev < 0 ) prev = 0; else if ( prev > 255 ) prev = 255; *output++ = prev; prev += base[sample&0x3]; if ( prev < 0 ) prev = 0; else if ( prev > 255 ) prev = 255; *output++ = prev; } break; case FOURBIT: for (bytes = hdr->frame_size / 2; bytes; bytes--) { sample = *input++; prev += base[sample>>4]; if ( prev < 0 ) prev = 0; else if ( prev > 255 ) prev = 255; *output++ = prev; prev += base[sample&0x0F]; if ( prev < 0 ) prev = 0; else if ( prev > 255 ) prev = 255; *output++ = prev; } break; } } // While still audio data to decompress.... } outputsize = output - outptr; abxa->cbdata += outputsize; return outputsize; } static sint32 abxa_readNextFrame (abxa_SoundDecoder* abxa) { abxa_FrameHeader* hdr; uint8* p; uint32 fsize; sint32 ret; fsize = abxa->frames[abxa->iframe].fsize; abxa_iio->fseek (abxa->abx, abxa->frames[abxa->iframe].ofs, SEEK_SET); // dump encoded data at the end of the buffer aligned on 8-byte p = ((uint8*)abxa->data + abxa->maxdata - ((fsize + 7) & (-8))); if (abxa_iio->fread (p, 1, fsize, abxa->abx) != fsize) { abxa->last_error = errno; return abxa_ErrBadFile; } hdr = (abxa_FrameHeader*) p; p += sizeof (abxa_FrameHeader); fsize -= sizeof (abxa_FrameHeader); hdr->usize = UQM_SwapLE16 (hdr->usize); hdr->freq = UQM_SwapLE16 (hdr->freq); hdr->max_error = UQM_SwapLE16 (hdr->max_error); if (hdr->freq == 0) { hdr->freq = abxa->decoder.frequency; } else if (hdr->freq != abxa->decoder.frequency) { fprintf (stderr, "abxa_readNextFrame(): " "WARNING: Frame frequency (%u) != global frequency (%u) " "for frame %u\n", hdr->freq, abxa->decoder.frequency, abxa->iframe); //abxa->decoder.frequency = hdr->freq; } abxa->iframe++; ret = abxa_decodeFrame (abxa, hdr, p, fsize); if (ret > 0 && ret != hdr->usize) { fprintf (stderr, "abxa_readNextFrame(): " "WARNING: decompressed frame size (%d) != specified size (%u) " "for frame %u\n", ret, hdr->usize, abxa->iframe); } return ret; } static sint32 abxa_stuffBuffer (abxa_SoundDecoder* abxa, void* buf, sint32 bufsize) { sint32 dataleft; dataleft = abxa->cbdata - abxa->dataofs; if (dataleft > 0) { if (dataleft > bufsize) dataleft = bufsize & (-4); memcpy (buf, (uint8*)abxa->data + abxa->dataofs, dataleft); abxa->dataofs += dataleft; } if (abxa->cbdata > 0 && abxa->dataofs >= abxa->cbdata) abxa->cbdata = abxa->dataofs = 0; // reset for new data return dataleft; } static const char* abxa_GetName (void) { return "Abx"; } static bool abxa_InitModule (int flags, const TFB_DecoderFormats* fmts) { abxa_formats = fmts; return true; (void)flags; // laugh at compiler warning } static void abxa_TermModule () { // no specific module term } static uint32 abxa_GetStructSize (void) { return sizeof (abxa_SoundDecoder); } static int abxa_GetError (THIS_PTR) { abxa_SoundDecoder* abxa = (abxa_SoundDecoder*) This; int ret = abxa->last_error; abxa->last_error = abxa_ErrNone; return ret; } static bool abxa_Init (THIS_PTR) { //abxa_SoundDecoder* abxa = (abxa_SoundDecoder*) This; /* enable if 16bit PCM abx exist This->need_swap = abxa_formats->big_endian != abxa_formats->want_big_endian; */ This->need_swap = false; return true; } static void abxa_Term (THIS_PTR) { //abxa_SoundDecoder* abxa = (abxa_SoundDecoder*) This; abxa_Close (This); // ensure cleanup } static bool abxa_Open (THIS_PTR, uio_DirHandle *dir, const char *file) { abxa_SoundDecoder* abxa = (abxa_SoundDecoder*) This; abxa_Header hdr; abxa_FrameInfo* info; size_t cread; uint32 i; abxa->abx = abxa_iio->fopen (dir, file, "rb"); if (!abxa->abx) { abxa->last_error = errno; return false; } if (abxa_readHeader (abxa, &hdr)) { abxa_Close (This); return false; } abxa->cframes = hdr.num_frames; abxa->frames = abxa_imem->malloc (abxa->cframes * sizeof (abxa_FrameInfo)); cread = abxa_iio->fread (abxa->frames, sizeof (abxa_FrameInfo), abxa->cframes, abxa->abx); if (cread != abxa->cframes) { abxa->last_error = abxa_ErrBadFile; abxa_Close (This); return false; } // byte swap when necessary for (i = 0, info = abxa->frames; i < abxa->cframes; ++i, ++info) { info->ofs = UQM_SwapLE32 (info->ofs); info->fsize = UQM_SwapLE16 (info->fsize); info->usize = UQM_SwapLE16 (info->usize); } This->frequency = hdr.freq; This->format = abxa_formats->mono8; abxa->channels = 1; abxa->pcm_frame = hdr.frame_samps; abxa->data = abxa_imem->malloc (hdr.frame_samps * 2); abxa->maxdata = hdr.frame_samps * 2; // estimate This->length = (float) hdr.tot_size / hdr.freq; abxa->last_error = 0; return true; } static void abxa_Close (THIS_PTR) { abxa_SoundDecoder* abxa = (abxa_SoundDecoder*) This; if (abxa->data) { abxa_imem->free (abxa->data); abxa->data = NULL; } if (abxa->frames) { abxa_imem->free (abxa->frames); abxa->frames = NULL; } if (abxa->abx) { abxa_iio->fclose (abxa->abx); abxa->abx = NULL; } abxa->last_error = 0; } static int abxa_Decode (THIS_PTR, void* buf, sint32 bufsize) { abxa_SoundDecoder* abxa = (abxa_SoundDecoder*) This; sint32 stuffed; sint32 total = 0; if (bufsize <= 0) return abxa->last_error = abxa_ErrBadArg; do { stuffed = abxa_stuffBuffer (abxa, buf, bufsize); ((uint8*)buf) += stuffed; bufsize -= stuffed; total += stuffed; if (bufsize > 0 && abxa->iframe < abxa->cframes) { stuffed = abxa_readNextFrame (abxa); if (stuffed <= 0) return stuffed; } } while (bufsize > 0 && abxa->iframe < abxa->cframes); return total; } static uint32 abxa_Seek (THIS_PTR, uint32 pcm_pos) { abxa_SoundDecoder* abxa = (abxa_SoundDecoder*) This; uint32 iframe; iframe = pcm_pos / abxa->pcm_frame; if (iframe < abxa->cframes) { abxa->iframe = iframe; abxa->cbdata = 0; abxa->dataofs = 0; } return abxa->iframe * abxa->pcm_frame; } static uint32 abxa_GetFrame (THIS_PTR) { abxa_SoundDecoder* abxa = (abxa_SoundDecoder*) This; // if there is nothing buffered return the actual current frame // otherwise return previous return abxa->dataofs == abxa->cbdata ? abxa->iframe : abxa->iframe - 1; } uqm-0.6.2/sc2/src/uqmversion.h0000644000175000017500000000252210552567102014662 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef UQMVERSION_H #define UQMVERSION_H #define UQM_MAJOR_VERSION 0 #define UQM_MAJOR_VERSION_S "0" #define UQM_MINOR_VERSION 6 #define UQM_MINOR_VERSION_S "6" #define UQM_PATCH_VERSION 2 #define UQM_PATCH_VERSION_S "2" #define UQM_EXTRA_VERSION "" /* The final version is interpreted as: * printf ("%d.%d.%d%s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, * UQM_PATCH_VERSION, UQM_EXTRA_VERSION); */ #define UQM_STRING_VERSION \ UQM_MAJOR_VERSION_S "." UQM_MINOR_VERSION_S "." UQM_PATCH_VERSION_S \ UQM_EXTRA_VERSION #define UQM_CVS_DATE "$Date: 2007-01-15 00:04:49 +0100 (Mon, 15 Jan 2007) $" #endif uqm-0.6.2/sc2/src/darwin/0000755000175000017500000000000010552600273013561 5ustar joeyjoeyuqm-0.6.2/sc2/src/darwin/SDLMain.m0000600000175000017500000001560510543202105015155 0ustar joeyjoey/* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs Modified for use with The Ur-Quan Masters by Nicolas Simonds */ #import "port.h" #import SDL_INCLUDE(SDL.h) #import "SDLMain.h" #import /* for PATH_MAX */ #import /* for strrchr() */ #import static int gArgc; static char **gArgv; static BOOL gFinderLaunch; @implementation SDLApplication /* Invoked from the Quit menu item */ - (void)terminate:(id)sender { /* Post a SDL_QUIT event */ SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent (&event); (void) sender; /* Get rid of unused variable warning */ } /* override NSApplication:sendEvent, to keep Cocoa from beeping on non-command keystrokes */ - (void)sendEvent:(NSEvent *)anEvent { if (NSKeyDown == [anEvent type] || NSKeyUp == [anEvent type]) { if ([anEvent modifierFlags] & NSCommandKeyMask) [super sendEvent: anEvent]; } else [super sendEvent: anEvent]; } @end /* The main class of the application, the application's delegate */ @implementation SDLMain static char * basename (char *path) { char *base; base = strrchr (path, '/'); if (base == NULL) return path; return (base + 1); } /* Set the working directory to the .app's parent directory */ - (void) setupWorkingDirectory:(BOOL)shouldChdir { char origindir[PATH_MAX]; char *c; if (!shouldChdir) return; strncpy (origindir, gArgv[0], sizeof origindir); origindir[sizeof origindir - 1] = '\0'; c = basename (origindir); if (c == origindir) strcpy (origindir, "."); else *c = '\0'; /* chdir to the binary app's point of origin */ if (chdir (origindir) != 0) abort (); /* then chdir to the .app's parent */ if ( chdir ("../Resources/") != 0 ) abort(); } void setupAppleMenu (void) { NSMenu *appleMenu; NSMenuItem *menuItem; NSString *title; NSString *appName; appName = [NSString stringWithUTF8String:basename (gArgv[0])]; appleMenu = [[NSMenu alloc] initWithTitle:appName]; /* Add menu items */ title = [@"Hide " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Quit " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; /* Put menu into the menubar */ menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; [menuItem setSubmenu:appleMenu]; [[NSApp mainMenu] addItem:menuItem]; /* Tell the application object that this is now the application menu */ [NSApp setAppleMenu:appleMenu]; /* Finally give up our references to the objects */ [appleMenu release]; [menuItem release]; } /* Create a window menu */ void setupWindowMenu (void) { NSMenu *windowMenu; NSMenuItem *windowMenuItem; NSMenuItem *menuItem; windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; /* "Minimize" item */ menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [windowMenu addItem:menuItem]; [menuItem release]; /* Put menu into the menubar */ windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; [windowMenuItem setSubmenu:windowMenu]; [[NSApp mainMenu] addItem:windowMenuItem]; /* Tell the application object that this is now the window menu */ [NSApp setWindowsMenu:windowMenu]; /* Finally give up our references to the objects */ [windowMenu release]; [windowMenuItem release]; } /* Replacement for NSApplicationMain */ void CustomApplicationMain (int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; SDLMain *sdlMain; /* Ensure the application object is initialised */ [SDLApplication sharedApplication]; /* Set up the menubar */ [NSApp setMainMenu:[[NSMenu alloc] init]]; setupAppleMenu (); setupWindowMenu (); /* Create SDLMain and make it the app delegate */ sdlMain = [[SDLMain alloc] init]; [NSApp setDelegate:sdlMain]; /* Start the main event loop */ [NSApp run]; [sdlMain release]; [pool release]; (void) argc; /* Get rid of unused variable warning */ (void) argv; /* Get rid of unused variable warning */ } /* Called when the internal event loop has just started running */ - (void) applicationDidFinishLaunching: (NSNotification *) note { int status; /* Set the working directory to the .app's parent directory */ [self setupWorkingDirectory:gFinderLaunch]; /* allow Cocoa to hear keystrokes like Command-Q, etc. */ setenv ("SDL_ENABLEAPPEVENTS", "1", 1); /* Hand off to main application code */ status = SDL_main (gArgc, gArgv); /* We're done, thank you for playing */ exit (status); (void) note; /* Get rid of unused variable warning */ } @end @implementation NSString (ReplaceSubString) - (NSString *) stringByReplacingRange:(NSRange)aRange with:(NSString *)aString { unsigned int bufferSize; unsigned int selfLen = [self length]; unsigned int aStringLen = [aString length]; unichar *buffer; NSRange localRange; NSString *result; bufferSize = selfLen + aStringLen - aRange.length; buffer = NSAllocateMemoryPages (bufferSize * sizeof (unichar)); /* Get first part into buffer */ localRange.location = 0; localRange.length = aRange.location; [self getCharacters:buffer range:localRange]; /* Get middle part into buffer */ localRange.location = 0; localRange.length = aStringLen; [aString getCharacters:(buffer + aRange.location) range:localRange]; /* Get last part into buffer */ localRange.location = aRange.location + aRange.length; localRange.length = selfLen - localRange.location; [self getCharacters:(buffer + aRange.location+aStringLen) range:localRange]; /* Build output string */ result = [NSString stringWithCharacters:buffer length:bufferSize]; NSDeallocateMemoryPages (buffer, bufferSize); return result; } @end #ifdef main # undef main #endif /* Main entry point to executable - should *not* be SDL_main! */ int main (int argc, char **argv) { /* Copy the arguments into a global variable */ int i; /* If we are launched by double-clicking, argv[1] is "-psn_ */ if ( argc >= 2 && strncmp (argv[1], "-psn_", 5) == 0 ) { gArgc = 1; gFinderLaunch = YES; } else { gArgc = argc; gFinderLaunch = NO; } gArgv = (char **) malloc (sizeof *gArgv * (gArgc + 1)); if (gArgv == NULL) abort (); for (i = 0; i < gArgc; i++) gArgv[i] = argv[i]; gArgv[i] = NULL; CustomApplicationMain (argc, argv); free (gArgv); return 0; } uqm-0.6.2/sc2/src/darwin/Makeinfo0000600000175000017500000000003010543202105015206 0ustar joeyjoeyuqm_MFILES="SDLMain.m" uqm-0.6.2/sc2/src/darwin/SDLMain.h0000600000175000017500000000074210543202105015144 0ustar joeyjoey/* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #import /* An internal Apple class used to setup Apple menus */ @interface NSAppleMenuController:NSObject {} - (void)controlMenu:(NSMenu *)aMenu; @end @interface SDLMain : NSObject @end @interface SDLApplication : NSApplication @end uqm-0.6.2/sc2/src/config_unix.h.in0000644000175000017500000000300010546776503015371 0ustar joeyjoey/* This file contains some compile-time configuration options for *nix * systems. * config_unix.h is generated from config_unix.h.in by build.sh * When building on MS Windows using build.sh (MinGW, Cygwin), * config_win.h is generated from src/config_win.h.in. * When using MSVC on MS Windows, you'll have to edit src/msvc++/config.h * manually if you want anything else than the defaults. */ #ifndef _CONFIG_UNIX_H #define _CONFIG_UNIX_H /* Directory where the UQM game data is located */ #define CONTENTDIR "@CONTENTDIR@" /* Directory where game data will be stored */ #define USERDIR "~/.uqm/" /* Directory where config files will be stored */ #define CONFIGDIR USERDIR /* Directory where supermelee teams will be stored */ #define MELEEDIR "${UQM_CONFIG_DIR}/teams/" /* Directory where save games will be stored */ #define SAVEDIR "${UQM_CONFIG_DIR}/save/" /* Defined if words are stored with the most significant byte first */ @WORDS_BIGENDIAN@ /* Defined if your system has readdir_r of its own */ @HAVE_READDIR_R@ /* Defined if your system has setenv of its own */ @HAVE_SETENV@ /* Defined if your system has strupr of its own */ @HAVE_STRUPR@ /* Defined if your system has stricmp of its own */ @HAVE_STRICMP@ /* Defined if your system has getopt_long */ @HAVE_GETOPT_LONG@ /* Defined if your system has iswgraph of its own*/ @HAVE_ISWGRAPH@ /* Defined if your system has wchar_t of its own */ @HAVE_WCHAR_T@ /* Defined if your system has wint_t of its own */ @HAVE_WINT_T@ #endif /* _CONFIG_UNIX_H */ uqm-0.6.2/sc2/src/getopt/0000755000175000017500000000000010552600273013577 5ustar joeyjoeyuqm-0.6.2/sc2/src/getopt/getopt.h0000600000175000017500000001445710543202106015246 0ustar joeyjoey/* Declarations for getopt. Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _GETOPT_H #ifndef __need_getopt # define _GETOPT_H 1 #endif /* If __GNU_LIBRARY__ is not already defined, either we are being used standalone, or this is the first header included in the source file. If we are being used with glibc, we need to include , but that does not exist if we are standalone. So: if __GNU_LIBRARY__ is not defined, include , which will pull in for us if it's from glibc. (Why ctype.h? It's guaranteed to exist and it doesn't flood the namespace with stuff the way some other headers do.) */ #if !defined __GNU_LIBRARY__ # include #endif #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; #ifndef __need_getopt /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { # if (defined __STDC__ && __STDC__) || defined __cplusplus const char *name; # else char *name; # endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ # define no_argument 0 # define required_argument 1 # define optional_argument 2 #endif /* need getopt */ /* Get definitions and prototypes for functions to process the arguments in ARGV (ARGC of them, minus the program name) for options given in OPTS. Return the option character from OPTS just read. Return -1 when there are no more options. For unrecognized options, or options missing arguments, `optopt' is set to the option letter, and '?' is returned. The OPTS string is a list of characters which are recognized option letters, optionally followed by colons, specifying that that letter takes an argument, to be placed in `optarg'. If a letter in OPTS is followed by two colons, its argument is optional. This behavior is specific to the GNU `getopt'. The argument `--' causes premature termination of argument scanning, explicitly telling `getopt' that there are no more options. If OPTS begins with `--', then non-option arguments are treated as arguments to the option '\0'. This behavior is specific to the GNU `getopt'. */ #if (defined __STDC__ && __STDC__) || defined __cplusplus # ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int __argc, char *const *__argv, const char *__shortopts); # else /* not __GNU_LIBRARY__ */ extern int getopt (); # endif /* __GNU_LIBRARY__ */ # ifndef __need_getopt extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts, const struct option *__longopts, int *__longind); extern int getopt_long_only (int __argc, char *const *__argv, const char *__shortopts, const struct option *__longopts, int *__longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int __argc, char *const *__argv, const char *__shortopts, const struct option *__longopts, int *__longind, int __long_only); # endif #else /* not __STDC__ */ extern int getopt (); # ifndef __need_getopt extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); # endif #endif /* __STDC__ */ #ifdef __cplusplus } #endif /* Make sure we later can get all the definitions and declarations. */ #undef __need_getopt #endif /* getopt.h */ uqm-0.6.2/sc2/src/getopt/getopt.c0000600000175000017500000007277610543202106015251 0ustar joeyjoey/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #include #ifndef HAVE_GETOPT_LONG #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #ifdef VMS # include # if HAVE_STRING_H - 0 # include # endif #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. */ # if defined HAVE_LIBINTL_H || defined _LIBC # include # ifndef _ # define _(msgid) gettext (msgid) # endif # else # define _(msgid) (msgid) # endif #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ # include # define my_index strchr #else #ifndef WIN32 # if HAVE_STRING_H # include # else # include # endif #else # include #endif /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif static char * my_index (str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ # if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); # endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Stored original parameters. XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ extern int __libc_argc; extern char **__libc_argv; /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ # ifdef USE_NONOPTION_FLAGS /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; # endif # ifdef USE_NONOPTION_FLAGS # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } # else # define SWAP_FLAGS(ch1, ch2) # endif #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ static void exchange (char **); #endif static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = HMalloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #if defined _LIBC && defined USE_NONOPTION_FLAGS if (posixly_correct == NULL && argc == __libc_argc && argv == __libc_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) HMalloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', nonoption_flags_max_len - len); } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { int print_errors = opterr; if (optstring[0] == ':') print_errors = 0; if (argc < 1) return -1; optarg = NULL; if (optind == 0 || !__getopt_initialized) { if (optind == 0) optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (print_errors) fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (print_errors) { if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, _("%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, _("%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (print_errors) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (print_errors) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); else /* +option or -option */ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (print_errors) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (print_errors) fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (print_errors) fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (print_errors) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ #endif /* HAVE_GETOPT_LONG */ uqm-0.6.2/sc2/src/getopt/Makeinfo0000600000175000017500000000004010543202106015226 0ustar joeyjoeyuqm_CFILES="getopt.c getopt1.c" uqm-0.6.2/sc2/src/getopt/getopt1.c0000600000175000017500000001070410543202106015311 0ustar joeyjoey/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #ifndef HAVE_GETOPT_LONG #include "getopt.h" #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } #endif /* Not ELIDE_CODE. */ #ifdef TEST #include int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ #endif /* HAVE_GETOPT_LONG */ uqm-0.6.2/sc2/src/res/0000755000175000017500000000000010552600273013066 5ustar joeyjoeyuqm-0.6.2/sc2/src/res/ur-quan-icon-alpha.ico0000600000175000017500000006117610543202106017157 0ustar joeyjoey 00h– èþ(æ 00¨ ¨¶h^"00 ¨%Æ'  ¨nM h^(0`€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@„DDDDDDDDDDDDDDDDDDD" DDDDDDDDDDDDDDD@@""¢"DDDDDDDDDDDDD D"*ª" DDDDDDDDDDDD@™8 D@""*ª"DDDDDDDDDDD3ª DD""ª¢ DDDDDDDDDD@;:¨ DD@""*ª"DDDDDDDDD›³ªª DD‚"ª¢ DDDDDDDD@»:ªª  D@ˆ"*ª"DDDDDDD›³ªª¢(¢ˆˆ‚"*¢ DDDDDD@;:ª¢"ªª ˆ‚"*ª DDDDD³ªª"*ªª¢ˆˆ€""*‡€„DDDD›2ª¢"ªªªª¨ˆ@"*wxDDDD“"*"*ªªªªª€D@"(‡yDDDD2"""ªƒªª¨Š DDDˆƒ¹DDDD"""*ª822ˆªªDD@ˆ;9DDDD""""ª¢3“:ªª DDD™‘DDDD""*¢;³:ªªªDDADDDDDDD@"""¢›³2ªªª¢DDDDDDDDD"""3“:ªªªª DDDD DD@""(228ªªªª¢""" DDDD"DD"ˆ"ª(Šªªªª¢ªª"DDD¢ „D""ªª:ªªªªªªª¢DDDª" ˆ€"""ªª¢*ªªªª£:DDD*¢ ˆˆ"""*ª¢"ªªªª;²DDD@*ª"ˆˆ€"""ªª¢*ª*ª;:DDD@"*£ˆˆD""*ªª"**ª;2 DDD@""ªˆ€D@"""ªªªª*ª;2 DDDD"*¢ DD""*ªªª*ª;2 DDDD""ª"DD@"""ªªªª£»² DDDD@""*ª DDD""ªªªª;»2 DDDDD""ª¢$DD""ªªª£»³¢ DDDDD@""*ª"DD""ªªª;»:¢ DDDDDD""ª§D""ªª#»³ª! DDDDDD@""*wx"""";»:¢‘DDDDDDD"(‡y"""#»³"#DDDDDDDD@"ˆˆ¹""#3;³2"3DDDDDDDDDˆ‹¹"3333")DDDDDDDDDD@9‘""""""!DDDDDDDDDDD™DDDDDDDDDDDDDD@DDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿðÿÿÿøÿÿð ?ÿÿàÿÿÀÿÿ€€ÿÿÀÿþ€ÿüÿøððð€ðÀðàðððø?ÿ€üÇÀÃà?ÁðÀpÀÀààÀààðððøøüü|þ<ÿ ÿ€ÿÀ?ÿàÿðÿÿøÿÿüÿÿþÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ( @€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ"  """ “ "ª €›* "*¢!ºª 1"ª";:ª" ˆ‚*¢! ³ª"*¢ˆ"ª¢›ª¢*ªª¨‚"‡’"¢ªªª*(ˆ2""¨2£Š ‹"""ª33ªª(™"*;³ªª¢""33ªªª "(‚£Šªª¢""(* ""ª*ªªªªª *¢(""*ª"ªªª« ª(ˆ""*ª"ªª; "*¨€""ªª¢ª; "ª€""*ªªª; "*¢"""*ªª«» "ª""*ªª»º "*¢ "*ª«»¢ "¨x""";º£ˆ‰"3;»"90ƒ¹"332)˜ """ ÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿ‚ÿÿÿü€øÀ?ø€ðàà ààüÎÇÃÀÀÀàà ðøüþÿÿƒÿçÿÿÿÿÿÿÿÿÿÿ( €€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿDDDDDDDDDDD@DDDDD ""DDDC:(‚*$DD¢¢"¢DA:"ª¢'H"*3¢ˆB‚"3ª"DB(""*ª*$B"‚"ªªª$B*(‚*ª£$D"¢‚*ª»$DB*€"#²$DD0#3#DDDA""$DDDDDDDDDÿÿ;þ?" ð‚*àÀ ³€*¢€"€€›ª€ªª€Àà’"ðªªùÿÿ(0`š/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš.þš.þš.þš.þš.þš.þš.þš.þš.þš.þš.þš.þš.þœ5ùžAñ¡Jê¢Uâ¡fΜu½—€°“‡¥‰›ˆ”ˆ„Œ~ƒw|{r|upzsoysmyrj{qf|uM€~5…‡‹ŒŽŒ ‘’–­Â Ê¦Õ¬ã¯ìªòòŒò{ïkñ^îMê@å9Ù5Ê ,·1¨!9“4C{AIkOO^RQZSQVQRRORNLOJIOHEMDBKB@J?=F=9A98<84;3.;--4-+,.&)1"CZ jt ~ v o R ? / %  ")06<CGJMT[_chosuy}€ƒ‡Š ”™›š˜—˜¡¤¤¥¨¬®°±³µµ·»½¾ÃÅÆÇÇÉÌÎÒÓÔ×ÜÞßãçëíòøúúùóíâ!Ý#"Ô("Í,Ç0Á7½;½C½L¿R¿VÆWÏZÖ]Ú]Û_)Þc7âhDälOâvcÝŠ|Ù ×±ŸÕ½¤×Ȭ×ÑŸ×Ô‹ÛÞÿÿÿléîVõ÷Rö÷Nö÷Höõ=øó7øô‘|‘Œ’|stx“”•˜›š‘“}|‰Š‡–›§¨Æ¨¨¡’–}}†„‚‚á±{›Ÿ§¯ÁÁÒ¼¯œŽ{…‚ebãí¤{šŸ¥¯¾ÄÑǶŽ}ƒga_åÙÜ®}˜Ÿ¥¯¼ÂÑɶ }€d_]èÑÛí¦}˜¥¯¼ÂÐ˼¡y€a]ÿçÐÏÐÙ®’{‘™p¤¨¼ÁÐ̼£}`]ÿèÂÇÏÔÍzàŽxŒnms¢¨¶ÁÏ̼¤|€d]ÿéÁÆÂÉÄ¥«íÜ´ŽuxNOtss£¨¶ÀÏͼ¦x…e_ÿèÁÆÄɾ£´ÚÜÖÖ¶‘ŠOJmquz£¨¶ÁÏͼz||†‚a]èÂįɼ¥±ÒÒÐÔÖÖ»OJnon}‘•¢¨µÀÐíóF}s‰„e]弯ÆÇ¾¥­ÑÌÃÌÐÔÖÖÛnnnyŠ}”¡§µÞòôòQ‡‰gaåµ²¼É¿¥­ÑÝÇÃÆÌÐÖÜÜÍo}”œ¢¥MHòød‚‡gT¶µµµµ§¯ÑÚDâÈÆÇÍÛDïÖÚ’“œnmMX]d‚‡‹Ÿ¶­­±¯¦¨ÂÊÆâIåµU¼QOÛÖÖÊ”ŽtqR]_d†•¥Ÿ¤ ¢£¯¶ÃÆÇáYYaZUÉÑÔÖÖÏ•ibde~xy“}ŽŽ‘˜¨¯²¶ÃƼ`]]_UÁËÏÓÖÖÑ—…‚‚…ux›¯­­²¶Âºa]]_WÀÄÊÏÓÖÖÓ™ˆˆ|y“Ž}Ÿ²­­²¿½X_a_UÄÆÃÊÏÓÖÖÔœŠ‘‘‘‘Ž›Ÿ}²­±¸ITáTáROÆÆÃÉÏÒÖÖÖŸ›¡¥¨¨Ž¡¼£´¬OO¸ÀÉÆ¾GKÆÆÄÉÏÒÖÖÖÁ¼ÌÓÐÔ¾¤Ž¦É¼¦‘sŠsz±v«µµÁÆÈßãÆÆÄÂÉÏÒÖÖÖÑÖÖÖÖÖ­•¥Ïϼ§‘xuŠsmozµ­®±µÀÇÆÇľ¾ÂÈÍÒÖÔÖÔÔÓêê”{Ÿ¿ÍϽ¨’ŠnMrtr­­­±µÀÇÃȾ¿¾ÃÈÍÌÍÌÍËéûþÀ—vލÁÍϽ©mImps|‘—±±­±µ¿ÇÌÏÈþ¾ÂÁÂÀÂÄÁêúëÁ•tŸ²ÀÌÑâHnony‹–­±­±µ¾ÆÌÐÈÿÀ¾Á¿ÃÆÂèúìÀ˜xx˜§²¿ÌÑrmmxŠ–­±­±´¾ÆÌÐÉÄÆÆÆ¾ÃÆÂâú켘x‹œ¨±¿ËÑvu”•¯±­±µ½ÆÌËÄÆÆÂÀÄÆÂêú켘x‘— §±¾ÊÒ¹±—“¯±®±´¼ÌÊÃÆÃÇÏÇÁëûúþµ›y“œ §­¾ÉÒÁ±—’¯±­±¾ÌÉÆÃÇÏÍÂêúúü꾘x“› ¦­¾ÇÑ´˜’›®­±¼ÌÌÍÌÏÍÂëûûú굜{’›Ÿ¦®¾ÇÑÆ´š‘š§®­¾ËÈÉÈÉÂêûúúéÁÄÀ˜x’šŸ¥¯¼ÆÑÛò}}’™¯­±¶ÂÂÂÁ¿êúúüêÁÄ« y™Ÿ¥¯¾ÃòôôkŽ‘­­­²¶µµ²êúúúëÃÁ¸egŽ˜Ÿ¥©PEôõdƒŠ•¢®­­«ª«ªãýÿýê¶¶ÀZfˆŽ˜žsMME^d‚‘˜¨­­«WYYX\[Zæ½¶ª``}Ž{npQ\^dƒŠ•±­±åVUUUUUå¼¶©efˆ}{k`ab‚|x•¢ ¨¤¨¥¥¦¢¥¡¥Ÿ‚‡|hff‚|’”“•“”””–“•“•|…†|vxÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿðÿÿÿøÿÿð ?ÿÿàÿÿÀÿÿ€€ÿÿÀÿþ€ÿüÿøððð€ðÀðàðððø?ÿ€üÇÀÃà?ÁðÀpÀÀààÀààðððøøüü|þ<ÿ ÿ€ÿÀ?ÿàÿðÿÿøÿÿüÿÿþÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ( @ ª\ ©a®Z±O±@ ·3À)ËÔ ãñôñìåáÞØÔÐÊÇÆÃ¾»·²®¨¢ž›˜‘ŠƒxmbXNJA 9 5 /'!4>=/%+$-,&0/+422779=;C>@EACHCGMHNTOU\YZ\`^ZigUwK¥„CÄŽ;ܘ2÷š/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þ›/ÿš/þš/þš/þš/þš/þš/þš/þ›/ÿš/þ›/ÿ‘6þ€BþpMýbVýTdòHrë2±¶  .= 0@&!+ 2°¶$%9 9?A>'+ 2©¶# $0?C?:/&; 0¬µ$ BB<56-&!ÈÕ:: 3­#  :5 8*&?ÊǪ2 3 #ÉÈ / 66AD²«3 -(*))$±± ,> :2ª¬5 6)"²³° +> 921 /8 6$±± *050.0 )%0 8&@AÉ !#,? '#5 7;#! #5 (&05 >& ¿!0 9,% +; <+" ¾Â¾!0 7*&"*9 /'!¿ÃÁ / /*&"<: /("¿ÃÁ#/ 6+' È×C8.' ÂÀ¯2; <.'BÊǦ1,# ±±³¹»¬ =8@¢µª4-! ­¬> :7§ª8 /*)))))*)18 24 ÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿ‚ÿÿÿü€øÀ?ø€ðàà ààüÎÇÃÀÀÀàà ðøüþÿÿƒÿçÿÿÿÿÿÿÿÿÿÿ( .b+9g;M;)G/.I3/I/3C<!<d‰3tÞ˜Y˜¼{™(Gm D ¡=Î5]_g'*)}² ¾.ä–=ò²·;D1 K ¬Æ^```.C.ˆÂ×Ò4èœ6óž f 0C0´'Ä'=Q=JJJAQA®ÐÊÁÄ.ë†e" € ¿-H-WAW&I&‹¸ÊÆÅßåùWf!y1S1"H""˜"¥,¸*&º'ËðÒ¿É$N%>C>UUU1C1‘·Ÿ´•ÏÅú½6A6--2 .ENMh{ Ã¢x§ä °HPH]]]65A RÊ(6f==Oy—̶¶Øø7Ê7;A<?>?I™‹·¬'2r6vÆÌß(¾Ê†<><ZEZ$J$«Õ.e*E~· ò&ƒcbcLMLV ³ V#&W Vs*f)?@?X¨±#J#4=4?3K3ÿÿÿš›œ’“”•–—˜™‰Š‹ŒŽA‘}~€‚ƒ„…†‡ˆopqrstuvwxyz{|abcdefghijklmnTUVWXYZ[\]^_`GH"IJKLMNOPQRS9:;<=>?@ABCDEF+,-./012345678 !"#$%&'()* ÿÿ þ?°¶ðà%9À?A€€+ € € €¶€#À $àC?ð&ù;ÿÿ (0`    %&%  75]PlI>0)!&*+&#Bè² æÑõ³„ˆLD6+   4\[q_[2— ÿ*ÿ4ÿ@ÿNÿJÿ èü¼~Q:&  <³ï Ý(ñâ0ôic ÝMÿ]ÿ…ÿ†ÿÉÿ†ÿ‹ÿnýñ5þ»a@( F½;ÿbÿ „ÿ šÿ§"ÿžÿ®F`âMÿcÿ„ÿ”ÿÁÿÃÿëÿ¶ÿÿTÿÈhB)  H¦Iÿ™ÿ@ÕÿXîÿ#µJÿGÿ:ÿzÿ¤G4c âIÿbÿ~ÿ‘ÿ¸ÿÇÿéÿÌÿ­ÿ^ÿÌjE)  @¸ tÿ¾ÿoÝÿ’ôÿ½Zÿñÿ3ñ2ÿ™ÿÁK,._ ÞEÿ`ÿ{ÿŽÿ´ÿÅÿæÿÒÿ°ÿjÿÓqG- A¹#gû(öÿ†ýÿÓûÿ×KÿéÿéÿFùFÿÿ·^:-1aáDÿ^ÿ{ÿŽÿ³ÿÄÿäÿÔÿ±ÿmÿÖpH, @¢3gúpÿÿ·ÿÿüëÿÎKÿãÿßÿãÿ÷ÿ˜ÿ ò ´_C4@éGÿPaPÿxÿŒÿ±ÿÂÿãÿ×ÿ²ÿvÿ×uI. ;¾1uÿvïÿÆÿÿþñÿØ`ÿÅÿÌÿÞÿòÿÝÿXÿ)v)ÿ6¢6ÿÃnQV’ èSJSÿdXdÿGIGÿrÿ‹ÿ°ÿÁÿàÿÙÿ³ÿyÿ ÛxJ/@³dúBöÿ¶ÿÿÿóÿÚUÿÂÿÈÿÅÿÑÿÇÿ{ÿ¦ÿ[ù[ÿ/ÿ/ÿ¥ÿ ÐŒ”÷nnnÿfefÿCECÿF@FÿE=Eÿtÿ‰ÿ­ÿ¿ÿßÿÝÿ´ÿ€ÿÞ}M1-–Hÿ Öÿ“ÿÿüóÿÙVÿÂÿÉÿÇÿÑÿ»ÿwÿ¥ÿþÿ'ü'ÿùÿÿÿ«ÿçódfdÿ{{{ÿYYYÿKKKÿA>Aÿ&8&ÿXÿuÿˆÿ¬ÿÁÿÞÿÝÿµÿ.‡.ÿ  àL-#¯@û›ÿhâÿÛôÿÓhÿÄÿÇÿÈÿÐÿ¶ÿ|ÿ¢ÿëÿìÿâÿõÿúÿÿÿ¶ÿh`hÿ}u}ÿTUTÿQQQÿWWWÿ&&&üî-ýXÿrÿ†ÿªÿ¾ÿâÿHàHÿÄÁÅÿŸšÿä„D#  =ÿqÿ=Ñÿ«ÿÿ´Yÿ±ÿÊÿÈÿÍÿºÿ}ÿœÿçÿ×ÿÆÿÙÿäÿõÿúÿÿÿâÿWZWÿVJVÿVVVÿ333ÿày¿)ÿXÿqÿ…ÿªÿ*©)ÿ¸ÁºÿëâéÿÖ;ÿQ^ºÿ+äp*  Cï$´ÿhúÿœ_ÿªÿ¤ÿ³ÿÑÿ½ÿ|ÿÿæÿ$Ó$ÿËÿÆÿÈÿØÿäÿùÿ)ò)ÿ)ð)ÿ Û ÿQ^Qÿ2&2ÿÌjBG°&ýVÿsÿ|ÿoqpÿ|†ÿɹ´ÿh²îÿ=üÿ ƒÿÏ= E)íµÿ„oÿ¬ÿ©ÿ©ÿ¨ÿªÿƒÿ—ÿçÿÕÿ®’®ÿH¥DÿÎÿÈÿÌÿÚÿÏÿ¸ ·ÿxÎxÿÿÿäÿ!ü¬`<-<œ"÷RÿTPTÿcZaÿribÿA¥¹ÿ¬ÿÿ;øÿ—ÿ íH= ád&ÿ­ÿÿœÿžÿ—ÿÿŠÿÅÿÓÿÊÿF«Dÿ}u–ÿ¤Wÿ©.ÿ˜jÿµ%ÿJ†–ÿm”fÿñÿúÿÿÿÓÿ&ó™Q7-<—õFBBÿXO@ÿ5t£ÿ³ÿÿ”ÿÿ.îÿBìq 6*ï~ÿbþxÿhÿrÿZÿwÿ—ÿ®ÿÆÿÊÿÍÿ¨8ÿ‘ÉÿËÿeÿÿšÒÿ–ÿÑÿèÿðÿúÿÿÿàÿ0ù›R9/>’ï!5ÿZÿÿBÿÿ/ßÿ&Iý“'%  ô ÂÑ Ð éAÿ‰ÿÿ¤ÿ®ÿÆÿÉÿµÿ€Ðÿ¯ÿÿÌúÿŒÿÿŠÿÁÿÕÿáÿïÿúÿÿÿèÿ8ø W?9M”Nï¢ÿ™ÿVÿŒ= %gSaQGJ’Lÿ–ÿœÿÿ£ÿ¬ÿÅÿ³ÿkîÿ¯þÿÞ÷ÿÿÿ{²ÿÀÿÇÿÓÿáÿîÿûÿÿÿîÿEü¬wp`{«ðî¬_9 ŸÿÈdH4+=¹eÿ£ÿšÿœÿ£ÿ½ÿ¹ÿš¹ÿŒýÿmÿÿóÿž„ÿÇÿÊÿÆÿÓÿáÿíÿûÿýÿóÿQùÛì Û Ûåë ïÕ~J(/ âMÿaÿ ÚuG1,N·[þ£ÿ›ÿžÿ¬ÿqƒ„ÿ”‹ÿ®;ÿƒŒÿ¶6ÿ7‡£ÿh‰fÿ É ÿÉÿÆÿÑÿàÿìÿúÿüÿùÿcÿYÿNÿ^ÿmÿ}ÿÿ‡ÿÞ: 5Ðnÿµÿuÿ á{I6;jÏ[ÿ¥ÿœÿhhiÿn}kÿ¨ ÿ¾ÿÐÿÈÿºÿ˜Œ’ÿu¨uÿÉÿÈÿÇÿÑÿàÿìÿúÿúÿúÿÁÿ´ÿØÿíÿâÿõÿºÿyÿÛS  6 ÏÿÑÿ¶ÿÿ æ‚UR~âD4Dÿ/€/ÿŸÿ=~=ÿ — ÿ§ÿ©ÿÂÿÊÿÎÿÂÿI³IÿÉÿÊÿÇÿÅÿÐÿßÿëÿúÿûÿþÿéÿÿÿüÿþÿýÿùÿÿ1ÿ$1Ö{ÿÞÿßÿµÿƒÿë—‹âGFGÿ`_`ÿPBPÿ%k%ÿ©ÿÿ™ÿ¢ÿ¨ÿ¿ÿËÿÊÿÌÿÇÿÄÿ¹ÿ»ÿÅÿÎÿÝÿêÿúÿòÿúÿñÿõÿíÿ÷ZÿÿaÿÄÿ'ÿ|, "­aÿ¼ÿÜÿáÿ·ÿ‹ÿò  íXXXÿrrrÿIJIÿCCCÿH9HÿYÿ›ÿÿšÿ¢ÿ§ÿ¾ÿÌÿÆÿÎÿÅÿ¹ÿ¼ÿ»ÿÆÿÎÿÝÿØÿÛÿÖÿÚÿÔÿæAÿQúìÿ:ý¬ÿ¾ÿ=ÿ‘- LÔ‹ÿÂÿÚÿáÿ·ÿ Œ ÿZPZÿ€€€ÿ^^^ÿNNNÿDDDÿ*)*ÿî<øŸÿžÿšÿ¡ÿ§ÿ¼ÿËÿØÿáÿÎÿÆÿºÿ»ÿÅÿÂÿÅÿÀÿÅÿÇÿÂÿØ]ÿZøÿÿ+ÿ‡ÿÂÿ3ÿˆ.  -Òaÿ¤ÿ¾ÿ×ÿæÿGŸGÿŠnŠÿWZWÿPPPÿXXXÿ676ÿß|Ÿ4ùÿžÿšÿ¡ÿ§ÿºÿÊÿØÿäÿÏÿÆÿ¼ÿÀÿ»ÿÂÿ¼ÿÆÿÈÿÅÿÕMÿYýÿÿ5óŸÿÀÿAÿ–/ •@ÿƒÿ¤ÿ½ÿÖÿçÿH‚HÿYCYÿ\Q\ÿ=:=ÿå{G?Œ3û›ÿŸÿšÿ¡ÿ¦ÿ¸ÿÉÿ×ÿãÿÒÿÇÿÉÿÈÿÈÿ»ÿÆÿÈÿÅÿÑ>ÿUúÿÿ4óžÿ²ÿ@ÿ’0 @×Qÿ†ÿ¡ÿ¼ÿÕÿæÿ={=ÿ?m?ÿ-ÿÌkB07‰+÷–ÿŸÿšÿ ÿ§ÿ·ÿÈÿÙÿÔÿÇÿÈÿÉÿÅÿ¾ÿÇÿÈÿÅÿ!Ûgÿ[ÿÿÿ/åÿ´ÿAÿš1  1 ã;ÿfÿ‚ÿžÿºÿÓÿêÿ µ ÿ¢ÿ7ö¦[>03€!ô“ÿ¢ÿ™ÿ ÿ¥ÿ²ÿØÿÓÿÆÿÈÿÆÿÌÿàÿÌÿÃÿ"ÜeÿRúõÿXüÿÿ@ð½ÿ©ÿNÿŸ1 {ùQÿiÿ‚ÿœÿ»ÿÑÿêÿÃÿ ÿ<ù¥]>09ŠöŽÿŸÿšÿžÿ¸ÿÙÿÑÿÉÿÆÿËÿáÿÜÿÄÿ ÛdÿWýÿÿVüÿÿPùñÿ!Ýaÿ¹ÿ?ÿ–0  "øNÿgÿÿšÿ¹ÿÍÿèÿÅÿ¦ÿ@ø«`>6b îNÿ˜ÿœÿžÿ±ÿÙÿÖÿÚÿÖÿßÿÜÿÄÿ%ÛmÿSúòÿSúÿÿUüõÿ ÚaÿÅÿ¨ÿWÿ¤+"{öMÿeÿ€ÿ˜ÿ¸ÿÌÿçÿÈÿ¥ÿ H ú²aGdæIÿƒÿ™ÿÿ»ÿÔÿÎÿÐÿÎÿÒÿÄÿØYÿQù÷ÿXýÿÿUü÷ÿÚWÿÂÿÇÿ¿ÿ@ÿ”$ t ïIÿdÿ}ÿ”ÿ¶ÿÊÿèÿËÿ³ÿ`Y^û¹p|ïHÿÿœÿ ÿ­ÿÅÿÅÿÄÿÁÿ¼ÿ ÚeÿVüúÿVüÿÿPùïÿÙZÿÃÿÇÿ¥!ÿa^ÿgÿž k ÞGÿcÿ~ÿ“ÿºÿ Æ ÿºàºÿçÑåÿü·ÿBGgüšèYÿÿœÿœÿ¤ÿ«ÿ©ÿ©ÿ£ÿ#Ì_ÿUþñÿWýÿÿUûúÿ#×mÿÆÿÂÿ°ÿ7Ûÿµÿ ÔC ` ÖCÿaÿ}ÿ ÿe‚eÿŸ”¡ÿîâÖÿ¦»Ùÿ?ûÿ rüâ,ÿsÿ™ÿœÿ›ÿ™.ÿ˜@ÿ™0ÿ”5ÿ®HÿEòïÿ9êÿÿDñüÿ!Õ_ÿ°ÿ­ÿ¾*ÿ’Óÿ8Åÿ!èh ]ÑCÿ`ÿC`Dÿo^nÿ‚oeÿs¡«ÿ™ÿÿ;ôÿzÿÿDÿ‰ÿÿœÿ™ÿ´ÿÇÿŽÌÿŽÄÿ¸ëÿ ²åÿ³Ñÿ Çbÿ¶ÿ­ÿ“ÿwÌÿ‚ÞÿÖU VÉ)5)ÿSHUÿ\WJÿKo‹ÿ ½îÿ¡þÿ"÷ÿuÿÛ.øžÿšÿ¢ÿšZÿ˜˜ÿ•rÿš‚ÿ”ƒÿ›rÿ•‹ÿœ^ÿ¶ÿ®ÿˆÿ"Òÿ*Ëÿ âi MÁ41$ÿ?>ÿ͹8ÿwÿ™ÿ¼ÿŠÑŠÿ×ËÎÿ18k÷’, =7íJÏÿ©:ÿ¨ÿºÿÅÿ’ÿÍÿ-Ñ-ÿÈÿÍÿãÿ÷ÿ@ï@ÿåÿ5H5ÿË[; ®NÿwÿHuHÿ¢„‹ÿ}±Üÿ:ëÿ?ö[; 1çnVÿ­ÿ¦ÿžÿŽÿºÿÜÿq nÿ7£Pÿ¶&ÿ¿ÿ0±Qÿ†µ„ÿÿÿ­ÿÍk/A½";!ý]NWÿQs‰ÿ—÷ÿ.Õÿ4ÜM,2àbÿKúRþUÿ…ÿ²ÿÊÿÆÿžiÿŽëÿðÿ™ÿÓÿëÿÿÿåÿ@ì75“Kö=óÿ,Ãÿ "ËD  2w˜x°Rþ˜ÿ¡ÿ´ÿËÿ’gÿ£ÿÿ©ÿÿ¡ÿÅÿÕÿïÿÿÿëÿFð…IU¤Lø'Ü] Hà§G&=Ƈÿ¡ÿ¡ÿ¾ÿ ¥Zÿõÿøÿ ˜ŒÿÄÿÈÿÙÿðÿÿÿñÿKîÖÄÌíÏn1…Vÿ„ÿ(ÉR.H °zÿ¤ÿNƒKÿE]ÿ¬0ÿ¹$ÿ%ªHÿuœsÿÂÿËÿÖÿéÿþÿèÿ›ÿÿµÿÀÿ«ÿ>ê~ hÿÝÿ’ÿ Ä`R±:I:ÿ”ÿ,‰,ÿ ›ÿ¯ÿÊÿÎÿ7º7ÿÂÿÇÿÃÿÓÿåÿúÿþÿøÿÿÿÿÿþÿÿÃ-x^ÿ×ÿÙÿuÿ ͽ>?>þZQZÿ>L>ÿŽÿ¢ÿŸÿ¯ÿÇÿÍÿÉÿ¾ÿ¹ÿÃÿÒÿæÿìÿìÿéÿ êÿ%ÿpÿŸÿ È5*ćÿÑÿÛÿŠÿdUdÿjkjÿPRPÿ-'-ý ÐOïœÿŸÿ©ÿ¼ÿÎÿ×ÿÆÿ¼ÿÀÿÅÿÃÿÈÿÇÿÖOÿ<ü´ÿ£ÿÒ:Tÿ¥ÿØÿÚÿeueÿ[I[ÿ:4:ÿ¸Q|Nð¥ÿœÿ¤ÿ¹ÿØÿÝÿÉÿÃÿÅÿ½ÿÆÿÄÿÕTÿ7÷§ÿ ÿÏ;?ãxÿ±ÿØÿÎÿEoEÿ&ø†:(‡rÿ£ÿžÿ¤ÿ¾ÿÚÿÐÿÇÿÇÿÂÿÇÿÅÿ#Üjÿ;ð°ÿ›ÿÖ>¢<ÿÿžÿÊÿÛÿ§ÿAæ‘C3Bô—ÿÿ¬ÿÔÿÎÿÈÿÏÿÙÿÉ ÿ1å•ÿYþÿÿ/èŒÿšÿÒ<" ³Pÿvÿ—ÿÂÿàÿºÿO÷ŸDI àhÿœÿ©ÿÕÿÖÿØÿÖÿÊ ÿ:è©ÿ]ÿÿÿJõÙÿ ÏÿžÿØ9;äQÿvÿ˜ÿÌÿäÿ ¾ ÿ=X<ù•[ Þ]ÿ—ÿ¬ÿÍÿÌÿËÿÆÿ7èŸÿ[ÿÿÿNøäÿÔ3ÿ¾ÿ“ÿ!Û0KÁCýpÿŸÿÂÿÐÿàÏÓÿGNlë¦éqÿŸÿ ÿ­ ÿ­ÿ¬ÿ#ÒqÿWÿÿÿDïÊÿÌ,ÿÇÿk‰ÿkÿ“ .÷jÿah`ÿš€‚ÿ½ÚÿXéÿ2ÿ<ÿÿŸÿ–Vÿ¨ÿ£ÿ¤ªÿÈöÿÒžÿ¼ ÿ¤ÿ”Žÿ<‚ìp‡/3/ú`SRÿC}šÿ·ÿÿGÞÿæ1îšÿŸÿdÿšÿš{ÿš†ÿ¡dÿ®ÿ¬ÿQzÿ Çÿˆ '-QüQÝÿCäÿ#`ÒOf,ÔMÿXþXúVúTûSøNûRú$8û(¯$ q=ñ!Û>#uˆqw]]k\N>.ÿüÿÿ€ÿÿþüøðààÀÀÀ€€€€ÀÀàðøüþÿ€ÿƒÿÃÿÿ(  OI¡+Ë%¢l) E¿ Vsÿ Z ÄWü¨ÿ±ÿ4À613zÍ·ÿ ò&ÿ‚ æMvUû ³ ÿÆÿKÓK"!pÍÆÌÿß(ÿ¾ÿÊÿ…Ú³YDYû$J$ÿ«ÿÕÿ]×H y—ÿÌÿ¶ÿ¶ÿØÿøÿ7Ê7ÿ5;6íAã™ÿ‹·¬ÿ%nÞ*‚hÿ{ÿ ÿÃÿ¢xÿ§ÿä ÿ±õ}V&%3× RÊÿV¶ f¦‘ÿ·ÿŸ´ÿ•ÏÿÅÿúÿ¿÷® %éQQyÿ5§Q<Ù"˜"ÿ¥,ÿ¸*ÿ&º'ÿËÿðÿÒÿ¿þÉÿ8¾5î¿ÿ ? áV?Vú!F!ó‹ù¸ÿÊÿÆÿÅÿßÿåÿùWÿaá%¨´ÿ'Ä'ÿ=Q=ÿz‰ÿ®ÿÐÿÊÿÁÿÄÿ.ë†ÿ`ä(BGï¬ÿÆÿSÎR¬ˆÿÂÿ×ÿÒÿ4èœÿ6óžÿbê)\>ë¡ÿ=Î5ÿRU_й}ÿ² ÿ¾ÿ.ä–ÿ=ò²ÿ·;ÿ2Í:- Ød‰ÿ2tßýòÿ˜Yÿ˜ÿ¼{ÿ™(ÿ=hÞ 00 Z×W²3”+ µ(¬'ª£<þðàÀ€Y€cú€üÿÿÿpÿÿÿ€ÿÀÿà2ÿðôùœuqm-0.6.2/sc2/src/res/sis1.ico0000600000175000017500000000427610543202106014433 0ustar joeyjoey ¨( @€€€€€€€€€€ÀÀÀÀÜÀðʦ """)))UUUMMMBBB999€|ÿPPÿ“ÖÿìÌÆÖïÖçç©­3f™Ì3333f3™3Ì3ÿff3fff™fÌfÿ™™3™f™™™Ì™ÿÌÌ3ÌfÌ™ÌÌÌÿÿfÿ™ÿÌ3333f3™3Ì3ÿ3333333f33™33Ì33ÿ3f3f33ff3f™3fÌ3fÿ3™3™33™f3™™3™Ì3™ÿ3Ì3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿff3fff™fÌfÿf3f33f3ff3™f3Ìf3ÿffff3fffff™ffÌf™f™3f™ff™™f™Ìf™ÿfÌfÌ3fÌ™fÌÌfÌÿfÿfÿ3fÿ™fÿÌÌÿÿÌ™™™3™™™™Ì™™33™f™3Ì™ÿ™f™f3™3f™f™™fÌ™3ÿ™™3™™f™™™™™Ì™™ÿ™Ì™Ì3fÌf™Ì™™ÌÌ™Ìÿ™ÿ™ÿ3™Ìf™ÿ™™ÿÌ™ÿÿÌ™3ÌfÌ™ÌÌ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌfÌf3™ffÌf™ÌfÌ™fÿ̙̙3Ì™fÌ™™Ì™ÌÌ™ÿÌÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÿÌÿ3™ÿfÌÿ™ÌÿÌÌÿÿÌ3ÿfÿ™Ì3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿfÿf3Ìffÿf™ÿfÌÌfÿÿ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÿ3Ìÿfÿÿ™ÿÿÌffÿfÿffÿÿÿffÿfÿÿÿf!¥___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøðûÿ¤  €€€ÿÿÿÿÿÿÿÿÿÿÿÿ ‹ff f‹‹f  ffŠ% $$ ff‹ _¡_ $%ŠŠ‹% ¡Ö¡ $%÷ÔŠf fŠ‹ _¡_ $싊fŠf fŠ‹% fŠ‹ŠÔf ff‹ f fff‹‹‹ŠŠf ffŠ‹% fff‹‹fÔŠf fŠ‹ f ffŠŠÔŠf, fŠ‹% ff f ffŠ‹‹ŠfŠf fŠ‹ f‹ fffŠ‹ŠÔf ff‹f _¡_ ffŠ‹ ffŠ‹‹‹ŠŠf ff‹f ¡Ö¡ fŠ ‹‹fŠf f" _¡_ f‹% ,ffŠ%ÔŠf, f fff  ffŠÔf f fff‹% ffŠ‹ŠŠf " ff‹ ffŠ‹‹‹fŠf f ff‹% ‹‹ŠÔŠf f ff‹ ,ff‹ŠÔŠf  fff‹%  f‹fŠÔf f ff‹ fffŠ‹ŠŠff ff‹f ffŠ‹‹‹fŠf fff f‹‹ŠŠŠ" _ fff" fff‹ÔŠŠ4Š ¡ "" ff‹fÛŠŠ4 …æ… "" f‹fÔŠ4f _¡æÖæ¡_ ""f4fÔ4Š …æ… "4444‹f ¡ ff‹f _ fff uqm-0.6.2/sc2/src/res/darwin/0000755000175000017500000000000010552600273014352 5ustar joeyjoeyuqm-0.6.2/sc2/src/res/darwin/Info.plist0000600000175000017500000000127510543202105016307 0ustar joeyjoey CFBundleDevelopmentRegion English CFBundleExecutable The Ur-Quan Masters CFBundleIconFile The Ur-Quan Masters.icns CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleShortVersionString @@VERSION@@ CFBundleSignature ???? CFBundleVersion @@VERSION@@ uqm-0.6.2/sc2/src/res/darwin/PkgInfo0000600000175000017500000000001010543202105015601 0ustar joeyjoeyAPPL????uqm-0.6.2/sc2/src/res/darwin/The Ur-Quan Masters.icns0000600000175000017500000020242210543202105020602 0ustar joeyjoeyicnsics#Hþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþis32÷3r†3  *($'F&  .*w} 1;$2IH<$3dr=74em! $;p^)J&$4…p „^IeE[#,?WW|r\ /!=]P',>OMq *Bkx4"iaU$*]m96…Q6 .r~kQ)Xs7O|\7?<3\„J( 6'A)5    &6" @  B* T- ‚ :M &AA $ jP /?'"L•‘RYb\q‚ W7­O60 +Z [B .  7+Zl+c;9_$ ?*4&   ?)//, &3)    ) ) $„„ ; €|-6   ¤1;"2FD:93mr=82nm /$U"pa3K$:B˜nke—E[!EPcW#x!/?^P&+ r/Lky4s2 ,]o8; €LG„o) -N C` +G%d)V4~†Hj …+ s8mk‘½Â½’ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‘½ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ½ÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÁÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀšÿÿÿÿÿÿÿÿÿÿÿÿÿÿ™(¾ÝààààààààààÞ¾'ICN#ÿÿðÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþ?ÿÿüÿÿðÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþ?ÿÿüil32 ?qœZŽ ƒ 3€1.S•¹d$  -/53$.BX®m  ƒ. d=6sÿ,%    * +w ¦= "€=4€;==X"ULX m  )==C1€1%)=Q9mMB w d›ÄÁ=3'fžÄÁ2&:€\9’ƒ:­[( ´D3<J ßpÅoSy D€Ü)ö gR‚ #$M2oC >Y HÛ3mS‚ÇvG-AKŽ(}sX =k°¨D”C…Fv„#(*’Y” 1,DK!„€[¦Ir…7G?o U—»¬3 >F Fd€@ymÁMÀ%$# [¬Z & €N’‰`*†B>^3ÌMä @du'FÌ4ZHH$¯fKT zL"!Q– )L‰?4_C ‰oqE~³<ˆ*7>R ¸­Á  *&#.¿FŽÒ€‚b/ 9?މ¬/ >;*Gq€5–j?5O- b±JUp¸Á¨Ž,+  €Jm¶/)  .›KiŠ9BK(Š€PJ8?‡XY‡#! Vª”:q6!(¾,7"5gD²¯eb0)fJ!!MK+C VX &€C  Š#0#   rb Q  5 € Amd ‹ "ƒ 2y˜ ƒ% ? O [54 ‹ K ‹ N Wˆ  I"2( ‡ ‡ y  ,\‘KY    m  1Ì€Q€    € $<€€,3.h EpÊÖ‹G.s‰‰{hqU^#=z"!);X›ÊˆDhG+ ‹6pt TªY8?1 #0#KDgv2Ì Hb…x@N?( „ N<¯?'}* +. ";€K 7' ,‰Y !1h#! `+mAD;+*34* @?€,@0C% !   ‡hR#8B,-<:" € € _-/7+!€€: ƒ /    >  ( *&    €%'.")ƒ/*%+ … 2-&9€   ‚503 (B&‚+ ‹,A ‹3Œ%#€2•€‚Ë šÈ„…¸•ƒ  ‚ †«© ‚ „€ ÑK "€=4€;==S"QIÏ« )==B1€1%)=M7eI@µ dŸÅÁ<2' e£ÆÁ0%b€v\".9”<¯ [B ·@V<dßpÏ™S|D-*€ÜIöž R¼%;$M1pB>võFlTö« GEk{Ì'}tY =¨ñËG–D€Ã#(½KÉY•  1!IDK1„‚}Ã7K?p Tœ¾«0>F Feƒ Þ9#"[¯X $‚A0·BM_3ÌMä ò/EXH1R5¯hISzM€‚ 9ÄYKbC'‰ysF€Ê„ ö *&#.¿FŽ" ƒ4êK >;*Gr‚‚ ÉóÙÎ++‚ €€¤1‚ €€8   à(EW  •Q  KoL‚F€"€ž‰‚‚ Vƒ `‚Ô‚6" ‚=™ÎÆ@`„…>Mƒ,Å ‹as$¸tŒ¸º€ Œ–€ I™‚l8mk?r„„„„„„„„„„„„„„„„„„„„„„q>MÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿCÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿBoÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿn‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‡‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‘‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’Œÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹zÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿzPÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿQÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ›`œ¸ÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁ·œ`ich#Hÿÿÿÿø?ÿÿÿÿüÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþ?ÿÿÿÿü?ÿÿÿÿüÿÿÿÿðÿÿÿÿø?ÿÿÿÿüÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþ?ÿÿÿÿü?ÿÿÿÿüÿÿÿÿðih32zƒ¥U_È‘;€  … ‡OfÑ_$Lq¬d   ‚  'O‚,Id•mÂq€‚    .(+,€ +.8TW~Ë]€€  …' `K?3`À""$(*%f[g   ‚ W©m%+Tm§3(&   ‚# '{€/Æ|  9‚= € =RmR=U,bE!š‹ 6‚=A,1„$€=1hD?mNX &‰˜=  ‚=4-=)I=:m=m/ uggޤ¾Ÿ|=+!€ c•¦°Ÿ( '\0€€,/hjLS_Âìæ (y qhLU_ÇéÏH Fc$ $@#£æ 1"6Ù h(¸Ù BAC #íÒDÕç0¬…Qó TF€¿Ñ+ö¢ E,U%o0$ N·_ö00& y 27?9ç©2í sV  0Unf 1'%.ò1"A^ ?*LC¼˜&è ŽÍªb ,Ul2PqumB Ã.  7*¡K–™<¶€+F‚Æ„?vk>€¥%½‹Ÿ *E-.˜”MÖŒ*O®F ÐŽ -U ¸2„d2#-Œ.  7U)" S-+‚)>ƒ”J&¯Ž6P5 Qk .U—²±l&AI5[k* O;dÇK-ÏL IL[^VA" KvdWlröç:&KS[WS5‚ \p‘kuËŠLŽ« € KR Hò`  ‚!QŽ>}Òkpª~Â4 AVeP ¨u hö€ ‚*FXGYD!+~Kx± {x‚I@-Löy§¢ YD€g"#G‹w!! UMÉ:,"ÚT!O ½R°{Ÿ Ê I1#" E’p AŽF‚«'9K1 ¿AnšØ¶!oz'".Ed>€ ,0¢Ÿ³'((7:%"; µÉÌ*¸ID~¾}9^L.0!"€ G~âªËŠK e-P€ö>£kFöXs¯\I" ,:aØqÁ†L >Z ‹[€X¤‡I2'fWB"  %e~.F™wȵŽU)8`7KW_\K) Œ{2SŸl.(  c–¬;Bhm’ÐÌÂŒq ‚%0ˆR‘ Š ¸{V  z $39‘ ® $@ ‰€   ,@]y+1  dd  a ,  <:ƒ gKg€ ‚ † =€ V €6ö¸~Ga~E‚     ^ ƒ  5[A~…/†ƒ€‡‚ ƒƒ-%_q;Qh„£èãhM$;h„‘‘…£„„<† (8#38b 7S_w¢ÂëÓ‡^/_‰…wi‚\ UC;8U{}‚ +=.`/!2;N™¨Ül/TT//Mov‹‹{oo˜ííG€$%Cv*8ATotv~zZKNRDGX‹šØ…Ü'³™E))W #K# :Mo™ÓÓÊŒ\J=x‹ˆ}o‚b0\GMQAD.$.D N~Œ‚«zdda^[L[…›×íªljoa\D4(-Uj‹ª‚²qs6$33e}¨¨°¨ííõ‚öí~AG1//GTo¨Îíƒöíôööñ°;-T]‰ «¨Ïííóƒöêç€Ú ÙÚÝÝ×Ýääíð€öôöõôöõöÛ¤6m~b}‹¨¨°ÝéÉíí‚öôíØÉÒÛÉÉèíÉÙíöñööô€öï¨E$*>NZ_Q9/ (<°öñïíí€Ò!ÉÉż¨Y% (Wb¦ÃÔáî¸a>$ !!€)§ãíí²WSXɹ¸¨M€Y(AGRjjLAK$ -   @/žåÍ'GѪd($#„jQFGRM %;1  #íÒD?&loS R G‚+¿Ñe‡¨¨ˆlB*0  N·HKÆ7 ;–€,™©_1B›…oN4$  , R%.7lä¦8$°–€,,H0;yoT8'p.    mBkíÉ堾ɠ€, ;oM2 5v…C65½ „ÉÈəѴ®,"=M1  ‡  Z1 2#+ÁɨlT“ÉÁi€8/;( B““9& @€¹f;@(€  ˆ ‚$š…  (!_¸U‚%;5*+ ‚L !+$-GQ„k   FA¨ˆz-1$;?B2!€+&‹8GIZo„o¨u QG‹‹„`FTGD€e$!g@  $ceMLöoKo|s71L>37. @n$8`!½R" X‡ 4* ;+€, |7  :¿A Q<)! *€ ?6€!µ%O  8#'  €? dv !;5e> GNT1-˜0F'  @z !=€ CDBG/ €(% G AD‚;A(2. €*  ^‡lS.DB;% *;?>8‚‚ . .5;E8G;;5!€ ‚,  kG2 (8 € :! !€ €1  €i#"  ‚>    /!'   €4D?   €€ M  6!%‚‚ !E3: €  ‰:G=%ƒ   ‰ L ,485ƒ… % 0>= (.€8: „ T>$&;!„ 7# ‘ .J.>€”E€.6H ƒ 0 '€€ ƒ$; € €˜ €0ƒ € ±ƒð_ñãdƒ Ÿôˆ]Ö›5 „Šö­‡ €€‹.ö˜,€‚†‚ ‡{„¥(€„„    €€‚!‚ ö» 9‚=†=OeM=Q, € ½Ø 6‚=@+1„$€=1aB>eJSçm ‚=4-=)G=9e=e-¤žg“¥¾ž{ =+!€bœ¦°ž$ &ŽO„*2hjLSdÅðæ &v‚qhLUdËîÏp/‚*c$688@#ªæ0(7Øh (½Øf€Ah#íÒD×ë9Ù…QôTt€i¿ÑE*ö¥i#,U>²P@ N·_ö.MB x27h/.dö©SŠí¢ˆ 0U­sUE%.ó0 !A\ ?*ãzrñ¬=ê€+¢öö™ ,U(ªX­·.mB È,7*ö uåã<¸*A‰êÃ1?˜¤j­æ ½‹¢  *EHM×ËN)Öƒ'  öÒ -U çX³2#--7UE= "S-4+…%ÉÒ6P7Qk-Vžµ¶k#AI5]k‡% ös IL[^VA!KvfWqwöë9%KS[WS4„%  •Þ  KR  Kó^ † à\AV.eP!¨u hö€„(VZ~ò~z‚I3BKLöŽ|¯¢YB‚…!Oö`,!"Ú T ;`½R°{¦Ë I„€ …ï%?9K3. ¿As¡Ø¶:€ƒ€*ö=@?7:%8] µÚÎ)¼/ra€ƒ€ 9öÍK e-P€ö>¦kF5T„ÛÆ' L >Z […€„9?çòÒŠ?[–7KW_\K(‚€    ƒ€ö©­†  ‚‚ö‹€„*  uÏ0Y2' ‚   ¶Ñ=Hp ‚ yJ€€ˆÈ0Nƒ€…!b ‚€| H+†!'„‚=öq6ƒ/ƒ€€ Ø  T+›ƒ'‚ €‚ žÏl€Yj 3€ +sˆöÛÅ„Ø~ ‚%‡ {¹ &„¶‰&R%u™#ˆ [{(i%¨€ LæJ' ƒ(‰Û؈öÐ.„‘¾ö´vº; •è7^³ I!ƒ•ž<€ ƒŒmƒ{€`T €‡ƒ€F ±h8mk "0888888888888888888888888888888880"WÃâõþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõâÂW¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿VÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿUÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿù5þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ5?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?LÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMMÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMDÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿD?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?*úÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿú*îÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØ‹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠ&ßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿß&I«áñúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúñá«I7u{Ž—››››››››››››››››››››››››››››››››–Ž{v7it32ÊÿŠª¿¥UUZ[_ÖÖȱŸˆm; …ƒ € €ˆƒ ’ ‚''™?YijyŸÕŠIGYZcTdžÍ¥‹ˆnX)€€ € €…‚€  *)(/=6UV[kt‚™¶É”VKPEEHX‰±’…žˆrD   … Œ‚   &%*:UHU‹HLPZ\q†–“lÙ­…Z58@Xº¨˜„l0/€€ € € €*%  ##"-?NO?ŠFWY€\Šš€ ÙƱe‚@Iƒ€   €‡‰€  #.+""-BGFFˆ',EIIK\mƒ•šŠmÙ˸£q4…‰ ‚ „ „  I5€.""+.-,C…"+-028IK^aksqm{¿Ì¿£„9 €…‚‚   ‘€ )ZJ€E-€#&EWUUƒ$€.1;;SY`€d m–ºÍ¸œi,  ƒ€‚„  €‘ &E\NNPI.((/:Rd“£ƒ"++,€.BLT€W ii’¼Ë±š]3ƒƒ‚ €€  ’€ (R`\NKLI5/3BQ`t¸Èÿ €"(-.:€E Z[[gÇɳ‡p?€ €  €€ ƒ   ?hmmZJ4+EE4ET^mŠÙæßƒ"%….IWRIIÙÙ˸¦q<   €€ † ˜­mmI5(%..EW\^mŠ·Öñ†"Š 2ª“xb.€ €   „ Œ„ 6m‚­m‚" ..P\^mŠŠ¡± ++"€€ 2*$ €   €€€€… !‚1 %%N\^mŠŠ‡†#+<<(#"&-   ‰ €  €€€ € ‹#€ '.9{ŠŠvm(1II.2;GN> ‚‚  ‚  … "6ˆ=CII$ h‚jaU€ (3II,]‡£†B ‚ ‚‚4„=9   € †€ € 4Ž=U€m€=3 \kgfU)+5dÆ­|; ƒ  ‚9##Š= ‰…€  €9ˆ=(gmmg=Da==4Ua= `fbE1pƪ¢q3 €   ‚4Ž=, ƒ€ƒ †=4‰=Ig=9U€m4= AU5Mh¯±–a8 €   € !*=931)#ƒƒ€#!0…=(#:Odla4%6Rmm4;Oaa=5 4-‹žµ¥€. €  ‚ ‚.‹=OI==++84)„'4…=+;U€m(U!,ImmU6LmmU@! J¹¼¥›j ‚ €8ƒ9„=]R€=9<=9ˆ €0898€9:==9=Rimmg#,Immg0BimmH$ € ‰¥£Œq=   € ‚ ƒ‰=4=9‡€‚€#==9=Imm=,Imm€=I€m/ € ‹¿¸Še€ “ #„=9#Œ€€  „ €ƒ,ImmXUIm==# €‹¨ŸnB  €$,9d†r„†‹–† €=59"Œ   € ( <[||t††–]9 9^eimC8U^C €uƒ{R*€€€€BgaiŽ˜¢§¶¾±ÉŸŸ’f  6=;4#2!ƒ…‚2 %Fca‡•£¨Ã°µ±ŸŸ "$-I ',# €pmd=€€€" -Gk~‚Š¢¢­½ÊÐÆÙääÔ¯pn (+,*ƒ€) 1Qn‚ž¢§¯¿ÕÅÓÜäämmkP  € €m_T,…„ 8Xn~{ˆ€˜´º¾¿ÆëõéÜÜÕ'ƒ  %&'& € 6`v~{–˜˜›·€¾ÉìöÜÜÙ¨ ‚  €€L<2 !HU[kXF1ƒA˜ë‚öE ƒ ?˜­Ì×àÙ   € 2UvvhUA„&£‚öØ‹€ H4,ˆ MU`fA2? &˜ööàs  (;K€DÕö € 2UkK!.Q\„ …ÇöóÙ ƒ€ H4, ‡=MTcW? !$0<@6*£öôæ¥  ED"FYÜÙ& 6QhF€ (73[¸öóÙ" €€B4* ‚€_1UdR. $S’­’qE&¯äöç» 3$Ir«ŽFö& :RfK .4^srY+H¸ööÂa € B/& ‚€C AZ`= (E $]­Úßn8rÎòöö?9%n˜ä¹ö%  ,H\a1 !2.ƒK„ŸŸ…Q !!íöö‘# € €B$€ „B (?Ah?(^¸  #W íõæ¿|D‹ÕôöØ" 9'G¬ …È¢ó$ #9T\9 9RQ„`¿éëѶ%0(·ööËx ƒ  €B3'€ƒ,!0AU -^ÆP '- 'B­íöä­R#làöÑ!9*ŸPÙ!#9K@e…U„B ÈÚööu,04ööäƒ  €B3'€€"7CU-5W ty. #dÃãíÑŠ2 {€ö¶0 GqD kÑ!€ #APA""=ƒ44IrÜöÑb:.FÙóöä­ €€E4'€"7CU7iWA6+ . 8k|²x2Bšöö¶1  !T’! #AP-]j‚ 1L>g”óöòF7z$Üöä­ €€€\SE€ +"-`0Øöᢠ€€ s}p< € "?PUn´¿ € !)92' *>. =öï¯1  "€A[cX  -PT*ƒ0hKCx•¼ãÉf<&=JØóݦ ‚Q„¦ qC<  "7CUh¯Â2!8BRLA4+A%AöÙÎ;    -AP* $“„:tEPoΰÌzN.9tØèÖÌ€ƒ„½¿ªªq<€ @"7CU>‹´2 !8PeoqiJ"F­2_öÙ³1    -AP* 4ªƒ/zhn}¨Ù­†W((Øèέ€€…ŽÏÔÆÆªªŽb. €&"7CUTˆP"2;BPPqquu`=E•öB gÙ­š. €   -AP*¡4 ƒ %qÆ–xx™Ù­sV<2P¾Ã¨˜†$NuÖÖÓÅ¿³”c. €@"7AC(6^ˆS^gdN@]†¥©n`Rµ…4pÔ³­x"    -AC5w_ƒ%¥¼„r|³š`D;[Cظ°žq€ˆS(@€§ÊÐʲS(&9AA-YžZikbD/Z©¶§se |¶Æl$ƒÖ­¢E    (7>A1Ez2 ƒ o«¢˜Ž—wG+$G ä´§‡6ˆ7'(+/F]¡µÂȱR+ /& h¹Ê·œb).AMS@:#.)9}‡Œg: € € 2A[qbss€n@   2FUE#  d}‰†Z‹%H>lyŒª”p]J6!+u¯Ê¸ŽR6FLU75% € 2 :F\Œkk; .D:pˆ——¢²¯°³‘l\E&   AKR@+5 €@5|kc,Š%'O4`l~¤¸u[H2!2u¹Ë±.%7?PPdR>‚2#22AAUCKPCUAA7" KUk~kUC„˜öòÑ  0A->AKSAUCPP>-#€‹M–¢pYwoK\”¾ÏÌŸzUJC;-ÙÆ¬i+ 2A2?96>)  KTcXA „a¸öò¾5   *=:4A20+! €€‹^—ÍËR‘~w_Ku˜²ËΟu\L;ŽÔÅ‘W ƒ   AUdR. €H¸öïÈ`    €€€‹" Q‡ˆ”Œ>¢¬£zXYrŽ²ÐÆ”vaM.LÙ˪~ €€€2 /U`X.$&$ ,,[Çööº_  …€Š#=uˆwnd1žÛÑ“pKTp–¼Üª‹vbF!ÆÈ»™€‚€' &GXf>.CG>/?TT- …òõö¾ € „‰!9mz„jXN.}è麑kKYp„ªª—~bFB³Ð´4„& 1AKkAASvvP- SÑÑuH, 9Ñíöߘƒ  €‰#>FXiXªS:8YRu¼q‘pXEEZÆž‡uX,#«Ð¼q"ƒ€"7FU4k~q?4Ci¶öö…E; A¹öïÙ  ‚‡)A:>D6Xiœª¢!+,aG4&$'7ŸyiCg¬Ð£2!!ˆ˜·½Ë£€4(9HK2?k }b91~ööË—k}Æ{¿áó˜   …f!!&$*3F\k¦& *"A]u‡S:AŽÕ¿b60Mn+46Ba£º-QN6±ïB-@M@<9vvQ9€Q¶ííÓ¨‚öKôï¨ <;|»£…‰o‚„ %! €" !&/I\„¤¤m"! €2 :‡U+#wÌÉ­~: ,<4R "X¾Ú;-JT@!QSK9 Z½¿–Rök{ðÜŸ %ÙÊh J\I„1,&#" !&EZ¢¤p!…& )FF#E‚ÙÆ­X L<' eW¿ØÚ~--…F*(ƒ" #.Ii“™p€8  Ekk~X&:ÙÆ­9"6ÆW¿ØØ~-… 1@p~‘ŸŠt]-Ùɱf1BgaK)¡_->72GI(…'rÛãξÀF²ÝŨQÎ #K{"€ƒf‘ª®ƒ~X.-?NROJIE.+=?;' „ &I|­Ä± ‰%ÌÉ´“i  XM'€ "6DU ?cNƒ DÃŽ±ÃÔÉžº¢’¢ )Lf~7 ƒ—­ÏÕŽ|S0DcftaNIE.€" €„  *kÀ㸵º‘uÌ˸™" *CUk€ "-7UU AA0 ƒ 8d­íÀ|H­­—{kUU€ ƒÀ߯Ÿ~k6Dj“­ tRIE.€" %I… &X~ÀéÛ½ªFÆË¸£q" €‚ 2AUU _k\€-Pfq€ö¤>­˜‡k@kXF2!‚‚ªö³žÀXLs—½ e\RII€"  €  %;\‡¶ÃÃÜÏg·Ì¿£g' €ƒ.ACSN&/{žÆÝÝáäÛÅöJJ*)Š­qa3  „*¨ªÆš‹vV;Ls“¯b\[XI€"   "+Gb‰š©ìã…Š°Í¸R  €€ 7HR@&>Tq’œ¥®®¤¦2\Ž—`9€€‚ƒ+m·Ç©„pY>+6If›s_\\ZI€"   %,1.:BWk…ØÕªqŠ·Ë±†R:€€"=LRM"1>MU^K V‹vv@€†1n¤©Ê‡kT>02.*'7o\XWWUB€" € € 14;Ui\K33Lfw¤–§^ÆÉ±­ n,, (2=HSShK ƒ 5{jrqRK‡ÀµŒzfRC3+m_QD4ZHEEB-€" € 4;]~~k+8F~¤º¨‡FÙÉÆ¿£€qI" ""P"7AAUhZZ…k€UP9€ˆ€‘ŒzXF$*H~~‘ƒkII2..-"€  € 4Ql‰ª‘kC*$Fkky~‘FÆÙÔÆÆªªˆoe€PZzq€-A0=,‚€€‚ €ƒ~]ZU?%Ip‡©ÕÀ‘qG&.+$"!€‚ :c€~–Ò¹Ÿ‚;63BP[uums{’§€Ð̀ £‹¸q"  !€ƒ…$0=RˆubC=<>;k²ÊºŒkG- ..%"! ‚ €.:^gÊÎÎÂrS659AbgqdTr¨¨ª€« ³qMWË6€€ƒƒ'0drqgb<:46Rf¦¿¾~IB/)('*.%""  ƒ  €XO6X~ŒÄðÀªsC*$FXXg€k€# BB8YÙªq6ƒ‚……  kÀv\XUFAO\p‘À­‹bF6BFB6,%€"   "X~Œ‘‡k60Z‘ª”‘uS63BK€XIOI "€.@uªq6€……"€3BXiXXI:0"6XitÆöªb<%6Xkytkk6"!€"  &Zk‘¤ª¤‘~X?*)k‘ºˆ~~X;%"6FUOFB€" (/2ÙªJ =  €†0"""BFFD60:IXk|ˆ‘Ž~3>KX~‘Á±Œ~k)!""  , &\yƒÀÇÃݯƒ\@02Y|ˆ€ŒX^D9.%)=B># (./ŽÍ¸‡L€ K, .€‚%"")6:7%00HPWuy›‘yT7>)! "!!(/2f‘ymi\S?' „" !$5W~¤¹ˆ#,€EH;+"" ƒ  2AT\k|pbbC.!! " † HjdA9 €!!;LV^baOG2&"€ €" €‚?^pf7F=6( € ..\N;+" ƒ -:QXbbO;7! „ YW/ "9IRdIG8,!!  !""  ‚ !,jqVA €\N;+"   *DSPC0‚ƒ  GD € " "6XI%‚ ""  ! € *q|L=7 %N€\N;+"!"!€€  "$6 ‡"‚ GQ; "! €  "" †€ ={Æ¡J \\I5.+€" €    …ƒ 3+ †  €  † &i£¥p KI5)#  €    … ‚ O6 ‡ 33Š ¼¯Z€ ›§a Æ \³‘ ‡   J©ŠU7  ƒ!-$$@]>b) !!Š 0Æ®V -£m/¸K€•G ‡ ‚ 7¦ªR#S€  ((#" )7QyL±V!‡  6ƪR ‚" tXM€‘ ’   € w±’## –}?p€l …  ƒ H|¡y <@/ƒ€  @Pcg³ d±— ¸¤QOZsV7 „ „ GzŠ+ %"‚€!33+3AE ˜ — w±’ƒ žR ‚ª«%„  G@  € .19CI<0'˜ — ¯±‚ƒ =”S€ nª¸ˆ  ‚ 2we € Xi‡uP3 ² q¼n„ ¯´y€ h¿ª†   'uP € Iap~~mkE"6FF(‚° 7¼¯>„ F|žp€ Ià    9C!3Pa€ƒ€Ž\ZDGPSU;ƒ‚  § dÆœ, € 7aq€ ,lƃ  €  $(<<6?lƒš“ ¡uXCK[ggX# „  ƒ Ÿ vÆ[  1Q€ Iªƒ  ƒ€ , %'07=I`ª5   ZG%,-6AKNUgj„‡”  ÁáèééíͰ…uh2/1KZs‹€‡lljh[…O„NDCA88$'#%L_t‡«å‡Q Š#%€'8?€A ªe<,$!ƒ#//GTi€o‹¤ÁÉÍííͰ™jG/DPZs‹€oiTTG5†/‰!;Qb€o¨¨Ëܨo;ˆ'.5=?8.ªvJ*(//!!!(2…;//;GGTl™¨åÒ²lT//JTI;/AMZo}ƒ‹‡„o‹¤Ëí°š„oG€†(*.10.>ˆ€X* "".€,-688>DFF‚Q"FDDEE<>@OTXw«­œlT//BLSI4EEFU”œž €Ý߃áà„Ýáåé€íͬŽjL&€€""… €"&)€+.\y€J (/356;;@G€M‚b[ZUUIKMO[o|~w^N/9DIL;;ciks‹™¿€Ë‘íä×Êʸ’tQ2' "#)96„ €"$€%,,Z†v< *588;;FMTUZoor€v‚~v]ZZXKTNOQRG/DGGF?X…‹¨ÏØÖ’Ü˳  ™lR8")'  !)1QUU‚ €‚€&''5˜nD"(,09;FMTWoor‹‹¨®€°zwuoWWAEJPD.AHJQsƒ‹¤¤–ŽŒ žŸ”‡‡„iL9,..&#(.8ju ‚…%#ªªvJ*"/;FMTWoo‡€‹¨¨Ü€í€¨ ™‡ooWKGD/!.JZs†‹}oZTloolT;EF@..%'(.8Jax †Š! #2. !/9AGIT€ov‹‹¨¨¸ÉÉ€í ÛŨ‹sZTQ;L~ƒ‹„oaŒTI>ƒ;2.‚F.‚ #'(.88?D /€5€G.>55GGV\W2$!$047?BQYZavv““¢°°ÒêíéãܹuieM;vˆ€‹€voZZQQI@€91.1BKKQ^€ifcƒb`Y_‚e800&"'(.8865 .ANXc~‰‚‚ž«œ‡m„d^]^cc[UNKU[oy…ŒŒªÆ×ÛÝíÛ½—„lTAjo€a\NN;;4-((/)1=U[[j}€‹ª±‹²€q sjH%%$',3880,#Hasƒ“¨ÁÇÉáëÓ¹‚»©€¦¤~kXIOQT_cee~•·ÁÄÜäÔ¸ŸlT;M„PMDD,/)%*.9>Tk~~ °€»éô‹ö€» ÈÀ†WP:32235+( ,]I&Bo™‚¨Á‚Éä‚íô„öõí¨¨Œv‹oTBAGGTl™€¨ÉéÒ²lT;F„G D;;!,/5GTTiŒ€¨åô•ö ëɨvU8!'-*( de5Go‹ ƒ¨¸Å¨Éé‚íõïïŠöí¨¨~M;‰G;1ƒ/ ;GITTiov‹¨¨ÁÛ€íõöííñ€öíô€ö íͰ™;;0+) !de.+G[‹¨“™ ‹¨¨Á¹¨Ü‚íôŽöñܨ¨‹}l‚TRG/OTTW‚os‹¨Ü†íöîôŒöíõöíôöîÒÉÁ‹;$"#HS`<3CVm‹“— ¨¨®¬€¨ÖÕßíïñöõïãÜÕÚỖÇýÆÇÇÈ‚Í Ë¹ÜÕàæÒíÒæ€íïíïó…öïõöôðò€öô‚öôÔÉÄ b;& $]]E!=Sdq}€‹“¨™‚¨ÊËÉÛ‚íîñöòòõôñŽíëÛíàƒÛäíñô…öòƒöîñöòôöâÒŨoF.$FZQ' @]rlo„‡‰’¤‹‚¨ é´¿×éíéííìêñƒõ‰öõööõ‡íìéí€é êíéíêÙÑéÉéÔÝ€íéïóõñõööõƒöîñöðòöïÛŨoL6-m2&?i~WoTi}€‹‚¨ Éɰ¸ÍíÉéíäÉɃí‰öîôöõ‡íäÍí€ÉÒéÉíÒ‚ÉäíÍÉÛéÉ€íïööíõ‚öîñ‡öïÛŨoL>8E`O AMTW€o}“¨‹‹ “¨ÅÛï„öíõïŒíÉÉÛä€ÉäÛɰ€¨ɬ„¨°€Ééƒíñ€öíô‚öïÛŨoL>8&E4+ /8>A€Wezs‹ŽŒw_bwwC@6!w¡°±Î€öôîõïí"ÉÉËÌŬÉÌˬ¬“¢›S!Nd~“¬¯¿Æ·í€õ€öÍì€öBîîÕ½¨W?<8&$ "*39BINSXZaa]WQB:90(6   (/2G~°Ôîööôïóïƒíæ…ÒÉFÈÁÉɼ®¨¨vlG$% "(/WW[bkz¦¸»ÊöÔÉÑáïïíÕ¸¡aB:4)/&  €?\ªÆ×äñíðîíÝÏ삹»€ÉÁ½Ç¹É½°¨¨‹Q5 €% .GGc{~†žœªµÂ€Ë®‰p_G;@FB$ %ƒ, *+  € € |š´Îéƒíéͪ˜‚””•””›ÁÉÆ¸²Â¬Å¯¨¦ h,  € 7;‚;D€GTTB8$  -- €€  - 0<@/&`B/A¬ÉåíéÍ; +G›¹Ñᬨ–d-‚(73 $Z7#f{jRQQN€FGMRRlWB6€  /850)€  €5 S’­’qE!MG31¨ÅäíéÉv r«Ž=v¤ËÊ“~U+ ƒ4^srY+ ([3+Fm“™“ƒscP g|iZM?6€  +8;6/€$‚‚+ $]­Úßn8>K=¬ÆÕײi uÚ¹3b•Á¹„\4€€ƒ&K„ŸŸ…QPG#0Oz ¨™‰yiibasoTI>6€  .8;911/4Z  #W íõæ¿|D ?b=cl†™oT S ¥¢Lz ™l# €„`¿éëѶeB$G‡ƒ¨ˆ{olRH<4!5; /  e€'B­íöä­R# W=dZaooT *KbolT#  „B ÈÚööu€eB'Goƒ¨volTG<2,€  .;€*  #dÃãíÑŠ2 Ge=Baw¨‹&€d‹“N#€„€$0³öÑb)ªK=1G‹ ¨ ‹‹soolTG<2*€€  '11$;€  (8k|²x2 eT†¨å¤m2 d˜¤™c#€ ƒ* $öò8 V=€ =‹Ã¹–W ƒ) U®®l1G=" ;a„}}oodUGA50)#$€€ !,' € \–‚€ *>. =1lš¯äí¿n8€*~°æÊ–U„  ,WPA67( ;Txy€oiTC88/,#B4,€€ !8€: W“2 +A%8j˜¬Ííé¾§ˆWTWoy…¬ÍåÈŸw… *1#;Ti€olU?4/.-! B_W..€ !! €;6_2   F­2WŒ°ííÍäÜ oTl™¹éÉí͸™b.„ ;Ti€oTI5/.! p¢™ee..  ! €€ E•öB€ kš°í€ÉÒå¨o ¨°ÍíÉéÊ z„e‚€  ;TioiTG<2( € Hd¡¡šf\N%  ! €4  4G Oµ…4 WެÍéÍÉÒå¨o ¾ÆÉÍÉͺše€ …R!€h  ;TicQ><2#':iv‰‡xD  ^  RS: y¶Æl$  'sš¬ÉÛËÉÍÕ¨o Ï×ÉɸÇÁ¦d€ „ 6;3  ;T^UC55'; :]‚““o<  „"  t_0 £Ä²S  P”¨¬€ÉÃÁ½ i“ÑÝÉɰÆÉ¶u0€ †MOD5,+€ !L‚¡e.   e€ :O B¿šS#   b™¨¬€É°¨¤‹Tl²ƒÉÁT€ ƒ€€;G;D;,!!  Oªe< Z$ Z9 22+ TÁ¹¬É€¨™l€Ti~¨¨€ÉÁ¤‹G€ € >G;;2(  ‚ € BªvI& €‚  2 €  T‹¤¨¸Å€¨~i‚TZs‹€¨°Å¨oQ$‚€€ 4;>G;/$!ƒ \ŠxK&     Ji §¨¡—€~5 +`~~“ª²Á™bC)‚ƒ-9?B>2$ ƒ +cxI € €Bh}¨¨“„u€9 1@@^€‘¹¸fD$„€;@A>5( „ .c‰v<   ƒ„Fg}“ •cTJ €(G`™Á´cQƒ†;;C@8/ …€+\ªe.   Gz‹“¨‹[ €o¨Á¸™o;‚;8/… € -uªe$ € !!ˆ GGo™¨ ‹T €… €=3T“¹Á¨oTB‡#8;;E<;2)! ƒ  €+ ‚™h1 €!"+-#-.5GDIY~„“ƒkG€‚€ [1,Ah›¨Á“}xzM1-25-$$16€; CDB>;2&!!ƒ€$4   LªvB !-.19.A18€A a\^k‹š‹g@‚€   ,, 8Q2+=i™¹¢’‹‹oXKKMA/9?A GD?:5(!„€. !zQ0 !8;€<I=BJLLooqy‹ ‚P!€/?TT- [H.#@‚¤¤—€‹s`YVI1EH€I GGA;9/ !„ € IB € B‡Y€!8D€GT>GZo}‹‹oGSÑÑuH,PQ0 Gƒ‹s„}lT;FP€T€GD9/!„€$€ "Z + e#ˆ‡Z € >GIT;$.BWoTloG€‚€Ci¶öö…E .QOGo„}s‹olT;FPPGG€;8.!‚…5CB€2 +M.bŽ’* $ .iWlooiWW 9 1~ööË—O  YZLj}…s‡roVI;FHKPGF<;8- 8#(?B.  4wŸW   +CZmdYTB€?hÚöîÓŽ 1csx„vpdC#%I>>;6/#  '3BB+ €'  $l¡e  1NeaXP5€€/Q¶ííÓŽ=.bv >^ls‹odK, 7;;84, € '5CB+  ‚! bœn5  $B 8N^bG!€ .Z½¿–R B V¡ FP`o‡i> 481.*  &4BB+ …‚#E|ªe5   X¿Ø8HPG!€€‚‚-2@:&e Ge;MTWo=)2 !.( ƒ,<=+€€€4ªe5  eHØ4PG€ƒ‚BP; e (eGP€T 2ö¶./"! ! ‚ ,54$€…"  $|¡g7 5 ,HG€‚‚:.¿ÝAD  €† JíõĆ\C €;GPLC* -/$! € "€…   ªn<€   -I5€† 'rÛãÈ•OF >HPK€ 9/ !  " €…#   £uC$   ';!€ …6DÃŽ¡¥„  ;GPTK   7/!!*:*+1)!€ €€„  u£vJ) !€?;,!„8d­nw|H ;GPTJ€ 5;8//!!  +;FA1"€ €…$  uR •vJ* !$;;154 €€€€€ =e3> ;GGPMIT€;1//-˜ 0=LA+'#€ €  ~€X* € '8;1$#  2*‚€ 66TYYQ80 8FG2CNO>?5410%! 0;G9*''%€ €‚ €! 1Bn€J  ..("!55'‚3 034/  0BGG(@KMAA<62..(&  € %?0)''&€ €‚‚" @ B~v<  ! !5=8' €ƒ3CHKD!>FDG;8/&€  „ *'€%$€ ‚‚ ‚!•n<5, !5AE<$ ‚†€ ;DGJQ9!;@=F;0#‚  ‚&€ ƒ€ ‚  ªneW*€!5AGG;$  ;;DGD;/!,;F;;$!  „  €•ª™ee.. € !5A€G<'!ˆƒ; >G!!,58!!  €€   ˆ   €.'-H™™WWSE&%%IND& 3@GGD954---4;GAGBA@;.)! $#04;@A?v'9D5EGGF>>A?=ƒ;5€!!…T‚ €‰  ‡€2ª.;!8'!4'! ;$55!8.€ ! ˆ‚ nL‰  @ €…. ‚‹^- 5:6'  +00+$ 5:.  €†€  $€€… , ‚,  T‰`,,."  $ !";0%!€€  € „€… €    €%-m–‰Y   $8# !€  ‚  €„Š„  €  2d™e ;! !!„ … K.‚€ƒ ‚‚)S‚ªªn$!    !!€ ‚ ‘  € ‚ €ƒ A|œlA$ €   €„€€‚ Š1    „€ IidQ#‚& ‚€ Š ! …  €€‚380  $$' „  €  ‰€   €€   €€    $ !€' € ƒ€ € ‚‚  €   !;$ €'   €€€      ‚"€€    ‚   €†€e ; /5 !N5''€€€     € ‰  €‡€( $4$D- :E? ‚   ‡ƒ   †€€/>)DB#&F 0C= †€  € „…   ƒ†€B@"M=!'J"9F†€€    „  ƒ††M7 T  ;6&#[7> ˆ  ˆƒ€€  ƒƒ‹L3 T  T;'6. T! €‡   ‰Š  ƒƒ‹#! G%Q; &Q;Y2;T€ƒ†.€€€  ‚Œ€ …Œ 3V5<88 %AQ&>&„† ^€€  …Œ4]'"= A-T(<(1„…9 €€    2[ C0 G%M(= >%Ž€‚  €— 2[ K?* >80 C(Ž€„  €„… ˜ 9L2[ K.. &N!€Z ;;Ž €‚  „ ›&L= @4e/;4€[T.Ž €€ƒ ‚ …‹‹Z9€N- 5'M4e?F €.K!6I‡ƒ+€€ ƒ  €  Ž ‹e2 5 "G GGI8D3)5+A.‡ƒ !: €  €  <‡‘e(+5 >G 4T(+9G(;;ˆƒe/ƒ  ‚ €e"‡ ‘e(4M;; -HRG!T6>T;$6Œ„ee7‚ƒ ' ƒŠ :-‘ 8TTI>.e5 ;T22€;.!‹€ [I#‚ 'ƒ‘ “';T>'€ Y<% ;$I‚TQ;;'ˆ„!% ƒ  A1$ ‘“  € KD /' a,3:"157%…€…& … ') ³ ON; J(. H>$"„€† €ƒ€ ˜— KDBƒ #+2#D9'0„€‡‚ƒ˜ —Y<%T„4?€ :O;ˆ„ ‚…²Z$ ;„Y<4€3W.T‡‚‚ ‚€€»Z:$„ &€ ^>ƒ€‚ƒ„¨  e 0 €e'ƒ„‚ƒ …Ÿ  e 4‚€#:ƒ„€€ , €Ž„Ÿ  e 1 "‡$ ‡„€ K Ž€‹™e $€;'‡ ˆ† ˜  •žƒ. T;$€€ƒ   €€Œˆƒ %I>$Ž€‚   €€ª€†   „ª€‚Š€€ …€ ÿÿ…ÿŠªÔð€_‚ñÚ¨d€ØBôóÓs*U°òòÜÖ¬‹Iƒ€‚…€œ4Ìôç‹C€9‚¹¹Äãʯs+ €  €€†Œ œXööÆŽZƒXÈØÓ˜TQ(€€  €‚ˆ €öÑ›‰‡  €• €öí­\ ˜‚„…„ ¡ÀöõíÒaŒ‚ˆ €‘€ £ ]¹ööì©K…€‚„‚  €‘¤\Àööé˜T+-…€‰ƒ‚”€ŒU” Øööéέm ‚€ € ƒƒ’Ž /–öôã­f‚€‚‡‚ š2ö庙Qƒ€€…°€€ 2=8/&ƒ€  €‚Š€˜ 77€   „ƒ€ ‚€…€‹!€  +P…b € €‚  †„€ €!6ˆ=BGG ‹,]­ñÏBƒ‚‚4„= 9€Ž€4Ž=Q€e€=3‰ dööí»:„‚9##Š=•€€9ˆ=`ee`=@[==4Q[= ‡v€ö œ3‚4Ž=,ƒƒ†=4‰=G`=9Q€e4=…ElÖöèA‚€ €!*=92/)"„‡€#!0…=#:L^d[4%5Oee4;L[[=5ƒ  ¿ööÈ6„‚.‹=LG==++84)„'4…=+;Q€eQ!,GeeQ5HeeQ@!ƒOçöóí¥€‚ €8ƒ9„=WN€=9<=9ˆ €0898€9:==9=Naee`#,Gee`/?aeeF$ƒ íñÜ­m €‚  ƒ‰=4=9‡€‚€#==9=Gee=,Gee€=G€e-ƒ «îñÚŸ”#„=9#Œ€ € „ €ƒ,GeeRQGe==#ƒ«îæ¬s‚€‚#*8dŒq‰Œ–Œ €=59"Œ4  99Ÿ˜ä¹ö#  ,H\a18URƒK„ŸŸ…Q9:#'†íöö!ƒfC1€ †B)?Ah?BŽç #W íõæ¿|D‹×ööá!99fÙ…È¢ô"#9T\9a†„`¿éëѶ7SG*·ööÎ}ƒ€ƒf[E†,!0AU DŽöEP)'B­íöä­R#{ööÑ9=çã € #9K@ŸÒ‰)„B ÈÚööuDU])öö䃀„f[E€…"7CU-#VŒã8ºÂQ #dÃãíÑŠ2 {€ö¶.+|ã­u kÑ#APA"=ãfƒ .\\wööÑbHMp€öä­€„p[E€‚A"7CUX¦ÍŒi[K/  8k|²x2Bšöö¶/ !!U™  #AP-“¨0‚.V{m¤ÇööòPYÂ6Ûöä­…‹„o)€ +". =öñµ0  !€AZbV  -PT* 2ã. ƒ"Q£{rÁáñöíjC=k}Øôଂ†¢ëæ­of €+"7CU£æÞ2:`sƒ}pZ0+A%AöãÏ8  €  -AP*Aåƒ,c´x‚®ÇçôÌzN7b´ØíÞÌ‚‡¢ë€ö­f.€ @"7CUb»Þ2(:`Ÿ«­¡w=F­2_öã´/   -AP*\ö. ƒRãÀ¤©¿ôã­†W-EãØíÖ­‰¢ë‚öÒ™Q €&"7CU(ˆÖ=Xiq­­¶·™m.E•öB iã­¡, €  -AP* .ö\ƒ>­ö庺ãã­sV<7ÇÈ©Ÿ€Š'QöòêÚ˜Q€@"7AC(R•Ö€•¡›}oŽÒæÞ©™Oµ…4pÕ´­x   -AC5¶—%ƒ >öô¿¯´´¡aDHˆHع±žq‹S 'Dœ¶îööòÑ…D&9AAD‰ÈŠ£¦šrUŠàñ泟x¶Æl$ƒÖ­¦E  (7>A1mÁSƒ²îÚÑÉ—zH+0r ä´©Š5Œ6 2]´ËÞöö¿ƒG /LD2:ƒˆŒg9€ €.?\vbyyq?  2FUE%  $ i€‰†Z”€ +ÉööÒ„(6FLUA7% €B :F]kk; -C9r‹ž—¦µ°²»‘k[C#AKR@+5  @5„~kc+‚ .€Ôöö¿F%7?PPdR>‚2)22AAUCKPCUAA7"€ KUk~kUC„ŸöòÑ0A->AKSAUCPP>-#“ -ööï I 2A2?96>)€ KTcXA „d½öòÇ5 *=:4A20+!“ € € •ööLJ ƒ    € AUdR.€€K½öñÈ^  €    •€   Lööä¹ ‹€#-U`X. '*)! ,,_Êöö¹]€™€  !àñöÚ‹$$GXf>/CG@./?TT- Œòõö½€€€˜€  €BÉöã\‰‚%1AKkA.ASvvP-!SÑÑuH, 9ÑíöàŸƒ€€€;€¥í­ /ŠöC#Áöí­=†€‚"7FU \k~qD\Ci¶öö…E; A¹öñã‚…‚'4KycK*=±ni¾õíX; #Ž˜·ÅÏ£.(9HK2$)Dk }m^1~ööË—k~Ï€Ðöô˜‹€Œ( 2, 0G?4öö™]0Nn+47Ca¢º€3-#’öö¿y-  >QO6²ñ@ -@M@#b5@vvYF#€Q¶ííÓª‡öK{öö©9:{¼«…Žs‹€’‚0„èöö¾`" ,?7!ƒ "YÇÚ9-JT@$ ;VSl\Z½¿–Rök{öö¦#ÚËhK\I‰…‚#E…€ö7 LZEŸW¿ØÚ}--ˆ€€=€ö%¿W.=TöW¿ØØ}->7QdYB „'rÛãÒÍàF²áË©QÖ#-8{²0… …;K  æôöÖ   XM% "6DU c™x1 ƒ DÃŽ±ÐçÉžº¤™¢ H|Ça…€„  uæööß= )6>CUk ‚ "-7UU 1AA0 ƒ 8d­íÀ|H­­—{kUU€ ‡  †  B0 Øööí­= ‰ 2AUU _k\€-Pfq€ö¤>­Ÿˆk@€ kXF?;.‡T ƒ  ÁöõíŸC  ˆACSN&/€¦ÎÝÝáäæéöJJ*+­qa2 †   ‚ € ^¹ööÑ5 ˆ 7HR@&AXu’œ¥®´¹¦4`—`8‚Œ €€Œ‚' ^ÀööÆ€['„‚"=LRM"1>MU^K Yvv@ …Ž‚ \i8‚Ø€öæ©KKEƒ2=HSShK ƒ 5{jrqRK€ ‚Ž€ \i8‚ ö퀭 u=8==„"7AAUhZZ…k€UP9• \G€؃öíÖ«Ÿ€À­†-A0=, ‚‚  ‚‹   ƒ"ƒ¶„ö¾¥¬ö­=ˆ –‚   ‚Š    X¾¾À€ÁÉtGZö¿Y"†…Žƒƒ‚‚ƒŠ .ƒ.K ƒ€#BB!=öö­Y†ƒ ‚ … …‚‰  )€Šuö­Y¢…‚‰  ˆ 2öö¿u.„m  ’.= ‡‚ nL‰   €„  •öèºx.‚{LR €‚….2/ …€  $„‰  ‚ €Tµæä»u DœkA7Z€… !!(€ „‰ €   €€,mÈîæ¶K¾º„¡-€†€ +‚  €„Š„  € †2d¶öö­K=€p€ ‰‚.„ ‰ 9ƒ€ƒˆ&S•€ö ¿u6 .Ia *  †€ .;Œ &#nD ƒ‚ €‡ J…èïæÊ6&)†€  €‚—ŽeeJ4‡ „…ZˆÆñÈ*7@N%††€” f¦Ÿl^8‡€€‚3\€™TqdZGˆ„  €” '‹T8)&‰‚ €€‚ K¨¯Šk0 ˆ„+90ƒ–so8€‹ƒ#(ƒ€€ ­ãÄ‚ma Š€€+9=6€˜Y0(”).%€‡€V¶öö~"€ ‡€€  *.# ’!\L €‹ =Ÿîö&€1° ƒ‚9Q Œ Œ†€ tÃé€<Ù0†€  ˆw1 W€ƒƒƒ  †€:˜ËÎT.¯k†€€&£˜?# aƒ„ /Œ††nØÇ‡ ØT‡+´åP'6Œ(#‚ 6#.#‹ƒŠ `Ô±a €öT#€€† EãöG! ŒQT6ކƒŠQÐöÙ Ç8Øš0€ƒ… Gö­> €3‹‚ ‹ )b`†‹ mÂØ€ ÖC}·¨……jö…9 €,L+‡†  € /\MA†Œ0›ç{@àD8šÆ1‡„0©í–;€..ƒ€†7% € 9Ys&š{öö  Û@lÅ Ž IØã­O+ > €#†€TE‚ GHm„* ”{öö €ö¤,8‘Ù  #N´å«P#L)‡€((‡ mŠšg* –«í¹{öö €ö&=Ù #N¶öŸÚ{€ ‡†  .. –­ä{ ¹öÙ ö&‚@ØŽ.Y¶öŸsM& €@e†‚ƒy`.88* •6íô{€½ïŽ# ö&tëØ‡,xöÚ‰\1 E<$!€  B[‚ºwö„2›aöö{`®41ö%¢²Œ‚ =Ðöö±W.¼.€  Žf.0=öÍj›=öö} Ç8ö€’\öö˃* ‚.” =2m«Ûº‚ööD Ø=–.€ö ÐS .¨R7ƒ Øö» ««ƒ€ˆ =ßöà‘.š`‚‹ ¨ƒ¨è»**ºº^,®¹«*…€ƒ u¼í¿9dkLƒ€€„ ³˜ä»„ öö{s{í˜vV„€„ 2qºÙM.>8 ‚€ƒ ´¨è»ƒ Ôò|¹ãì¼8„€… /vÙl ‚¼Øö»ƒmå}€«ìñ㉃S»Ÿ‚…²­íè­…Øö¹{öö‡‚ ?·. ‚€€¹ `íõX…oºê¯€Tö„€‚AH„¨öéA†Už¯€<—ö„„€ …Ÿ·ö†$‡O„€fÔì„„€ * €Ž„Ÿµö& ˆT€{êLJ„€ !S   Ž€‹— mö& {¹ˆ† /``T  •žƒöå? “€€ƒ /gŠŠ €€ŒˆƒÙÓ—‚Ž€‚ /gŠa€€ª€†69*€„ 2+C$ª€‚Š€€š€ D%ÿÿ…t8mk@ "--3888888888888888888888888888888888888888888888888888888888888888888888888888888888888883--" 9Ws†•¦µÂÉÎÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÎɵ¦•†sW9!Ax–²ÆÔâëõýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýõëâÔÆ²–xA!MŒÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎŒM3˜ÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓ˜3@¿÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷¿@š÷þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ÷šLÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓL!ŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠ!?ÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅ?9xÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿx9Y˜ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ˜Y{ºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿº{ÏÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏŸÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞŸ ¯ëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿë¯ ºóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóº&ÄùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÄ&1ÍþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÍ18ÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐ8:ÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐ:?ÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑ?IÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÔIIÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÔILÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕLMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMMÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖMDÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓDDÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÓDAÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒA<ÐþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÐ<4ÈùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÈ4*ÂõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõÂ*¸ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð¸¬çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ笡ÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞ¡“ÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑ“~½ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ½~e¤ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¤e9pàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàp9"QÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÄQ"3•éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé•3iËûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûËi @Ÿßûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûߟ@ S™ËéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéË™S&gЦſÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÅ¦Šg&*Yv »ÊØâêðõùþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþùõðêâØÊ» vY*:Vp€›ª¸ÂÊÒÚàåæççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççççæåàÚÒʸª›€pV:7Xtwy{}ƒŽ••˜››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››››˜••Žƒ}{ywtX7 &9MYclry~~yrlcYM9& uqm-0.6.2/sc2/src/res/darwin/uqm.r0000600000175000017500000000013110543202105015312 0ustar joeyjoeydata 'MBAR' (128) { $"0001 0080" /* ...€ */ }; uqm-0.6.2/sc2/src/res/starcon2.ico0000600000175000017500000000137610543202106015305 0ustar joeyjoey è( @€€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿ‡wwwwwwwwwwwwwwxpppÀpÀp@p ppwÀpDdÌÌpFLÏÿÀ@pDDLÌÏüpDD̯üÌpDBªªÿÌÀpD"jj¬Ì pDBffÌüÀpd"jlÏüÀÀpDBªÌÏ<ÀpDBÏÌÌ<p@DGÆÃìpwGÌÎÀp DDÌ<pwÀp p@ppppÀ ppÀpp‡wwwwwwwwwwwwwwxuqm-0.6.2/sc2/src/res/ur-quan-icon-24-hover-alpha.ico0000600000175000017500000001115610543202106020514 0ustar joeyjoeyè6È ˆ æ(0€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿDDDDDDDDDDDDDDDDDDDDDDDDDDDDD@DDDDDDD!@"""DDDDDB3¢D*¢DDDD#º¢@"ª DDD@;ª"¢‚"¢DD#º¢*ª(€*rDD""ªª¢ (sDD"*‚(Š(H³DD "£³ª¢„2DH@"#³ªª D@ D""Šª¢* D@¢("*ª*ªª¢DD*(ˆ"ª¢ªª²DD¨€@"*ªªª²DD* D""ªª«²DD@"ª@"ªª»¢DDD*¤€"*«º DDD@"w""»¢1DDDD;0"32#DDDD@3DDDDDDDDDDDDDDDDDDDDDDDDDDÿÿÿÿÿÿÿàÿü ?ø0ðàÀÀÀƒÀC˜Œ€ÀÀ€ÀÀà`ð@øüþ0ÿÿÿÿÿ(0Ü6Ý) àåê ìîéãÜÕÏËÇú­ªªª ¬«ª §$¡&œ– ‹uojh h fd`]'b'.e.3f39d:BfBLdKKnLJoLIfJHYGEOE=G>;A<8<96;7284/80,7-*6*'5(%5%#5#!5!3446 4 6 9 7 79%8:8P?[GdRnZs^}Y‡RŽR“Y™^Ÿd£f¨`®Zº&WÂ4TÏKLÝ`Dçv;ñŽ2ú˜0ýš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þ›/ÿš/þ›/ÿ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›0þ›0ý›1ý›3ü›4ûœ7ù;÷@ôžEñ Lí¡Té¤^ä¦jÞªyÖ­ŠÎ±™Ç´¨¾¶±¹¹º¸¼¼¼»½¾¾¾¾¿¿¿ÀÀÀÁÁÁÂÂÂÃÃÃÄÄÄÅÅÅÆÆÆÇÇÇÈÈÈÉÉÉÊÊÊËËËÌÌÌÍÍÍÎÎÎÏÏÏÐÐÐÑÑÑÒÒÒÓÓÓÔÔÔÕÕÕÖÖÖ×××ØØØÙÙÙÚÚÚÛÛÛÜÜÜÝÝÝÞÞÞßßßàààØââÐåäÈçæÁéè¨çé“ãê~ãìeãîUâîGßë;Ûæ1×à)ÓÜ%ÒÙ ÍÙÉØÀÜÈÑÉÊ!ÌÂ$˼$ͺ%θ&Ï·)Ó¸,Ö¹/Ú¹ÿÿÿ7á¾@æÈDEE@64KK$>""44SV;" 53Xñ7?' 67Zí '5413 94Sñ (-2?E¹4JW *923E/½XI ///#22<-ñW3BB"VñU 22KS328:UñU ;;CC=<@*/ B: @541   1-2?  ÿE /2;5 ÿ;" B4  ûÿC  B? ûé@" 2?"ýéI>"ºæKDõêUJ<3UñQDOOPSK7WR=EEEEEDI5ÿÿÿÿÿÿÿàÿü ?ø0ðàÀÀÀƒÀC˜Œ€ÀÀ€ÀÀà`ð@øüþ0ÿÿÿÿÿ(0   Nkf9  XoX ù9þGô"Ð Ÿm+ ’Zÿ 7ZÿVôoÇ^ÿ—ÿ¸ÿ­ÿ\ø’/‘›ýtÏÿ áQÿŽý`4´Uÿ‘ÿÎÿÜÿwû˜0 ‰R¹ÿ¹ëÿá6ÿ úÿ ˆ ÿ¦:;ËYÿ ‰ ÿÆÿÝÿ}û›4¡QÎÿäßÿØ&ÿÎÿ¸ÿ³ÿ(Ù(ÿ>È•;8;å^U^ÿ:H:ÿ€ÿ¼ÿÞÿ•ÿ³@‘™þ°Üÿ×'ÿÌÿ¯ÿ¤ÿæÿþÿêÿ#‚#þn^nÿTQTÿò:ú€ÿºÿ*á*ÿ“£ÿ"¶67É_Äÿ³-ÿ»ÿ³ÿ¤ÿ Í ÿËÿÚÿøÿ4ó4ÿ6–6ÿ%%èm†;ø y ÿzŽjÿ¦½Ýÿ;¸ÿ •!ÁŠ)ÿ¤ÿ“ÿÿÎÿE²Gÿ&¡Tÿ¬>ÿ6¡^ÿRÆOÿÿÿlîq'{)- õNb€ÿ”ýÿ,®úp ˜5ß+ÚVú™ÿ·ÿÅÿ•§ÿ ÿÿ•—ÿÐÿñÿüÿuíu0€tó›þ‹z©M7"µ’ÿ¤ÿ¹ÿ™¤ÿ•ÿÿ •žÿÁÿÑÿðÿþÿ}븸åçe ½~ÿ'¼HF'Õÿ1“1ÿ!›Bÿ²+ÿ!­?ÿJªHÿÈÿÐÿìÿøÿ®ÿŸÿÀÿ¼ÿAÛD ´Êÿ¹ÿ)Ï–;/;ëGXGÿˆÿ¢ÿ°ÿÊÿ Ê ÿÆÿ½ÿÉÿçÿýÿúÿü ÿÿCÿÿjp†ÿâÿ²ÿGTGÿhchÿF>Fÿ é}ø£ÿ¬ÿÅÿÕÿÈÿ½ÿÇÿÉÿÈÿÔ;ÿCÿÄÿ’ÿp,;æªÿÜÿH˜HÿVOVÿâbš}þ¤ÿ§ÿÆÿÛÿÊÿÄÿÁÿÄÿÐ9ÿBüÂÿ‰ÿs ¶hÿªÿÕÿ­ÿ6Þ]*—vþ¡ÿ¥ÿÊÿÎÿÇÿÎÿÇÿ/äŽÿFúÐÿ‚ÿwK'åmÿ¦ÿÛÿÃÿ=Û`4Ê~ÿŸÿÅÿÕÿÒÿÔÿ,â‚ÿVüþÿ"ædÿˆÿz7ÎaÿšÿÓÿ=Ñ=ÿc`Zê Çgÿ¢ÿ¸ÿÄÿÂÿ6èšÿSûöÿÛCÿ©"ÿNFÿk.Ã^ÿŒÿ¤®”ÿš´çÿpñ ò†ÿ ÿ›?ÿ˜DÿÖÿ=îûÿÐQÿ¹ÿn£ÿ8¯*¾DE;ÿOzÿ Œÿÿ ú'ï“ÿ!ÿ–ƒÿ—€ÿ¤ÿ¯Gÿ› ÿ@™ÿD±&¸ 6±ÿ(—ô qF¿@ÿBú=ø:ö;÷3 ÿ'¼!› lUQI<@<ÿàþüøðàÀ€€€€€€€Ààðøüþÿ?ÿuqm-0.6.2/sc2/src/res/ur-quan-icon-24-hover.ico0000600000175000017500000000432610543202106017432 0ustar joeyjoeyè&È(0€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ!"""3¢*¢#º¢"ª ;ª"¢‚"¢#º¢*ª(€*r""ªª¢ (s"*‚(Š(³ "£³ª¢€2"#³ªª ""Šª¢* ¢("*ª*ªª¢*(ˆ"ª¢ªª²¨€"*ªªª²* ""ªª«²"ª"ªª»¢* €"*«º "w""»¢1;0"32#3ÿÿÿÿÿÿÿàÿü ?ø0ðàÀÀÀƒÀC˜Œ€ÀÀ€ÀÀà`ð@øüþ0ÿÿÿÿÿ(0 Û1Ü6Ý) àåê ìîéãÜÕÏËÇú­ªªª ¬«ª §$¡&œ– ‹uojh h fd`]'b'.e.3f39d:BfBLdKKnLJoLIfJHYGEOE=G>;A<8<96;7284/80,7-*6*'5(%5%#5#!5!3446 4 6 9 7 79%8:8P?[GdRnZs^}Y‡RŽR“Y™^Ÿd£f¨`®Zº&WÂ4TÏKLÝ`Dçv;ñŽ2ú˜0ýš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þ›/ÿš/þ›/ÿ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›/þ›0þ›0ý›1ý›3ü›4ûœ7ù;÷@ôžEñ Lí¡Té¤^ä¦jÞªyÖ­ŠÎ±™Ç´¨¾¶±¹¹º¸¼¼¼»½¾¾¾¾¿¿¿ÀÀÀÁÁÁÂÂÂÃÃÃÄÄÄÅÅÅÆÆÆÇÇÇÈÈÈÉÉÉÊÊÊËËËÌÌÌÍÍÍÎÎÎÏÏÏÐÐÐÑÑÑÒÒÒÓÓÓÔÔÔÕÕÕÖÖÖ×××ØØØÙÙÙÚÚÚÛÛÛÜÜÜÝÝÝÞÞÞßßßàààØââÐåäÈçæÁéè¨çé“ãê~ãìeãîUâîGßë;Ûæ1×à)ÓÜ%ÒÙ ÍÙÉØÀÜÈÑÉÊ!ÌÂ$˼$ͺ%θ&Ï·)Ó¸,Ö¹/Ú¹ÿÿÿ7á¾@æÈþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþDEE@6þþþþþþþþþþþþþþ4KK$þ>""4þþþþþþþþþþþ4SVþþ;" 5þþþþþþþþþ3Xñ7þþ?' 6þþþþþþþ7Zí '5413 9þþþþþ4Sñ (-2?E¹4þþþþJW *923E/½XþþþþI ///#2þ2<-ñWþþþþ3BB"VñU 2þ2KS3þþþ28þþ:UñU ;;CCþþþþ=<þþ@*/ Bþþþ: @541  þþþþ 1-2?  ÿþþþþE /2;þ5 ÿþþþþ;" Bþþ4  ûÿþþþþþC  Bþþ? ûéþþþþþþ@" þ2?"ýéIþþþþþþþ>"ºæKDõêUJþþþþþþþþ<3UñQDOOPSKþþþþþþþþþþ7WRþþ=EEEEEDIþþþþþþþþþþþþ5þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿàÿÿü ?ÿø0ÿðÿàÿÀÿÀÿÀƒÿÀCÿ˜ÿŒÿ€ÿÀÿÀ€ÿÀÀÿà`ÿð@ÿøÿüÿþ0ÿÿÿÿÿÿÿÿuqm-0.6.2/sc2/src/res/ur-quan2.ico0000600000175000017500000000427610543202106015226 0ustar joeyjoey ¨( @€€€€€€€€€€ÀÀÀÀÜÀðʦ """)))UUUMMMBBB999€|ÿPPÿ“ÖÿìÌÆÖïÖçç©­3f™Ì3333f3™3Ì3ÿff3fff™fÌfÿ™™3™f™™™Ì™ÿÌÌ3ÌfÌ™ÌÌÌÿÿfÿ™ÿÌ3333f3™3Ì3ÿ3333333f33™33Ì33ÿ3f3f33ff3f™3fÌ3fÿ3™3™33™f3™™3™Ì3™ÿ3Ì3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿff3fff™fÌfÿf3f33f3ff3™f3Ìf3ÿffff3fffff™ffÌf™f™3f™ff™™f™Ìf™ÿfÌfÌ3fÌ™fÌÌfÌÿfÿfÿ3fÿ™fÿÌÌÿÿÌ™™™3™™™™Ì™™33™f™3Ì™ÿ™f™f3™3f™f™™fÌ™3ÿ™™3™™f™™™™™Ì™™ÿ™Ì™Ì3fÌf™Ì™™ÌÌ™Ìÿ™ÿ™ÿ3™Ìf™ÿ™™ÿÌ™ÿÿÌ™3ÌfÌ™ÌÌ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌfÌf3™ffÌf™ÌfÌ™fÿ̙̙3Ì™fÌ™™Ì™ÌÌ™ÿÌÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÿÌÿ3™ÿfÌÿ™ÌÿÌÌÿÿÌ3ÿfÿ™Ì3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿfÿf3Ìffÿf™ÿfÌÌfÿÿ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÿ3Ìÿfÿÿ™ÿÿÌffÿfÿffÿÿÿffÿfÿÿÿf!¥___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøðûÿ¤  €€€ÿÿÿÿÿÿÿÿÿÿÿÿ * """"""""", 3"""-"""""* "å """""",8,3ä3"""-"""" å"  """",,û833ää3"""3""* "  ""&ûû33úää33""""33"""""" """",833úää33""""333""""" """,-33úä3333""""33-""""" """3-333333ú3ú-"""f33-"""" ""333-33333úúf33-""" """""-333ì333úúìì33-""" """"""-3330333úúìì""33-"" -"""""---330,30ìú3"""33-"" 3-""""---3,8233úú-""""3÷" 3-"""""--3022,333úú""""ìï 33-"""f--330333úú-""""ì8, 33-"ff---33ìì333úú""""&,,&" 333ìì----3ú÷333úú-""""&""" 333ì÷""---3333333úú"""""""" "33-""""---3333333ú3""""""" "33-""""---33ú3333úú3---""" ""33-""""---3ú3333333333-""" ""33-""""---33ú3333333333""" """33-""""---3ú33333333å3""" """33÷""""---3ú3333333úå3""" """"ìï"""--3ú3333333åú3""" """"ìì,&"""--33ú33333ååú3""" """"",8&""--333333ååååú3""" """""&&&""""-----33åååååúä3""" """""""""""----3-ååååúúú3"""" """""""""""-000077åúúúú """" """""""""""""-333úú2,"""""" """""""""""""""f-333 ,""""""""uqm-0.6.2/sc2/src/res/ur-quan1.ico0000600000175000017500000000427610543202106015225 0ustar joeyjoey ¨( @€€€€€€€€€€ÀÀÀÀÜÀðʦ """)))UUUMMMBBB999€|ÿPPÿ“ÖÿìÌÆÖïÖçç©­3f™Ì3333f3™3Ì3ÿff3fff™fÌfÿ™™3™f™™™Ì™ÿÌÌ3ÌfÌ™ÌÌÌÿÿfÿ™ÿÌ3333f3™3Ì3ÿ3333333f33™33Ì33ÿ3f3f33ff3f™3fÌ3fÿ3™3™33™f3™™3™Ì3™ÿ3Ì3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿff3fff™fÌfÿf3f33f3ff3™f3Ìf3ÿffff3fffff™ffÌf™f™3f™ff™™f™Ìf™ÿfÌfÌ3fÌ™fÌÌfÌÿfÿfÿ3fÿ™fÿÌÌÿÿÌ™™™3™™™™Ì™™33™f™3Ì™ÿ™f™f3™3f™f™™fÌ™3ÿ™™3™™f™™™™™Ì™™ÿ™Ì™Ì3fÌf™Ì™™ÌÌ™Ìÿ™ÿ™ÿ3™Ìf™ÿ™™ÿÌ™ÿÿÌ™3ÌfÌ™ÌÌ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌfÌf3™ffÌf™ÌfÌ™fÿ̙̙3Ì™fÌ™™Ì™ÌÌ™ÿÌÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÿÌÿ3™ÿfÌÿ™ÌÿÌÌÿÿÌ3ÿfÿ™Ì3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿfÿf3Ìffÿf™ÿfÌÌfÿÿ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÿ3Ìÿfÿÿ™ÿÿÌffÿfÿffÿÿÿffÿfÿÿÿf!¥___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøðûÿ¤  €€€ÿÿÿÿÿÿÿÿÿÿÿÿ #ig  ‡ ì   `fŒ g Œ a aÐ ` aŒf #aŒ ‚"Œ® " Ñ` "#  a (Ñ"a " `‡ " ` Œ"a`Œ" g a ‡   ‚" ‡Œg""f" Œ `  """ É""f ""# ` g` "" Ð "# " % "Ý""‡ ""   i#ma"("("" "" `ØÊ‡‡"("aaf"""" $" Ñ` """a`Œ‚`ƒ""" %##  ׇ" g""af f÷aƒaa" "&## "ç f``a `` ìÌ(g `" "## `f‡ g```ƒ ö‚Ø(m(" #$%#× "((a a`ì"‚--(" %i®Œ "`aa".f ‚‚3fag"""" Ð a`` g3(ŒŒl4"a `"" ìÊaf‡‚aìg3444"` ‚`ag(" ׌` "a ®`‡` Ì-3w4a  `‡ƒgÌ""Œ "`Œg f"Ì-(a`lf‡ ŒÝaÌ"É """` "쌂4` l ï`g‚3Ê " "f` aˆ‚444Œ34```ˆ‚"""Ñ"((Œ.ú|w444443-gg-4ä4ä4#Ê-.-344ääääää||ú4434wää|ö—Àž4#Ê(343ú|ääw"""(-wäääää|ä.#"#"""""f".4w(-("(()""#$""##mÊf"(-"(-444444-(###$####gÊ""" ""(44(("((""".4""##uqm-0.6.2/sc2/src/res/Makeinfo0000600000175000017500000000012510543202106014521 0ustar joeyjoeycase "$HOST_SYSTEM" in MINGW32*) uqm_EXTRA_OFILES="UrQuanMasters.rc.o" ;; esac uqm-0.6.2/sc2/src/res/UrQuanMasters.rc0000600000175000017500000000433110543202106016150 0ustar joeyjoey///////////////////////////////////////////////////////////////////////////// // UrQuanMasters.rc // // Resource script for Win32 builds // #include "../uqmversion.h" ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #ifdef _WIN32 LANGUAGE 0x09, 0x01 // LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Version // 1 VERSIONINFO FILEVERSION UQM_MAJOR_VERSION,UQM_MINOR_VERSION,UQM_PATCH_VERSION,0 PRODUCTVERSION UQM_MAJOR_VERSION,UQM_MINOR_VERSION,UQM_PATCH_VERSION,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x1L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "Comments", "See http://sc2.sourceforge.net\0" VALUE "CompanyName", "sc2.sourceforge.net\0" VALUE "FileDescription", "The Ur-Quan Masters main executable\0" VALUE "FileVersion", UQM_STRING_VERSION "\0" VALUE "InternalName", "uqm\0" VALUE "LegalCopyright", "(C) 1992-1993, 2002-2005 by respective authors\0" #ifdef _DEBUG VALUE "OriginalFilename", "uqmdebug.exe\0" #else VALUE "OriginalFilename", "uqm.exe\0" #endif VALUE "ProductName", "The Ur-Quan Masters\0" VALUE "ProductVersion", UQM_STRING_VERSION "\0" VALUE "SpecialBuild", "Alpha\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. SDL_app ICON PRELOAD DISCARDABLE "ur-quan-icon-alpha.ico" 102 ICON DISCARDABLE "ur-quan-icon-std.ico" 103 ICON DISCARDABLE "ur-quan1.ico" 104 ICON DISCARDABLE "sis1.ico" 105 ICON DISCARDABLE "ur-quan2.ico" 106 ICON DISCARDABLE "kohr-ah1.ico" 107 ICON DISCARDABLE "starcon2.ico" uqm-0.6.2/sc2/src/res/kohr-ah1.ico0000600000175000017500000000427610543202106015166 0ustar joeyjoey ¨( @€€€€€€€€€€ÀÀÀÀÜÀðʦ """)))UUUMMMBBB999€|ÿPPÿ“ÖÿìÌÆÖïÖçç©­3f™Ì3333f3™3Ì3ÿff3fff™fÌfÿ™™3™f™™™Ì™ÿÌÌ3ÌfÌ™ÌÌÌÿÿfÿ™ÿÌ3333f3™3Ì3ÿ3333333f33™33Ì33ÿ3f3f33ff3f™3fÌ3fÿ3™3™33™f3™™3™Ì3™ÿ3Ì3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿff3fff™fÌfÿf3f33f3ff3™f3Ìf3ÿffff3fffff™ffÌf™f™3f™ff™™f™Ìf™ÿfÌfÌ3fÌ™fÌÌfÌÿfÿfÿ3fÿ™fÿÌÌÿÿÌ™™™3™™™™Ì™™33™f™3Ì™ÿ™f™f3™3f™f™™fÌ™3ÿ™™3™™f™™™™™Ì™™ÿ™Ì™Ì3fÌf™Ì™™ÌÌ™Ìÿ™ÿ™ÿ3™Ìf™ÿ™™ÿÌ™ÿÿÌ™3ÌfÌ™ÌÌ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌfÌf3™ffÌf™ÌfÌ™fÿ̙̙3Ì™fÌ™™Ì™ÌÌ™ÿÌÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÿÌÿ3™ÿfÌÿ™ÌÿÌÌÿÿÌ3ÿfÿ™Ì3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿfÿf3Ìffÿf™ÿfÌÌfÿÿ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÿ3Ìÿfÿÿ™ÿÿÌffÿfÿffÿÿÿffÿfÿÿÿf!¥___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøðûÿ¤  €€€ÿÿÿÿÿÿÿÿÿÿÿÿ ’’ ø  ÷ë êëìêCë÷ êëìð êøð êì÷ CøømêêCë ìC CøøC’ C C’ CC’ ð CCCø’êC÷÷÷ð Cøð C   ÷ C êm ’÷ C møø ÷ C mm¼mmC÷ ÷øm ê Cm÷  mm  êø  Cêmm  êêø   Gê m CêC êmm ’  C  CC C Cmêê    C êC mê  C êCC CC C ë Cø   CC C êøê C CCC ê CCC CCC CC uqm-0.6.2/sc2/src/res/ur-quan-icon-std.ico0000600000175000017500000002362610543202106016662 0ustar joeyjoey(fhŽ èö ¨Þ 00h†00¨î( À€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ "":(‚* ¢¢"¢:"ª¢'"*3¢ˆ‚"3ª"(""*ª* "‚"ªªª *(‚*ª£ "¢‚*ª» *€"#² 0#3#"" ÿÿþ?ðàÀ€€€€€€Ààðùÿÿ( @›/ÿ.b+9g;M;)G/.I3/I/3C<!<d‰3tÞ˜Y˜¼{™(Gm D ¡=Î5]_g'*)}² ¾.ä–=ò²·;D1 K ¬Æ^```.C.ˆÂ×Ò4èœ6óž f 0C0´'Ä'=Q=JJJAQA®ÐÊÁÄ.ë†e" € ¿-H-WAW&I&‹¸ÊÆÅßåùWf!y1S1"H""˜"¥,¸*&º'ËðÒ¿É$N%>C>UUU1C1‘·Ÿ´•ÏÅú½6A6--2 .ENMh{ Ã¢x§ä °HPH]]]65A RÊ(6f==Oy—̶¶Øø7Ê7;A<?>?I™‹·¬'2r6vÆÌß(¾Ê†<><ZEZ$J$«Õ.e*E~· ò&ƒcbcLMLV ³ V#&W Vs*f)?@?X¨±#J#4=4?3K3ÿÿÿš›œ’“”•–—˜™‰Š‹ŒŽA‘}~€‚ƒ„…†‡ˆopqrstuvwxyz{|abcdefghijklmnTUVWXYZ[\]^_`GH"IJKLMNOPQRS9:;<=>?@ABCDEF+,-./012345678 !"#$%&'()* ÿÿÿÿþ?ÿÿðÿÿàÿÿÀÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿÀÿÿàÿÿðÿÿùÿÿÿÿÿÿ( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ" """ “ "ª €›* "*¢ ºª 0"ª";:ª" ˆ‚*¢ ³ª"*¢ˆ"ª¢›ª¢*ªª¨‚"‡’"¢ªªª*(ˆ2""¨2£Š ‹"""ª33ªª(™"*;³ªª¢€""33ªªª "(‚£Šªª¢""(* ""ª*ªªªªª *¢(""*ª"ªªª« ª(ˆ""*ª"ªª; "*¨€""ªª¢ª; "ª€€""*ªªª; "*¢"""*ªª«» "ª""*ªª»º "*¢ "*ª«»¢ "¨x""";º£ˆ‰"3;»"90ƒ¹"332)˜ """ ÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿ‚ÿÿÿü€øÀ?ø€ðàà ààüÎÇÃÀÀÀàà ðøüþÿÿƒÿçÿÿÿÿÿÿÿÿÿÿ( @€ ª\ ©a®Z±O±@ ·3À)ËÔ ãêñôñìåáÞØÔÐÊÇÆÃ¾»·²®¨¢ž›˜‘ŠƒxmbXNJA 9 5 /'!4>=/%+$-,&0/+422779=;C>@EACHCGMHNTOU\YZ\`^ZigUwK¥„CÄŽ;ܘ2÷š/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þ›/ÿš/þš/þš/þš/þš/þš/þš/þ›/ÿš/þ›/ÿ‘6þ€BþpMýbVýTdòHrë2±¶  .=ÙÙÙ0@&!+ÙÙÙÙÙÙÙÙÙÙÙ2°¶$%9Ù9?A>'+ÙÙÙÙÙÙÙÙÙ2©¶# $0?C?:/&;ÙÙÙÙÙÙÙ0¬µ$ BB<56-&!ÈÕ::ÙÙÙÙÙ3­#  :5ÙÙ8*&?ÊǪ2ÙÙÙÙÙ3 #ÉÈ /ÙÙÙ66AD²«3ÙÙÙÙÙ-(*))$±± ,>ÙÙ:2ª¬5ÙÙÙÙÙÙÙÙÙ6)"²³° +>ÙÙ921ÙÙÙÙÙÙ/8ÙÙÙ6$±± *050.0ÙÙÙÙÙÙ)%0ÙÙÙ8&@AÉ !#,?ÙÙÙÙ'#5ÙÙ7;#! #5ÙÙÙÙ(&05ÙÙ>& ¿!0ÙÙÙÙÙ9,% +;ÙÙ<+" ¾Â¾!0ÙÙÙÙÙÙ7*&"*9ÙÙ/'!¿ÃÁ /ÙÙÙÙÙÙÙ/*&"<:Ù/("¿ÃÁ#/ÙÙÙÙÙÙÙÙ6+' È×C8.' ÂÀ¯2;ÙÙÙÙÙÙÙÙÙ<.'BÊǦ1,# ±±³¹»¬ÙÙÙÙÙÙÙÙÙÙÙÙ=8@¢µª4-! ­¬>ÙÙÙÙÙÙÙÙÙÙÙÙÙ:7§ª8ÙÙ/*)))))*)18ÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙ24ÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿ‚ÿÿÿü€øÀ?ø€ðàà ààüÎÇÃÀÀÀàà ðøüþÿÿƒÿçÿÿÿÿÿÿÿÿÿÿ(0`€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ€" ""¢" "*ª" ™8 ""*ª"3ª ""ª¢ ;:¨ ""*ª"›³ªª ‚"ª¢ »:ªª  ˆ"*ª"›³ªª¢(¢ˆˆ‚"*¢ ;:ª¢"ªª ˆ‚"*ª ³ªª"*ªª¢ˆˆ€""*‡€€›2ª¢"ªªªª¨ˆ"*wx“"*"*ªªªªª€"(‡y2"""ªƒªª¨Š ˆƒ¹"""*ª822ˆªªˆ;9""""ª¢3“:ªª ™‘""*¢;³:ªªª"""¢›³2ªªª¢"""3“:ªªªª  ""(228ªªªª¢""" ""ˆ"ª(Šªªªª¢ªª"¢ €""ªª:ªªªªªªª¢ª" ˆ€"""ªª¢*ªªªª£:*¢ ˆˆ"""*ª¢"ªªªª;²*ª"ˆˆ€"""ªª¢*ª*ª;:"*£ˆˆ""*ªª"**ª;2 ""ªˆ€"""ªªªª*ª;2 "*¢ ""*ªªª*ª;2 ""ª""""ªªªª£»² ""*ª ""ªªªª;»2 ""ª¢ ""ªªª£»³¢ ""*ª"""ªªª;»:¢ ""ª§""ªª#»³ª! ""*wx"""";»:¢‘"(‡y"""#»³"#"ˆˆ¹""#3;³2"3ˆ‹¹"3333")9‘""""""!™ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿðÿÿÿøÿÿð ?ÿÿàÿÿÀÿÿ€€ÿÿÀÿþ€ÿüÿøððð€ðÀðàðððø?ÿ€üÇÀÃà?ÁðÀpÀÀààÀààðððøøüü|þ<ÿ ÿ€ÿÀ?ÿàÿðÿÿøÿÿüÿÿþÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(0`€ š/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš/þš.þš.þš.þš.þš.þš.þš.þš.þš.þš.þš.þš.þš.þœ5ùžAñ¡Jê¢Uâ¡fΜu½—€°“‡¥‰›ˆ”ˆ„Œ~ƒw|{r|upzsoysmyrj{qf|uM€~5…‡‹ŒŽŒ ‘’–­Â Ê¦Õ¬ã¯ìªòòŒò{ïkñ^îMê@å9Ù5Ê ,·1¨!9“4C{AIkOO^RQZSQVQRRORNLOJIOHEMDBKB@J?=F=9A98<84;3.;--4-+,.&)1"CZ jt ~ v o R ? / %  ")06<CGJMT[_chosuy}€ƒ‡Š ”™›š˜—˜¡¤¤¥¨¬®°±³µµ·»½¾ÃÅÆÇÇÉÌÎÒÓÔ×ÜÞßãçëíòøúúùóíâ!Ý#"Ô("Í,Ç0Á7½;½C½L¿R¿VÆWÏZÖ]Ú]Û_)Þc7âhDälOâvcÝŠ|Ù ×±ŸÕ½¤×Ȭ×ÑŸ×Ô‹ÛÞÿÿÿléîVõ÷Rö÷Nö÷Höõ=øó7øôùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùù‘|‘Œ’|stùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùx“”•˜›š‘“}ùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùù|‰Š‡–ùù›§¨Æ¨¨¡’–}ùùùùùùùùùùùùùùùùùùùùùùùùùùù}†„‚‚á±{ùù›Ÿ§¯ÁÁÒ¼¯œŽùùùùùùùùùùùùùùùùùùùùùùùùù{…‚ebãí¤{ùùùšŸ¥¯¾ÄÑǶŽùùùùùùùùùùùùùùùùùùùùùùù}ƒga_åÙÜ®}ùùùù˜Ÿ¥¯¼ÂÑɶ ùùùùùùùùùùùùùùùùùùùùù}€d_]èÑÛí¦}ùùùùù˜¥¯¼ÂÐ˼¡ùùùùùùùùùùùùùùùùùùùy€a]ÿçÐÏÐÙ®’{ùùùùù‘™p¤¨¼ÁÐ̼£ùùùùùùùùùùùùùùùùù}`]ÿèÂÇÏÔÍzàŽùùùxŒnms¢¨¶ÁÏ̼¤ùùùùùùùùùùùùùùù|€d]ÿéÁÆÂÉÄ¥«íÜ´ŽuxNOtss£¨¶ÀÏͼ¦ùùùùùùùùùùùùùx…e_ÿèÁÆÄɾ£´ÚÜÖÖ¶‘ŠOJmquz£¨¶ÁÏͼz|ùùùùùùùùùùù|†‚a]èÂįɼ¥±ÒÒÐÔÖÖ»OJnon}‘•¢¨µÀÐíóF}sùùùùùùùùù‰„e]弯ÆÇ¾¥­ÑÌÃÌÐÔÖÖÛnnnyŠù}”¡§µÞòôòQ‡ùùùùùùùùù‰gaåµ²¼É¿¥­ÑÝÇÃÆÌÐÖÜÜÍo}ùùùù”œ¢¥MHòød‚ùùùùùùùù‡gT¶µµµµ§¯ÑÚDâÈÆÇÍÛDïÖÚ’ùùùùùù“œnmMX]d‚‡ùùùùùùùù‹Ÿ¶­­±¯¦¨ÂÊÆâIåµU¼QOÛÖÖÊ”ùùùùùùŽtqR]_d†ùùùùùùùùù•¥Ÿ¤ ¢£¯¶ÃÆÇáYYaZUÉÑÔÖÖÏ•ùùùùùùibde~xùùùùùùùùùy“}ŽŽ‘˜¨¯²¶ÃƼ`]]_UÁËÏÓÖÖÑ—ùùùùùù…‚‚…uùùùùùùùùùùùùùùùx›¯­­²¶Âºa]]_WÀÄÊÏÓÖÖÓ™ùùùùùùˆˆ|ùùùùùùùùùy“Žùùùùù}Ÿ²­­²¿½X_a_UÄÆÃÊÏÓÖÖÔœŠ‘‘‘‘Žùùùùùùùùù›Ÿùùùùù}²­±¸ITáTáROÆÆÃÉÏÒÖÖÖŸ›¡¥¨¨ùùùùùùùùŽ¡¼£ùùùùù´¬OO¸ÀÉÆ¾GKÆÆÄÉÏÒÖÖÖÁ¼ÌÓÐÔ¾¤ùùùùùùùަɼ¦‘sùùùŠsz±v«µµÁÆÈßãÆÆÄÂÉÏÒÖÖÖÑÖÖÖÖÖ­•ùùùùùùù¥Ïϼ§‘xuŠsmozµ­®±µÀÇÆÇľ¾ÂÈÍÒÖÔÖÔÔÓêê”ùùùùùùù{Ÿ¿ÍϽ¨’ŠnMrtr­­­±µÀÇÃȾ¿¾ÃÈÍÌÍÌÍËéûþÀ—vùùùùùùùލÁÍϽ©mImps|‘—±±­±µ¿ÇÌÏÈþ¾ÂÁÂÀÂÄÁêúëÁ•tùùùùùùùŸ²ÀÌÑâHnony‹ùù–­±­±µ¾ÆÌÐÈÿÀ¾Á¿ÃÆÂèúìÀ˜xùùùùùùùx˜§²¿ÌÑrmmxŠùùùù–­±­±´¾ÆÌÐÉÄÆÆÆ¾ÃÆÂâú켘xùùùùùùùù‹œ¨±¿ËÑvu”ùùùùù•¯±­±µ½ÆÌËÄÆÆÂÀÄÆÂêú켘xùùùùùùùù‘— §±¾ÊÒ¹±—ùùùùùù“¯±®±´¼ÌÊÃÆÃÇÏÇÁëûúþµ›yùùùùùùùùù“œ §­¾ÉÒÁ±—ùùùùùù’¯±­±¾ÌÉÆÃÇÏÍÂêúúü꾘xùùùùùùùùùù“› ¦­¾ÇÑ´˜ùùùùù’›®­±¼ÌÌÍÌÏÍÂëûûú굜{ùùùùùùùùùùù’›Ÿ¦®¾ÇÑÆ´šùùùù‘š§®­¾ËÈÉÈÉÂêûúúéÁÄÀ˜xùùùùùùùùùùùù’šŸ¥¯¼ÆÑÛò}}ùù’™¯­±¶ÂÂÂÁ¿êúúüêÁÄ« yùùùùùùùùùùùùù™Ÿ¥¯¾ÃòôôkŽù‘­­­²¶µµ²êúúúëÃÁ¸egŽùùùùùùùùùùùùùùù˜Ÿ¥©PEôõdƒŠ•¢®­­«ª«ªãýÿýê¶¶ÀZfˆùùùùùùùùùùùùùùùùùŽ˜žsMME^d‚‘˜¨­­«WYYX\[Zæ½¶ª``}ùùùùùùùùùùùùùùùùùùùŽ{npQ\^dƒŠ•±­±åVUUUUUå¼¶©efˆùùùùùùùùùùùùùùùùùùùùù}{k`ab‚|ùx•¢ ¨¤¨¥¥¦¢¥¡¥Ÿ‚‡ùùùùùùùùùùùùùùùùùùùùùùù|hff‚|ùùùù’”“•“”””–“•“•ùùùùùùùùùùùùùùùùùùùùùùùùù|…†|ùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùvxùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿðÿÿÿÿÿøÿÿÿÿð ?ÿÿÿÿàÿÿÿÿÀÿÿÿÿ€€ÿÿÿÿÀÿÿÿþ€ÿÿÿüÿÿÿøÿÿðÿÿðÿÿð€ÿÿðÀÿÿðàÿÿððÿÿðø?ÿÿÿ€üÿÿÇÀÿÿÃà?ÿÿÁðÿÿÀpÿÿÀÿÿÀÿÿàÿÿàÀÿÿààÿÿððÿÿðøÿÿøüÿÿü|ÿÿþ<ÿÿÿ ÿÿÿ€ÿÿÿÀ?ÿÿÿàÿÿÿðÿÿÿÿøÿÿÿÿüÿÿÿÿþÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿuqm-0.6.2/sc2/src/port.h0000644000175000017500000002633710546776503013462 0ustar joeyjoey#ifndef _PORT_H #define _PORT_H #include "config.h" #ifdef __MINGW32__ // Microsoft Windows headers expect this to be set. The MSVC compiler sets // it, but MinGW doesn't. # if defined(_X86_) # define _M_IX86 # elif defined(_IA64_) # define _M_IA64 # elif defined(__amd64__) # define _M_AMD64 # elif defined(__m68k__) # define _68K_ # elif defined(__ppc__) # define _M_PPC # endif #endif // Compilation related #ifdef _MSC_VER # define inline __inline #else # define inline __inline__ # ifdef __MINGW32__ // For when including Microsoft Windows header files. # define _inline inline # endif #endif // Compilation warnings: // UQM uses a lot of functions that can be used unsafely, but it uses them // in a safe way. The warnings about these functions however may drown out // serious warnings, so we turn them off. #ifdef _MSC_VER # define _CRT_SECURE_NO_DEPRECATE #endif #ifdef _MSC_VER # include #else # include #endif #ifndef HAVE_STRICMP # define stricmp strcasecmp #else # define strcasecmp stricmp #endif #ifndef HAVE_STRUPR char *strupr (char *str); #endif #if !defined (_MSC_VER) && !defined (HAVE_READDIR_R) # include int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); #endif // Directories #ifdef WIN32 # include # define PATH_MAX _MAX_PATH # define NAME_MAX _MAX_FNAME // _MAX_DIR and FILENAME_MAX could also be candidates. // If anyone can tell me which one matches NAME_MAX, please // let me know. - SvdB #else # include /* PATH_MAX is per POSIX defined in , but: * "A definition of one of the values from Table 2.6 shall bea * omitted from on specific implementations where the * corresponding value is equal to or greater than the * stated minimum, but where the value can vary depending * on the file to which it is applied. The actual value supported * for a specific pathname shall be provided by the pathconf() * function." * _POSIX_NAME_MAX will provide a minimum (14). * This is relevant (at least) for Solaris. */ # ifndef NAME_MAX # define NAME_MAX _POSIX_NAME_MAX # endif #endif // Some types #ifdef _MSC_VER typedef int ssize_t; typedef unsigned short mode_t; #endif // Directories #include #ifdef _MSC_VER # define MKDIR(name, mode) ((void) mode, _mkdir(name)) #elif defined(__MINGW32__) # define MKDIR(name, mode) ((void) mode, mkdir(name)) #else # define MKDIR mkdir #endif #ifdef _MSC_VER # include # define chdir _chdir # define getcwd _getcwd # define access _access # define F_OK 0 # define W_OK 2 # define R_OK 4 # define open _open # define read _read //# define fstat _fstat # define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) # define S_IRWXU (S_IREAD | S_IWRITE | S_IEXEC) # define S_IRWXG 0 # define S_IRWXO 0 # define S_ISDIR(mode) (((mode) & _S_IFMT) == _S_IFDIR) # define S_ISREG(mode) (((mode) & _S_IFMT) == _S_IFREG) # define write _write //# define stat _stat # define unlink _unlink #elif defined (__MINGW32__) # define S_IRWXG 0 # define S_IRWXO 0 #endif // Memory #ifdef WIN32 # ifdef __MINGW32__ # include # elif defined (_MSC_VER) # define alloca _alloca # endif #elif defined(__linux__) || defined(__svr4__) # include #endif // Printf #ifdef _MSC_VER #define snprintf _snprintf #define vsnprintf _vsnprintf #endif // setenv() #ifndef HAVE_SETENV int setenv (const char *name, const char *value, int overwrite); #endif #ifndef HAVE_WCHAR_T typedef unsigned short wchar_t; #endif #ifndef HAVE_WINT_T typedef unsigned int wint_t; #endif #if defined (_MSC_VER) || defined(__MINGW32__) # define USE_WINSOCK #endif // errno error numbers. The values used don't matter, as long as they // don't conflict with existing errno error numbers. #ifdef PORT_WANT_ERRNO # ifdef USE_WINSOCK # include # ifndef E2BIG # define E2BIG 0x01000001 # endif # ifndef EACCES # define EACCES 0x01000002 # endif # ifndef EADDRINUSE # define EADDRINUSE 0x01000003 # endif # ifndef EADDRNOTAVAIL # define EADDRNOTAVAIL 0x01000004 # endif # ifndef EAFNOSUPPORT # define EAFNOSUPPORT 0x01000005 # endif # ifndef EAGAIN # ifdef EWOULDBLOCK # define EAGAIN EWOULDBLOCK # else # define EAGAIN 0x01000006 # endif # endif # ifndef EALREADY # define EALREADY 0x01000007 # endif # ifndef EBADF # define EBADF 0x01000008 # endif # ifndef EBADMSG # define EBADMSG 0x01000009 # endif # ifndef EBUSY # define EBUSY 0x0100000a # endif # ifndef ECANCELED # define ECANCELED 0x0100000b # endif # ifndef ECHILD # define ECHILD 0x0100000c # endif # ifndef ECONNABORTED # define ECONNABORTED 0x0100000d # endif # ifndef ECONNREFUSED # define ECONNREFUSED 0x0100000e # endif # ifndef ECONNRESET # define ECONNRESET 0x0100000f # endif # ifndef EDEADLK # define EDEADLK 0x01000010 # endif # ifndef EDESTADDRREQ # define EDESTADDRREQ 0x01000011 # endif # ifndef EDOM # define EDOM 0x01000012 # endif // Reserved in POSIX //# ifndef //EDQUOT //# define //EDQUOT 0x01000013 //# endif # ifndef EEXIST # define EEXIST 0x01000014 # endif # ifndef EFAULT # define EFAULT 0x01000015 # endif # ifndef EFBIG # define EFBIG 0x01000016 # endif # ifndef EHOSTUNREACH # define EHOSTUNREACH 0x01000017 # endif # ifndef EIDRM # define EIDRM 0x01000018 # endif # ifndef EILSEQ # define EILSEQ 0x01000019 # endif # ifndef EINPROGRESS # define EINPROGRESS 0x0100001a # endif # ifndef EINTR # define EINTR 0x0100001b # endif # ifndef EINVAL # define EINVAL 0x0100001c # endif # ifndef EIO # define EIO 0x0100001d # endif # ifndef EISCONN # define EISCONN 0x0100001e # endif # ifndef EISDIR # define EISDIR 0x0100001f # endif # ifndef ELOOP # define ELOOP 0x01000020 # endif # ifndef EMFILE # define EMFILE 0x01000021 # endif # ifndef EMLINK # define EMLINK 0x01000022 # endif # ifndef EMSGSIZE # define EMSGSIZE 0x01000023 # endif // Reserved in POSIX //# ifndef //EMULTIHOP //# define //EMULTIHOP 0x01000024 //# endif # ifndef ENAMETOOLONG # define ENAMETOOLONG 0x01000025 # endif # ifndef ENETDOWN # define ENETDOWN 0x01000026 # endif # ifndef ENETRESET # define ENETRESET 0x01000027 # endif # ifndef ENETUNREACH # define ENETUNREACH 0x01000028 # endif # ifndef ENFILE # define ENFILE 0x01000029 # endif # ifndef ENOBUFS # define ENOBUFS 0x0100002a # endif # ifndef ENODATA # define ENODATA 0x0100002b # endif # ifndef ENODEV # define ENODEV 0x0100002c # endif # ifndef ENOENT # define ENOENT 0x0100002d # endif # ifndef ENOEXEC # define ENOEXEC 0x0100002e # endif # ifndef ENOLCK # define ENOLCK 0x0100002f # endif // Reserved in POSIX //# ifndef ENOLINK //# define ENOLINK 0x01000030 //# endif # ifndef ENOMEM # define ENOMEM 0x01000031 # endif # ifndef ENOMSG # define ENOMSG 0x01000032 # endif # ifndef ENOPROTOOPT # define ENOPROTOOPT 0x01000033 # endif # ifndef ENOSPC # define ENOSPC 0x01000034 # endif # ifndef ENOSR # define ENOSR 0x01000035 # endif # ifndef ENOSTR # define ENOSTR 0x01000036 # endif # ifndef ENOSYS # define ENOSYS 0x01000037 # endif # ifndef ENOTCONN # define ENOTCONN 0x01000038 # endif # ifndef ENOTDIR # define ENOTDIR 0x01000039 # endif # ifndef ENOTEMPTY # define ENOTEMPTY 0x0100003a # endif # ifndef ENOTSOCK # define ENOTSOCK 0x0100003b # endif # ifndef ENOTSUP # define ENOTSUP 0x0100003c # endif # ifndef ENOTTY # define ENOTTY 0x0100003d # endif # ifndef ENXIO # define ENXIO 0x0100003e # endif # ifndef EOPNOTSUPP # define EOPNOTSUPP 0x0100003f # endif # ifndef EOVERFLOW # define EOVERFLOW 0x01000040 # endif # ifndef EPERM # define EPERM 0x01000041 # endif # ifndef EPIPE # define EPIPE 0x01000042 # endif # ifndef EPROTO # define EPROTO 0x01000043 # endif # ifndef EPROTONOSUPPORT # define EPROTONOSUPPORT 0x01000044 # endif # ifndef EPROTOTYPE # define EPROTOTYPE 0x01000045 # endif # ifndef ERANGE # define ERANGE 0x01000046 # endif # ifndef EROFS # define EROFS 0x01000047 # endif # ifndef ESPIPE # define ESPIPE 0x01000048 # endif # ifndef ESRCH # define ESRCH 0x01000049 # endif // Reserved in POSIX //# ifndef //ESTALE //# define //ESTALE 0x0100004a //# endif # ifndef ETIME # define ETIME 0x0100004b # endif # ifndef ETIMEDOUT # define ETIMEDOUT 0x0100004c # endif # ifndef ETXTBSY # define ETXTBSY 0x0100004d # endif # ifndef EWOULDBLOCK # ifdef EAGAIN # define EWOULDBLOCK EAGAIN # else # define EWOULDBLOCK 0x0100004e # endif # endif # ifndef EXDEV # define EXDEV 0x0100004f # endif // Non-POSIX: # ifndef EHOSTDOWN # define EHOSTDOWN 0x01100001 # endif # ifndef EPFNOSUPPORT # define EPFNOSUPPORT 0x01100002 # endif # ifndef EPROCLIM # define EPROCLIM 0x01100003 # endif # ifndef ESHUTDOWN # define ESHUTDOWN 0x01100004 # endif # ifndef ESOCKTNOSUPPORT # define ESOCKTNOSUPPORT 0x01100005 # endif # elif defined (__FreeBSD__) || defined (__OpenBSD__) # ifndef EBADMSG # define EBADMSG EIO # endif # endif /* defined (__FreeBSD__) || defined (__OpenBSD__) */ #endif /* defined (PORT_WANT_ERRNO) */ // Use SDL_INCLUDE and SDL_IMAGE_INCLUDE to portably include the SDL files // from the right location. // TODO: Where the SDL and SDL_image headers are located could be detected // from the build script. #ifdef __APPLE__ // SDL_image.h in a directory SDL_image under the include dir. # define SDL_DIR SDL # define SDL_IMAGE_DIR SDL_image #else // SDL_image.h directly under the include dir. # undef SDL_DIR # undef SDL_IMAGE_DIR #endif #ifdef SDL_DIR # define SDL_INCLUDE(file) #else # define SDL_INCLUDE(file) #endif /* SDL_DIR */ #ifdef SDL_IMAGE_DIR # define SDL_IMAGE_INCLUDE(file) #else # define SDL_IMAGE_INCLUDE(file) #endif /* SDL_IMAGE_DIR */ // Mark a function as using printf-style function arguments, so that // extra consistency checks can be made by the compiler. // The first argument to PRINTF_FUNCTION and VPRINTF_FUNCTION is the // index of the format string argument, the second is the index of // the first argument which is specified in the format string (in the // case of PRINTF_FUNCTION) or of the va_list argument (in the case of // VPRINTF_FUNCTION). #ifdef __GNUC__ # define PRINTF_FUNCTION(formatArg, firstArg) \ __attribute__((format(printf, formatArg, firstArg))) # define VPRINTF_FUNCTION(formatArg) \ __attribute__((format(printf, formatArg, 0))) #else # define PRINTF_FUNCTION(formatArg, firstArg) # define VPRINTF_FUNCTION(formatArg) #endif #if defined(__GNUC__) # define _NORETURN __attribute__((noreturn)) #else # define _NORETURN #endif #endif /* _PORT_H */ uqm-0.6.2/sc2/src/port.c0000600000175000017500000000516710543202107013420 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * This file contains definitions that might be included in one system, but * omited in another. * * Created by Serge van den Boom */ #include "port.h" #include #include #include #include #if !defined (_MSC_VER) && !defined (HAVE_READDIR_R) # include #endif #ifndef HAVE_STRUPR char * strupr (char *str) { char *ptr; ptr = str; while (*ptr) { *ptr = (char) toupper (*ptr); ptr++; } return str; } #endif #ifndef HAVE_SETENV int setenv (const char *name, const char *value, int overwrite) { char *string, *ptr; size_t nameLen, valueLen; if (!overwrite) { char *old; old = getenv (name); if (old != NULL) return 0; } nameLen = strlen (name); valueLen = strlen (value); string = malloc (nameLen + valueLen + 2); // "NAME=VALUE\0" // putenv() does NOT make a copy, but uses the string passed. ptr = string; strcpy (string, name); ptr += nameLen; *ptr = '='; ptr++; strcpy (ptr, value); return putenv (string); } #endif #if !defined (_MSC_VER) && !defined (HAVE_READDIR_R) // NB. This function calls readdir() directly, and as such has the same // reentrance issues as that function. For the purposes of UQM it will // do though. // Note the POSIX requires that "The pointer returned by readdir() // points to data which may be overwritten by another call to // readdir( ) on the same directory stream. This data is not // overwritten by another call to readdir() on a different directory // stream." // NB. This function makes an extra copy of the dirent and will hence be // slower than a direct call to readdir() or readdir_r(). int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) { struct dirent *readdir_entry; readdir_entry = readdir(dirp); if (readdir_entry == NULL) { *result = NULL; return errno; } *entry = *readdir_entry; *result = entry; return 0; } #endif uqm-0.6.2/sc2/src/sc2code/0000755000175000017500000000000010552600274013620 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/commanim.h0000600000175000017500000000252010543202101015543 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _COMMANIM_H #define _COMMANIM_H #include "libs/compiler.h" #include "libs/gfxlib.h" #include "libs/tasklib.h" #ifdef COMM_INTERNAL typedef enum { UP_DIR, DOWN_DIR, NO_DIR } ANIM_DIR; typedef enum { PICTURE_ANIM, COLOR_ANIM } ANIM_TYPE; struct SEQUENCE { COUNT Alarm; ANIM_DIR Direction; BYTE FramesLeft; ANIM_TYPE AnimType; union { FRAME CurFrame; COLORMAP CurCMap; } AnimObj; }; #endif typedef struct SEQUENCE SEQUENCE; typedef SEQUENCE *PSEQUENCE; void UpdateSpeechGraphics (BOOLEAN Initialize); Task StartCommAnimTask(void); extern volatile BOOLEAN PauseAnimTask; #endif /* _COMMANIM_H */ uqm-0.6.2/sc2/src/sc2code/commglue.h0000600000175000017500000000653310543202103015565 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _COMMGLUE_H #define _COMMGLUE_H #include "globdata.h" #include "resinst.h" #include "libs/sound/trackplayer.h" extern LOCDATA CommData; extern int cur_comm; extern UNICODE shared_phrase_buf[2048]; #define PLAYER_SAID(r,i) ((r)==(i)) #define PHRASE_ENABLED(p) \ (*(UNICODE *)GetStringAddress ( \ SetAbsStringTableIndex (CommData.ConversationPhrases, (p)-1) \ ) != '\0') #define DISABLE_PHRASE(p) \ (*(UNICODE *)GetStringAddress ( \ SetAbsStringTableIndex (CommData.ConversationPhrases, (p)-1) \ ) = '\0') #define RESPONSE_TO_REF(R) (R) #define Response(i,a) \ DoResponsePhrase(i,(RESPONSE_FUNC)a,0) enum { GLOBAL_PLAYER_NAME = -1000000, GLOBAL_SHIP_NAME, GLOBAL_PLAYER_LOCATION, GLOBAL_ALLIANCE_NAME, UNREASONABLE_NUMBER = GLOBAL_ALLIANCE_NAME + 1000, }; typedef COUNT RESPONSE_REF; typedef void (*RESPONSE_FUNC) (RESPONSE_REF R); extern void DoResponsePhrase (RESPONSE_REF R, RESPONSE_FUNC response_func, UNICODE *ContstructStr); extern void DoNPCPhrase (UNICODE *pStr); extern void NPCPhrase_cb (int index, TFB_TrackCB cb); #define NPCPhrase(index) NPCPhrase_cb ((index), NULL) #define ALLIANCE_NAME_BUFSIZE 256 extern void GetAllianceName (UNICODE *buf, RESPONSE_REF name_1); extern void construct_response (UNICODE *buf, int R /* promoted from RESPONSE_REF */, ...); extern LOCDATAPTR init_race (RESOURCE comm_id); extern LOCDATAPTR init_arilou_comm (void); extern LOCDATAPTR init_blackurq_comm (void); extern LOCDATAPTR init_chmmr_comm (void); extern LOCDATAPTR init_commander_comm (void); extern LOCDATAPTR init_druuge_comm (void); extern LOCDATAPTR init_ilwrath_comm (void); extern LOCDATAPTR init_melnorme_comm (void); extern LOCDATAPTR init_mycon_comm (void); extern LOCDATAPTR init_orz_comm (void); extern LOCDATAPTR init_pkunk_comm (void); extern LOCDATAPTR init_rebel_yehat_comm (void); extern LOCDATAPTR init_shofixti_comm (void); extern LOCDATAPTR init_slyland_comm (void); extern LOCDATAPTR init_slylandro_comm (void); extern LOCDATAPTR init_spahome_comm (void); extern LOCDATAPTR init_spathi_comm (void); extern LOCDATAPTR init_starbase_comm (void); extern LOCDATAPTR init_supox_comm (void); extern LOCDATAPTR init_syreen_comm (void); extern LOCDATAPTR init_talkpet_comm (void); extern LOCDATAPTR init_thradd_comm (void); extern LOCDATAPTR init_umgah_comm (void); extern LOCDATAPTR init_urquan_comm (void); extern LOCDATAPTR init_utwig_comm (void); extern LOCDATAPTR init_vux_comm (void); extern LOCDATAPTR init_yehat_comm (void); extern LOCDATAPTR init_zoqfot_comm (void); extern LOCDATAPTR init_umgah_comm (void); #endif /* _COMMGLUE_H */ uqm-0.6.2/sc2/src/sc2code/ifontres.h0000600000175000017500000000040010543202103015571 0ustar joeyjoey#define STARCON_FONT 0x03800003L #define TINY_FONT 0x03800103L #define MICRO_FONT 0x03c00203L #define LANDER_FONT 0x11400303L #define PLAYER_FONT 0x17a00403L #define PT13AA_FONT 0x24000503L #define PT17AA_FONT 0x24000603L #define PT45AA_FONT 0x24000703L uqm-0.6.2/sc2/src/sc2code/intro.c0000600000175000017500000004453310543202101015103 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "controls.h" #include "options.h" #include "settings.h" #include "setup.h" #include "sounds.h" #include "fmv.h" #include "resinst.h" #include "nameref.h" #include "libs/graphics/gfx_common.h" #include "libs/graphics/drawable.h" #include "libs/sound/sound.h" //#include "libs/vidlib.h" #include "libs/inplib.h" #include "libs/log.h" #include typedef struct { /* standard state required by DoInput */ BOOLEAN (*InputFunc) (PVOID pInputState); COUNT MenuRepeatDelay; /* Presentation state */ TimeCount StartTime; TimeCount LastSyncTime; TimeCount TimeOut; int TimeOutOnSkip; STRING SlideShow; FONT Font; FRAME Frame; MUSIC_REF MusicRef; BOOLEAN Batched; FRAME SisFrame; FRAME RotatedFrame; int LastDrawKind; int LastAngle; COUNT OperIndex; COLOR TextFadeColor; COLOR TextColor; COLOR TextBackColor; int TextVPos; RECT clip_r; RECT tfade_r; #define MAX_TEXT_LINES 15 TEXT TextLines[MAX_TEXT_LINES]; COUNT LinesCount; char Buffer[512]; } PRESENTATION_INPUT_STATE, *PPRESENTATION_INPUT_STATE; static BOOLEAN DoPresentation (PVOID pIS); BOOLEAN DoFMV (const char *name, const char *loopname, BOOLEAN uninit) { VIDEO_REF VidRef; VidRef = LoadVideoFile (name); if (!VidRef) return FALSE; VidPlay (VidRef, loopname, uninit); VidDoInput (); VidStop (); DestroyVideo (VidRef); return TRUE; } static BOOLEAN ParseColorString (const char *Src, COLOR* pColor) { unsigned clr; if (1 != sscanf (Src, "%x", &clr)) return FALSE; *pColor = BUILD_COLOR (MAKE_RGB15 ( (clr >> 19) & 0x1f, (clr >> 11) & 0x1f, (clr >> 3) & 0x1f), 0); return TRUE; } static BOOLEAN DoFadeScreen (PRESENTATION_INPUT_STATE* pPIS, const char *Src, BYTE FadeType) { BYTE xform_buf[1] = {FadeType}; int msecs; if (1 == sscanf (Src, "%d", &msecs)) { pPIS->TimeOut = XFormColorMap ((COLORMAPPTR) xform_buf, (SIZE)(msecs * ONE_SECOND / 1000)) + ONE_SECOND / 10; pPIS->TimeOutOnSkip = FALSE; } return TRUE; } static void DrawTracedText (TEXT *pText, COLOR Fore, COLOR Back) { SetContextForeGroundColor (Back); pText->baseline.x--; font_DrawText (pText); pText->baseline.x += 2; font_DrawText (pText); pText->baseline.x--; pText->baseline.y--; font_DrawText (pText); pText->baseline.y += 2; font_DrawText (pText); pText->baseline.y--; SetContextForeGroundColor (Fore); font_DrawText (pText); } static COUNT ParseTextLines (TEXT *Lines, COUNT MaxLines, char* Buffer) { COUNT i; const char* pEnd = Buffer + strlen (Buffer); for (i = 0; i < MaxLines && Buffer < pEnd; ++i, ++Lines) { char* pTerm = strchr (Buffer, '\n'); if (!pTerm) pTerm = Buffer + strlen (Buffer); *pTerm = '\0'; /* terminate string */ Lines->pStr = Buffer; Lines->CharCount = ~0; Buffer = pTerm + 1; } return i; } static void Present_BatchGraphics (PRESENTATION_INPUT_STATE* pPIS) { if (!pPIS->Batched) { pPIS->Batched = TRUE; LockMutex (GraphicsLock); BatchGraphics (); } } static void Present_UnbatchGraphics (PRESENTATION_INPUT_STATE* pPIS, BOOLEAN bYield) { if (pPIS->Batched) { UnbatchGraphics (); UnlockMutex (GraphicsLock); pPIS->Batched = FALSE; if (bYield) TaskSwitch (); } } static void Present_GenerateSIS (PRESENTATION_INPUT_STATE* pPIS) { #define MODULE_YOFS_P (-79) #define DRIVE_TOP_Y_P (DRIVE_TOP_Y + MODULE_YOFS_P) #define JET_TOP_Y_P (JET_TOP_Y + MODULE_YOFS_P) #define MODULE_TOP_Y_P (MODULE_TOP_Y + MODULE_YOFS_P) CONTEXT OldContext; FRAME SisFrame; FRAME ModuleFrame; FRAME SkelFrame; STAMP s; RECT r; HOT_SPOT hs; int slot; COUNT piece; COLOR SisBack; LockMutex (GraphicsLock); OldContext = SetContext (OffScreenContext); SkelFrame = CaptureDrawable (LoadGraphic (SISSKEL_MASK_PMAP_ANIM)); ModuleFrame = CaptureDrawable (LoadGraphic (SISMODS_MASK_PMAP_ANIM)); GetFrameRect (SkelFrame, &r); SisFrame = CaptureDrawable (CreateDrawable ( WANT_PIXMAP, r.extent.width, r.extent.height, 1 )); SetContextFGFrame (SisFrame); SetContextClipRect (NULL_PTR); SisBack = BUILD_COLOR (MAKE_RGB15 (0x01, 0x01, 0x01), 0x07); SetContextBackGroundColor (SisBack); ClearDrawable (); SetFrameTransparentColor (SisFrame, SisBack); s.frame = SetAbsFrameIndex (SkelFrame, 0); s.origin.x = 0; s.origin.y = 0; DrawStamp (&s); for (slot = 0; slot < NUM_DRIVE_SLOTS; ++slot) { piece = GLOBAL_SIS (DriveSlots[slot]); if (piece < EMPTY_SLOT) { s.origin.x = DRIVE_TOP_X; s.origin.y = DRIVE_TOP_Y_P; s.origin.x += slot * SHIP_PIECE_OFFSET; s.frame = SetAbsFrameIndex (ModuleFrame, piece); DrawStamp (&s); } } for (slot = 0; slot < NUM_JET_SLOTS; ++slot) { piece = GLOBAL_SIS (JetSlots[slot]); if (piece < EMPTY_SLOT) { s.origin.x = JET_TOP_X; s.origin.y = JET_TOP_Y_P; s.origin.x += slot * SHIP_PIECE_OFFSET; s.frame = SetAbsFrameIndex (ModuleFrame, piece); DrawStamp (&s); } } for (slot = 0; slot < NUM_MODULE_SLOTS; ++slot) { piece = GLOBAL_SIS (ModuleSlots[slot]); if (piece < EMPTY_SLOT) { s.origin.x = MODULE_TOP_X; s.origin.y = MODULE_TOP_Y_P; s.origin.x += slot * SHIP_PIECE_OFFSET; s.frame = SetAbsFrameIndex (ModuleFrame, piece); DrawStamp (&s); } } DestroyDrawable (ReleaseDrawable (SkelFrame)); DestroyDrawable (ReleaseDrawable (ModuleFrame)); hs.x = r.extent.width / 2; hs.y = r.extent.height / 2; SetFrameHot (SisFrame, hs); SetContext (OldContext); FlushGraphics (); UnlockMutex (GraphicsLock); pPIS->SisFrame = SisFrame; } BOOLEAN ShowPresentationFile (const char *name) { return ShowPresentation (CaptureStringTable ( LoadStringTableFile (contentDir, name))); } static BOOLEAN DoPresentation (PVOID pIS) { PRESENTATION_INPUT_STATE* pPIS = (PRESENTATION_INPUT_STATE*) pIS; if (PulsedInputState.menu[KEY_MENU_CANCEL] || (GLOBAL (CurrentActivity) & CHECK_ABORT)) return FALSE; /* abort requested - we are done */ if (pPIS->TimeOut) { if (GetTimeCounter () > pPIS->TimeOut) { /* time elapsed - continue normal ops */ pPIS->TimeOut = 0; return TRUE; } if (pPIS->TimeOutOnSkip && (PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_SPECIAL] || PulsedInputState.menu[KEY_MENU_RIGHT]) ) { /* skip requested - continue normal ops */ pPIS->TimeOut = 0; return TRUE; } SleepThread (ONE_SECOND / 84); return TRUE; } while (pPIS->OperIndex < GetStringTableCount (pPIS->SlideShow)) { char Opcode[16]; STRINGPTR pStr = GetStringAddress (pPIS->SlideShow); pPIS->OperIndex++; pPIS->SlideShow = SetRelStringTableIndex (pPIS->SlideShow, 1); if (!pStr) continue; if (1 != sscanf (pStr, "%15s", Opcode)) continue; pStr += strlen (Opcode); if (*pStr != '\0') ++pStr; strupr (Opcode); if (strcmp (Opcode, "DIMS") == 0) { /* set dimensions */ int w, h; if (2 == sscanf (pStr, "%d %d", &w, &h)) { pPIS->clip_r.extent.width = w; pPIS->clip_r.extent.height = h; /* center on screen */ pPIS->clip_r.corner.x = (SCREEN_WIDTH - w) / 2; pPIS->clip_r.corner.y = (SCREEN_HEIGHT - h) / 2; LockMutex (GraphicsLock); SetContextClipRect (&pPIS->clip_r); UnlockMutex (GraphicsLock); } } else if (strcmp (Opcode, "FONT") == 0) { /* set font */ utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr); if (pPIS->Font) DestroyFont (ReleaseFont (pPIS->Font)); pPIS->Font = CaptureFont ((FONT_REF) LoadFontFile (pPIS->Buffer)); if (!pPIS->Batched) LockMutex (GraphicsLock); SetContextFont (pPIS->Font); if (!pPIS->Batched) UnlockMutex (GraphicsLock); } else if (strcmp (Opcode, "ANI") == 0) { /* set ani */ utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr); if (pPIS->Frame) DestroyDrawable (ReleaseDrawable (pPIS->Frame)); pPIS->Frame = CaptureDrawable (LoadCelFile (pPIS->Buffer)); } else if (strcmp (Opcode, "MUSIC") == 0) { /* set music */ utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr); if (pPIS->MusicRef) { StopMusic (); DestroyMusic (pPIS->MusicRef); } pPIS->MusicRef = LoadMusicFile (pPIS->Buffer); PlayMusic (pPIS->MusicRef, FALSE, 1); } else if (strcmp (Opcode, "WAIT") == 0) { /* wait */ int msecs; Present_UnbatchGraphics (pPIS, TRUE); if (1 == sscanf (pStr, "%d", &msecs)) { pPIS->TimeOut = GetTimeCounter () + msecs * ONE_SECOND / 1000; pPIS->TimeOutOnSkip = TRUE; return TRUE; } } else if (strcmp (Opcode, "SYNC") == 0) { /* absolute time-sync */ int msecs; Present_UnbatchGraphics (pPIS, TRUE); if (1 == sscanf (pStr, "%d", &msecs)) { pPIS->LastSyncTime = pPIS->StartTime + msecs * ONE_SECOND / 1000; pPIS->TimeOut = pPIS->LastSyncTime; pPIS->TimeOutOnSkip = FALSE; return TRUE; } } else if (strcmp (Opcode, "RESYNC") == 0) { /* flush and update absolute sync point */ pPIS->LastSyncTime = pPIS->StartTime = GetTimeCounter (); } else if (strcmp (Opcode, "DSYNC") == 0) { /* delta time-sync; from the last absolute sync */ int msecs; Present_UnbatchGraphics (pPIS, TRUE); if (1 == sscanf (pStr, "%d", &msecs)) { pPIS->TimeOut = pPIS->LastSyncTime + msecs * ONE_SECOND / 1000; pPIS->TimeOutOnSkip = FALSE; return TRUE; } } else if (strcmp (Opcode, "TC") == 0) { /* text fore color */ ParseColorString (pStr, &pPIS->TextColor); } else if (strcmp (Opcode, "TBC") == 0) { /* text back color */ ParseColorString (pStr, &pPIS->TextBackColor); } else if (strcmp (Opcode, "TFC") == 0) { /* text fade color */ ParseColorString (pStr, &pPIS->TextFadeColor); } else if (strcmp (Opcode, "TVA") == 0) { /* text vertical align */ pPIS->TextVPos = toupper (*pStr); } else if (strcmp (Opcode, "TEXT") == 0) { /* simple text draw */ SIZE leading; COUNT i; COORD y; utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr); pPIS->LinesCount = ParseTextLines (pPIS->TextLines, MAX_TEXT_LINES, pPIS->Buffer); if (!pPIS->Batched) LockMutex (GraphicsLock); GetContextFontLeading (&leading); if (!pPIS->Batched) UnlockMutex (GraphicsLock); switch (pPIS->TextVPos) { case 'T': /* top */ y = leading; break; case 'M': /* middle */ y = (pPIS->clip_r.extent.height - pPIS->LinesCount * leading) / 2; break; default: /* bottom */ y = pPIS->clip_r.extent.height - pPIS->LinesCount * leading; } for (i = 0; i < pPIS->LinesCount; ++i, y += leading) { pPIS->TextLines[i].align = ALIGN_CENTER; pPIS->TextLines[i].baseline.x = SCREEN_WIDTH / 2; pPIS->TextLines[i].baseline.y = y; } if (!pPIS->Batched) LockMutex (GraphicsLock); SetContextClipping (TRUE); for (i = 0; i < pPIS->LinesCount; ++i) DrawTracedText (pPIS->TextLines + i, pPIS->TextColor, pPIS->TextBackColor); if (!pPIS->Batched) UnlockMutex (GraphicsLock); } else if (strcmp (Opcode, "TFI") == 0) { /* text fade-in */ SIZE leading; COUNT i; COORD y; utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr); pPIS->LinesCount = ParseTextLines (pPIS->TextLines, MAX_TEXT_LINES, pPIS->Buffer); Present_UnbatchGraphics (pPIS, TRUE); LockMutex (GraphicsLock); GetContextFontLeading (&leading); UnlockMutex (GraphicsLock); switch (pPIS->TextVPos) { case 'T': /* top */ y = leading; break; case 'M': /* middle */ y = (pPIS->clip_r.extent.height - pPIS->LinesCount * leading) / 2; break; default: /* bottom */ y = pPIS->clip_r.extent.height - pPIS->LinesCount * leading; } pPIS->tfade_r = pPIS->clip_r; pPIS->tfade_r.corner.y += y - leading; pPIS->tfade_r.extent.height = (pPIS->LinesCount + 1) * leading; for (i = 0; i < pPIS->LinesCount; ++i, y += leading) { pPIS->TextLines[i].align = ALIGN_CENTER; pPIS->TextLines[i].baseline.x = SCREEN_WIDTH / 2; pPIS->TextLines[i].baseline.y = y; } LockMutex (GraphicsLock); SetContextClipping (TRUE); for (i = 0; i < pPIS->LinesCount; ++i) DrawTracedText (pPIS->TextLines + i, pPIS->TextFadeColor, pPIS->TextFadeColor); /* do transition */ SetTransitionSource (&pPIS->tfade_r); BatchGraphics (); for (i = 0; i < pPIS->LinesCount; ++i) DrawTracedText (pPIS->TextLines + i, pPIS->TextColor, pPIS->TextBackColor); ScreenTransition (3, &pPIS->tfade_r); UnbatchGraphics (); UnlockMutex (GraphicsLock); } else if (strcmp (Opcode, "TFO") == 0) { /* text fade-out */ COUNT i; Present_UnbatchGraphics (pPIS, TRUE); LockMutex (GraphicsLock); SetContextClipping (TRUE); /* do transition */ SetTransitionSource (&pPIS->tfade_r); BatchGraphics (); for (i = 0; i < pPIS->LinesCount; ++i) DrawTracedText (pPIS->TextLines + i, pPIS->TextFadeColor, pPIS->TextFadeColor); ScreenTransition (3, &pPIS->tfade_r); UnbatchGraphics (); UnlockMutex (GraphicsLock); } else if (strcmp (Opcode, "SAVEBG") == 0) { /* save background */ TFB_DrawScreen_Copy (&pPIS->clip_r, TFB_SCREEN_MAIN, TFB_SCREEN_EXTRA); } else if (strcmp (Opcode, "RESTBG") == 0) { /* restore background */ TFB_DrawScreen_Copy (&pPIS->clip_r, TFB_SCREEN_EXTRA, TFB_SCREEN_MAIN); } else if (strcmp (Opcode, "DRAW") == 0) { /* draw a graphic */ #define PRES_DRAW_INDEX 0 #define PRES_DRAW_SIS 1 int cargs; int draw_what; int index, x, y, scale, angle; char ImgName[16]; int OldScale; STAMP s; if (1 == sscanf (pStr, "%15s", ImgName) && strcmp (strupr (ImgName), "SIS") == 0) { draw_what = PRES_DRAW_SIS; cargs = sscanf (pStr, "%*s %d %d %d %d", &x, &y, &scale, &angle) + 1; } else { draw_what = PRES_DRAW_INDEX; cargs = sscanf (pStr, "%d %d %d %d %d", &index, &x, &y, &scale, &angle); } if (cargs < 1) { log_add (log_Warning, "Bad DRAW command '%s'", pStr); continue; } if (cargs < 5) angle = 0; if (cargs < 4) scale = GSCALE_IDENTITY; if (cargs < 3) { x = 0; y = 0; } if (draw_what == PRES_DRAW_INDEX) { /* draw stamp by index */ s.frame = SetAbsFrameIndex (pPIS->Frame, (COUNT)index); } else if (draw_what == PRES_DRAW_SIS) { /* draw dynamic SIS image with player's modules */ if (!pPIS->SisFrame) Present_GenerateSIS (pPIS); s.frame = SetAbsFrameIndex (pPIS->SisFrame, 0); } if (angle != 0) { if (angle != pPIS->LastAngle || draw_what != pPIS->LastDrawKind) { DestroyDrawable (ReleaseDrawable (pPIS->RotatedFrame)); pPIS->RotatedFrame = CaptureDrawable ( RotateFrame (s.frame, DEGREES_TO_ANGLE (angle))); pPIS->LastAngle = angle; pPIS->LastDrawKind = draw_what; } s.frame = pPIS->RotatedFrame; } s.origin.x = x; s.origin.y = y; if (!pPIS->Batched) LockMutex (GraphicsLock); OldScale = GetGraphicScale (); SetGraphicScale (scale); SetContextClipping (TRUE); DrawStamp (&s); SetGraphicScale (OldScale); if (!pPIS->Batched) UnlockMutex (GraphicsLock); } else if (strcmp (Opcode, "BATCH") == 0) { /* batch graphics */ Present_BatchGraphics (pPIS); } else if (strcmp (Opcode, "UNBATCH") == 0) { /* unbatch graphics */ Present_UnbatchGraphics (pPIS, FALSE); } else if (strcmp (Opcode, "FTC") == 0) { /* fade to color */ Present_UnbatchGraphics (pPIS, TRUE); return DoFadeScreen (pPIS, pStr, FadeAllToColor); } else if (strcmp (Opcode, "FTB") == 0) { /* fade to black */ Present_UnbatchGraphics (pPIS, TRUE); return DoFadeScreen (pPIS, pStr, FadeAllToBlack); } else if (strcmp (Opcode, "FTW") == 0) { /* fade to white */ Present_UnbatchGraphics (pPIS, TRUE); return DoFadeScreen (pPIS, pStr, FadeAllToWhite); } else if (strcmp (Opcode, "CLS") == 0) { /* clear screen */ RECT r; Present_UnbatchGraphics (pPIS, TRUE); LockMutex (GraphicsLock); GetContextClipRect (&r); r.corner.x = r.corner.y = 0; /* paint black rect over screen */ SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); DrawFilledRectangle (&r); UnlockMutex (GraphicsLock); } else if (strcmp (Opcode, "CALL") == 0) { /* call another script */ Present_UnbatchGraphics (pPIS, TRUE); utf8StringCopy (pPIS->Buffer, sizeof (pPIS->Buffer), pStr); ShowPresentationFile (pPIS->Buffer); } else if (strcmp (Opcode, "NOOP") == 0) { /* no operation - must be a comment in script */ /* do nothing */ } } /* we are all done */ return FALSE; } BOOLEAN ShowPresentation (STRING PresStr) { CONTEXT OldContext; FONT OldFont; RECT OldRect; PRESENTATION_INPUT_STATE pis; pis.SlideShow = PresStr; if (!pis.SlideShow) return FALSE; pis.SlideShow = SetAbsStringTableIndex (pis.SlideShow, 0); pis.OperIndex = 0; LockMutex (GraphicsLock); OldContext = SetContext (ScreenContext); GetContextClipRect (&OldRect); OldFont = SetContextFont (NULL); /* paint black rect over screen */ SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); ClearDrawable (); UnlockMutex (GraphicsLock); FlushInput (); SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); pis.MenuRepeatDelay = 0; pis.InputFunc = DoPresentation; pis.Font = 0; pis.Frame = 0; pis.RotatedFrame = 0; pis.LastDrawKind = -1; pis.LastAngle = 0; pis.MusicRef = 0; pis.SisFrame = 0; pis.Batched = FALSE; pis.TextVPos = 'B'; pis.LastSyncTime = pis.StartTime = GetTimeCounter (); pis.TimeOut = 0; DoInput (&pis, TRUE); SleepThreadUntil (FadeMusic (0, ONE_SECOND)); StopMusic (); FadeMusic (NORMAL_VOLUME, 0); DestroyMusic (pis.MusicRef); DestroyDrawable (ReleaseDrawable (pis.RotatedFrame)); DestroyDrawable (ReleaseDrawable (pis.Frame)); DestroyFont (ReleaseFont (pis.Font)); DestroyStringTable (ReleaseStringTable (pis.SlideShow)); LockMutex (GraphicsLock); SetContextFont (OldFont); SetContextClipRect (&OldRect); SetContext (OldContext); UnlockMutex (GraphicsLock); return TRUE; } uqm-0.6.2/sc2/src/sc2code/load.h0000600000175000017500000000170010543202101014661 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _LOAD_H #define _LOAD_H #include "sis.h" #include "libs/compiler.h" #include "globdata.h" extern ACTIVITY NextActivity; extern BOOLEAN LoadGame (COUNT which_game, SUMMARY_DESC *summary_desc); #endif /* _LOAD_H */ uqm-0.6.2/sc2/src/sc2code/restypes.h0000600000175000017500000000165510543202103015633 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/melee.h0000600000175000017500000000667710543202101015053 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MELEE_H #define _MELEE_H #include "init.h" #include "libs/tasklib.h" #include "libs/gfxlib.h" #include "libs/sndlib.h" #include "libs/reslib.h" #include "netplay/packet.h" // for NetplayAbortREason and NetplayResetReason. typedef struct melee_state MELEE_STATE; enum { MELEE_ANDROSYNTH, MELEE_ARILOU, MELEE_CHENJESU, MELEE_CHMMR, MELEE_DRUUGE, MELEE_EARTHLING, MELEE_ILWRATH, MELEE_KOHR_AH, MELEE_MELNORME, MELEE_MMRNMHRM, MELEE_MYCON, MELEE_ORZ, MELEE_PKUNK, MELEE_SHOFIXTI, MELEE_SLYLANDRO, MELEE_SPATHI, MELEE_SUPOX, MELEE_SYREEN, MELEE_THRADDASH, MELEE_UMGAH, MELEE_URQUAN, MELEE_UTWIG, MELEE_VUX, MELEE_YEHAT, MELEE_ZOQFOTPIK, NUM_MELEE_SHIPS, MELEE_NONE = (BYTE) ~0 }; #define NUM_MELEE_ROWS 2 #define NUM_MELEE_COLUMNS 7 //#define NUM_MELEE_COLUMNS 6 #define MELEE_FLEET_SIZE (NUM_MELEE_ROWS * NUM_MELEE_COLUMNS) #define ICON_WIDTH 16 #define ICON_HEIGHT 16 extern FRAME PickMeleeFrame; #define PICK_BG_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x01, 0x0F), 0x01) #define MAX_TEAM_CHARS 30 #define MAX_VIS_TEAMS 5 #define NUM_PREBUILT 15 #define NUM_PICK_COLS 5 #define NUM_PICK_ROWS 5 typedef BYTE MELEE_OPTIONS; typedef COUNT FleetShipIndex; typedef struct { BYTE ShipList[MELEE_FLEET_SIZE]; UNICODE TeamName[MAX_TEAM_CHARS + 1 + 24]; /* The +1 is for the terminating \0; the +24 is in case some * default name in starcon.txt is unknowingly mangled. */ } TEAM_IMAGE; struct melee_state { BOOLEAN (*InputFunc) (struct melee_state *pInputState); COUNT MenuRepeatDelay; BOOLEAN Initialized; MELEE_OPTIONS MeleeOption; DIRENTRY TeamDE; COUNT TopTeamIndex, BotTeamIndex; COUNT side, row, col; TEAM_IMAGE TeamImage[NUM_SIDES]; COUNT star_bucks[NUM_SIDES]; COUNT CurIndex; Task flash_task; TEAM_IMAGE FileList[MAX_VIS_TEAMS]; TEAM_IMAGE PreBuiltList[NUM_PREBUILT]; MUSIC_REF hMusic; }; typedef MELEE_STATE *PMELEE_STATE; extern PMELEE_STATE volatile pMeleeState; extern void Melee (void); void teamStringChanged (PMELEE_STATE pMS, int player); void entireFleetChanged (PMELEE_STATE pMS, int player); void fleetShipChanged (PMELEE_STATE pMS, int player, size_t index); void updateTeamName (PMELEE_STATE pMS, COUNT side, const char *name, size_t len); bool updateFleetShip (PMELEE_STATE pMS, COUNT side, COUNT index, BYTE ship); void updateRandomSeed (PMELEE_STATE pMS, COUNT side, DWORD seed); void confirmationCancelled(PMELEE_STATE pMS, COUNT side); void connectedFeedback (NetConnection *conn); void abortFeedback (NetConnection *conn, NetplayAbortReason reason); void resetFeedback (NetConnection *conn, NetplayResetReason reason, bool byRemote); void errorFeedback (NetConnection *conn); void closeFeedback (NetConnection *conn); #endif /* _MELEE_H */ uqm-0.6.2/sc2/src/sc2code/comm/0000755000175000017500000000000010552600275014554 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/syreen/0000755000175000017500000000000010552600275016061 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/syreen/syreen.res0000600000175000017500000000042610543202027020064 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/syreen PACKAGE SYREEN_PACKAGE syreen.con GFXRES SYREEN_PMAP_ANIM syreen.ani FONTRES SYREEN_FONT syreen.fon MUSICRES SYREEN_MUSIC syreen.mod STRTAB SYREEN_CONVERSATION_PHRASES syreen.txt STRTAB SYREEN_COLOR_MAP syreen.ct uqm-0.6.2/sc2/src/sc2code/comm/syreen/ifontres.h0000600000175000017500000000004210543202027020040 0ustar joeyjoey#define SYREEN_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/syreen/restypes.h0000600000175000017500000000024110543202027020066 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/syreen/syreenc.c0000600000175000017500000004621110543202027017662 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/syreen/resinst.h" #include "comm/syreen/strings.h" #include "libs/sound/sound.h" #include "build.h" static LOCDATA syreen_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)SYREEN_PMAP_ANIM, /* AlienFrame */ (FONT)SYREEN_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)SYREEN_COLOR_MAP, /* AlienColorMap */ SYREEN_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ SYREEN_CONVERSATION_PHRASES, /* PlayerPhrases */ 15, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 5, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 7, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 9, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 11, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 13, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 15, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 12), /* BlockMask */ }, { 17, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 19, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 13), }, { 21, /* StartIndex */ 6, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 27, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ (1 << 14), /* BlockMask */ }, { 31, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 37, /* StartIndex */ 4, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND / 15, ONE_SECOND / 15, /* RestartRate */ 0, /* BlockMask */ }, { 41, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ (1 << 5), /* BlockMask */ }, { 44, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 6, 0, /* FrameRate */ ONE_SECOND * 3, ONE_SECOND, /* RestartRate */ (1 << 7) | (1 << 14), /* BlockMask */ }, { 48, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND,/* RestartRate */ (1 << 9) | (1 << 13), /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 4, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void FriendlyExit (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (PLAYER_SAID (R, bye)) NPCPhrase (GOODBYE); else if (PLAYER_SAID (R, im_on_my_way) || PLAYER_SAID (R, doing_this_for_you) || PLAYER_SAID (R, if_i_die)) NPCPhrase (GOOD_LUCK); else if (PLAYER_SAID (R, bye_before_vault)) NPCPhrase (GOODBYE_BEFORE_VAULT); else if (PLAYER_SAID (R, bye_after_vault)) NPCPhrase (GOODBYE_AFTER_VAULT); else if (PLAYER_SAID (R, bye_before_ambush)) NPCPhrase (GOODBYE_BEFORE_AMBUSH); else if (PLAYER_SAID (R, bye_after_ambush)) NPCPhrase (GOODBYE_AFTER_AMBUSH); else { if (PLAYER_SAID (R, hands_off)) NPCPhrase (OK_WONT_USE_HANDS); else if (PLAYER_SAID (R, not_much_more_to_say)) NPCPhrase (THEN_STOP_TALKING); NPCPhrase (LATER); NPCPhrase (SEX_GOODBYE); AlienTalkSegue (1); AlienTalkSegue (2); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 0) ), ONE_SECOND / 2); AlienTalkSegue ((COUNT)~0); SET_GAME_STATE (PLAYER_HAD_SEX, 1); SET_GAME_STATE (PLAYER_HAVING_SEX, 0); } } static void Sex (RESPONSE_REF R) { if (PLAYER_SAID (R, in_the_spirit)) NPCPhrase (OK_SPIRIT); else if (PLAYER_SAID (R, what_in_mind)) NPCPhrase (SOMETHING_LIKE_THIS); else if (PLAYER_SAID (R, disease)) NPCPhrase (JUST_RELAX); else if (PLAYER_SAID (R, what_happens_if_i_touch_this)) { NPCPhrase (THIS_HAPPENS); DISABLE_PHRASE (what_happens_if_i_touch_this); } else if (PLAYER_SAID (R, are_you_sure_this_is_ok)) { NPCPhrase (YES_SURE); DISABLE_PHRASE (are_you_sure_this_is_ok); } else if (PLAYER_SAID (R, boy_they_never_taught)) { NPCPhrase (THEN_LET_ME_TEACH); DISABLE_PHRASE (boy_they_never_taught); } if (!PHRASE_ENABLED (what_happens_if_i_touch_this) && !PHRASE_ENABLED (are_you_sure_this_is_ok) && !PHRASE_ENABLED (boy_they_never_taught)) Response (not_much_more_to_say, FriendlyExit); else { if (PHRASE_ENABLED (what_happens_if_i_touch_this)) Response (what_happens_if_i_touch_this, Sex); if (PHRASE_ENABLED (are_you_sure_this_is_ok)) Response (are_you_sure_this_is_ok, Sex); if (PHRASE_ENABLED (boy_they_never_taught)) Response (boy_they_never_taught, Sex); } } static void Foreplay (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_my_reward) || PLAYER_SAID (R, what_about_us)) { if (PLAYER_SAID (R, whats_my_reward)) NPCPhrase (HERES_REWARD); else NPCPhrase (ABOUT_US); NPCPhrase (MORE_COMFORTABLE); AlienTalkSegue (1); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 1) ), ONE_SECOND); AlienTalkSegue ((COUNT)~0); SET_GAME_STATE (PLAYER_HAVING_SEX, 1); } else if (PLAYER_SAID (R, why_lights_off)) { NPCPhrase (LIGHTS_OFF_BECAUSE); DISABLE_PHRASE (why_lights_off); } else if (PLAYER_SAID (R, evil_monster)) { NPCPhrase (NOT_EVIL_MONSTER); DISABLE_PHRASE (evil_monster); } if (PHRASE_ENABLED (why_lights_off)) Response (why_lights_off, Foreplay); else if (PHRASE_ENABLED (evil_monster)) Response (evil_monster, Foreplay); else Response (disease, Sex); Response (in_the_spirit, Sex); Response (what_in_mind, Sex); Response (hands_off, FriendlyExit); } static void AfterAmbush (RESPONSE_REF R) { if (PLAYER_SAID (R, what_now_after_ambush)) { NPCPhrase (DO_THIS_AFTER_AMBUSH); DISABLE_PHRASE (what_now_after_ambush); } else if (PLAYER_SAID (R, what_about_you)) { NPCPhrase (ABOUT_ME); DISABLE_PHRASE (what_about_you); } else if (PLAYER_SAID (R, whats_up_after_ambush)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (SYREEN_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_AFTER_AMBUSH_1); break; case 1: NPCPhrase (GENERAL_INFO_AFTER_AMBUSH_2); break; case 2: NPCPhrase (GENERAL_INFO_AFTER_AMBUSH_3); break; case 3: NPCPhrase (GENERAL_INFO_AFTER_AMBUSH_4); --NumVisits; break; } SET_GAME_STATE (SYREEN_INFO, NumVisits); DISABLE_PHRASE (whats_up_after_ambush); } if (PHRASE_ENABLED (what_about_you)) Response (what_about_you, AfterAmbush); else if (!GET_GAME_STATE (PLAYER_HAD_SEX)) { Response (what_about_us, Foreplay); } if (PHRASE_ENABLED (what_now_after_ambush)) Response (what_now_after_ambush, AfterAmbush); if (PHRASE_ENABLED (whats_up_after_ambush)) Response (whats_up_after_ambush, AfterAmbush); Response (bye_after_ambush, FriendlyExit); } static void AmbushReady (RESPONSE_REF R) { if (PLAYER_SAID (R, repeat_plan)) { NPCPhrase (OK_REPEAT_PLAN); DISABLE_PHRASE (repeat_plan); } if (PHRASE_ENABLED (repeat_plan)) Response (repeat_plan, AmbushReady); Response (bye_before_ambush, FriendlyExit); } static void SyreenShuttle (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_next_step)) { NPCPhrase (OPEN_VAULT); DISABLE_PHRASE (whats_next_step); } else if (PLAYER_SAID (R, what_do_i_get_for_this)) { NPCPhrase (GRATITUDE); DISABLE_PHRASE (what_do_i_get_for_this); } else if (PLAYER_SAID (R, not_sure)) { NPCPhrase (PLEASE); DISABLE_PHRASE (not_sure); } else if (PLAYER_SAID (R, where_is_it)) { NPCPhrase (DONT_KNOW_WHERE); NPCPhrase (GIVE_SHUTTLE); SET_GAME_STATE (SYREEN_SHUTTLE, 1); SET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP, 1); DISABLE_PHRASE (where_is_it); } else if (PLAYER_SAID (R, been_there)) { NPCPhrase (GREAT); NPCPhrase (GIVE_SHUTTLE); SET_GAME_STATE (SYREEN_SHUTTLE, 1); SET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP, 1); DISABLE_PHRASE (been_there); } if (PHRASE_ENABLED (whats_next_step)) Response (whats_next_step, SyreenShuttle); else { if (!GET_GAME_STATE (KNOW_SYREEN_VAULT)) { if (PHRASE_ENABLED (where_is_it)) Response (where_is_it, SyreenShuttle); } else { if (PHRASE_ENABLED (been_there)) Response (been_there, SyreenShuttle); } if (!PHRASE_ENABLED (where_is_it) || !PHRASE_ENABLED (been_there)) { Response (im_on_my_way, FriendlyExit); Response (doing_this_for_you, FriendlyExit); Response (if_i_die, FriendlyExit); } } if (PHRASE_ENABLED (what_do_i_get_for_this)) Response (what_do_i_get_for_this, SyreenShuttle); if (PHRASE_ENABLED (not_sure)) Response (not_sure, SyreenShuttle); } static void NormalSyreen (RESPONSE_REF R) { BYTE i, LastStack; RESPONSE_REF pStr[4]; LastStack = 0; pStr[0] = pStr[1] = pStr[2] = pStr[3] = 0; if (PLAYER_SAID (R, we_here_to_help)) NPCPhrase (NO_NEED_HELP); else if (PLAYER_SAID (R, we_need_help)) NPCPhrase (CANT_GIVE_HELP); else if (PLAYER_SAID (R, know_about_deep_children)) { NPCPhrase (WHAT_ABOUT_DEEP_CHILDREN); DISABLE_PHRASE (know_about_deep_children); } else if (PLAYER_SAID (R, mycons_involved)) { NPCPhrase (WHAT_PROOF); SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 3); } else if (PLAYER_SAID (R, have_no_proof)) { NPCPhrase (NEED_PROOF); SET_GAME_STATE (SYREEN_WANT_PROOF, 1); } else if (PLAYER_SAID (R, have_proof)) { NPCPhrase (SEE_PROOF); DISABLE_PHRASE (have_proof); } else if (PLAYER_SAID (R, what_doing_here)) { NPCPhrase (OUR_NEW_WORLD); SET_GAME_STATE (SYREEN_STACK0, 1); LastStack = 1; } else if (PLAYER_SAID (R, what_about_war)) { NPCPhrase (ABOUT_WAR); SET_GAME_STATE (SYREEN_STACK0, 2); LastStack = 1; } else if (PLAYER_SAID (R, help_us)) { NPCPhrase (WONT_HELP); SET_GAME_STATE (SYREEN_STACK0, 3); } else if (PLAYER_SAID (R, what_about_history)) { NPCPhrase (BEFORE_WAR); SET_GAME_STATE (SYREEN_STACK1, 1); LastStack = 2; } else if (PLAYER_SAID (R, what_about_homeworld)) { NPCPhrase (ABOUT_HOMEWORLD); SET_GAME_STATE (SYREEN_STACK1, 2); LastStack = 2; } else if (PLAYER_SAID (R, what_happened)) { NPCPhrase (DONT_KNOW_HOW); SET_GAME_STATE (KNOW_SYREEN_WORLD_SHATTERED, 1); SET_GAME_STATE (SYREEN_STACK1, 3); } else if (PLAYER_SAID (R, what_about_outfit)) { NPCPhrase (HOPE_YOU_LIKE_IT); SET_GAME_STATE (SYREEN_STACK2, 1); LastStack = 3; } else if (PLAYER_SAID (R, where_mates)) { NPCPhrase (MATES_KILLED); SET_GAME_STATE (SYREEN_STACK2, 2); LastStack = 3; } else if (PLAYER_SAID (R, get_lonely)) { NPCPhrase (MAKE_OUT_ALL_RIGHT); SET_GAME_STATE (SYREEN_STACK2, 3); } else if (PLAYER_SAID (R, look_at_egg_sacks)) { NPCPhrase (HORRIBLE_TRUTH); SET_GAME_STATE (BATTLE_SEGUE, 0); SET_GAME_STATE (SYREEN_HOME_VISITS, 0); SET_GAME_STATE (SYREEN_KNOW_ABOUT_MYCON, 1); SyreenShuttle ((RESPONSE_REF)0); return; } if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) < 3) { if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) == 2 && GET_GAME_STATE (KNOW_SYREEN_WORLD_SHATTERED)) { if (PHRASE_ENABLED (know_about_deep_children)) pStr[0] = know_about_deep_children; else pStr[0] = mycons_involved; } } else { if (GET_GAME_STATE (EGG_CASE0_ON_SHIP) || GET_GAME_STATE (EGG_CASE1_ON_SHIP) || GET_GAME_STATE (EGG_CASE2_ON_SHIP)) { if (PHRASE_ENABLED (have_proof)) pStr[0] = have_proof; else pStr[0] = look_at_egg_sacks; } else if (!GET_GAME_STATE (SYREEN_WANT_PROOF)) { pStr[0] = have_no_proof; } } switch (GET_GAME_STATE (SYREEN_STACK0)) { case 0: pStr[1] = what_doing_here; break; case 1: pStr[1] = what_about_war; break; case 2: pStr[1] = help_us; break; } switch (GET_GAME_STATE (SYREEN_STACK1)) { case 0: pStr[2] = what_about_history; break; case 1: pStr[2] = what_about_homeworld; break; case 2: pStr[2] = what_happened; break; } switch (GET_GAME_STATE (SYREEN_STACK2)) { case 0: pStr[3] = what_about_outfit; break; case 1: pStr[3] = where_mates; break; case 2: pStr[3] = get_lonely; break; } if (pStr[LastStack]) Response (pStr[LastStack], NormalSyreen); for (i = 0; i < 4; ++i) { if (i != LastStack && pStr[i]) Response (pStr[i], NormalSyreen); } Response (bye, FriendlyExit); } static void InitialSyreen (RESPONSE_REF R) { if (PLAYER_SAID (R, we_are_vice_squad)) { NPCPhrase (OK_VICE); NPCPhrase (HOW_CAN_YOU_BE_HERE); } else if (PLAYER_SAID (R, we_are_the_one_for_you_baby)) { NPCPhrase (MAYBE_CAPTAIN); NPCPhrase (HOW_CAN_YOU_BE_HERE); } else if (PLAYER_SAID (R, we_are_vindicator0)) { NPCPhrase (WELCOME_VINDICATOR0); if (speechVolumeScale == 0.0f) { NPCPhrase (GLOBAL_PLAYER_NAME); NPCPhrase (WELCOME_VINDICATOR1); NPCPhrase (GLOBAL_SHIP_NAME); NPCPhrase (WELCOME_VINDICATOR2); } NPCPhrase (HOW_CAN_YOU_BE_HERE); } else if (PLAYER_SAID (R, we_are_impressed)) { NPCPhrase (SO_AM_I_CAPTAIN); NPCPhrase (HOW_CAN_YOU_BE_HERE); } else if (PLAYER_SAID (R, i_need_you)) { NPCPhrase (OK_NEED); DISABLE_PHRASE (i_need_you); } else if (PLAYER_SAID (R, i_need_touch_o_vision)) { NPCPhrase (TOUCH_O_VISION); DISABLE_PHRASE (i_need_touch_o_vision); } Response (we_here_to_help, NormalSyreen); Response (we_need_help, NormalSyreen); if (PHRASE_ENABLED (i_need_you)) Response (i_need_you, InitialSyreen); if (PHRASE_ENABLED (i_need_touch_o_vision)) Response (i_need_touch_o_vision, InitialSyreen); } static void PlanAmbush (RESPONSE_REF R) { (void) R; // ignored NPCPhrase (OK_FOUND_VAULT); SET_GAME_STATE (MYCON_AMBUSH, 1); SET_GAME_STATE (SYREEN_HOME_VISITS, 0); Response (whats_my_reward, Foreplay); Response (bye_after_vault, FriendlyExit); } static void SyreenVault (RESPONSE_REF R) { if (PLAYER_SAID (R, vault_hint)) { NPCPhrase (OK_HINT); DISABLE_PHRASE (vault_hint); } if (PHRASE_ENABLED (vault_hint)) { Response (vault_hint, SyreenVault); } Response (bye_before_vault, FriendlyExit); } static void Intro (void) { BYTE NumVisits; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } NumVisits = GET_GAME_STATE (SYREEN_HOME_VISITS); if (GET_GAME_STATE (MYCON_KNOW_AMBUSH)) { switch (NumVisits++) { case 0: NPCPhrase (HELLO_AFTER_AMBUSH_1); ActivateStarShip (SYREEN_SHIP, 0); break; case 1: NPCPhrase (HELLO_AFTER_AMBUSH_2); break; case 2: NPCPhrase (HELLO_AFTER_AMBUSH_3); break; case 3: NPCPhrase (HELLO_AFTER_AMBUSH_3); --NumVisits; break; } AfterAmbush ((RESPONSE_REF)0); } else if (GET_GAME_STATE (MYCON_AMBUSH)) { switch (NumVisits++) { case 0: NPCPhrase (READY_FOR_AMBUSH); --NumVisits; break; } AmbushReady ((RESPONSE_REF)0); } else if (!GET_GAME_STATE (SYREEN_KNOW_ABOUT_MYCON)) { switch (NumVisits++) { case 0: NPCPhrase (HELLO_BEFORE_AMBUSH_1); break; case 1: NPCPhrase (HELLO_BEFORE_AMBUSH_2); break; case 2: NPCPhrase (HELLO_BEFORE_AMBUSH_3); break; case 3: NPCPhrase (HELLO_BEFORE_AMBUSH_4); --NumVisits; break; } if (NumVisits > 1) NormalSyreen ((RESPONSE_REF)0); else { construct_response (shared_phrase_buf, we_are_vindicator0, GLOBAL_SIS (CommanderName), we_are_vindicator1, GLOBAL_SIS (ShipName), we_are_vindicator2, NULL_PTR); Response (we_are_vice_squad, InitialSyreen); Response (we_are_the_one_for_you_baby, InitialSyreen); DoResponsePhrase (we_are_vindicator0, InitialSyreen, shared_phrase_buf); Response (we_are_impressed, InitialSyreen); } } #ifdef NEVER else if (!GET_GAME_STATE (SYREEN_SHUTTLE)) { switch (NumVisits++) { case 0: NPCPhrase (MUST_ACT); --NumVisits; break; } SyreenShuttle ((RESPONSE_REF)0); } #endif /* NEVER */ else if (GET_GAME_STATE (SHIP_VAULT_UNLOCKED)) { PlanAmbush ((RESPONSE_REF)0); } else { switch (NumVisits++) { case 0: NPCPhrase (FOUND_VAULT_YET_1); break; case 1: NPCPhrase (FOUND_VAULT_YET_2); --NumVisits; break; } SyreenVault ((RESPONSE_REF)0); } SET_GAME_STATE (SYREEN_HOME_VISITS, NumVisits); } static COUNT uninit_syreen (void) { return (0); } static void post_syreen_enc (void) { // nothing defined so far } LOCDATAPTR init_syreen_comm (void) { LOCDATAPTR retval; syreen_desc.init_encounter_func = Intro; syreen_desc.post_encounter_func = post_syreen_enc; syreen_desc.uninit_encounter_func = uninit_syreen; syreen_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); syreen_desc.AlienTextBaseline.y = 0; syreen_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; SET_GAME_STATE (BATTLE_SEGUE, 0); retval = &syreen_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/syreen/strings.h0000600000175000017500000000617310543202027017713 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, HELLO_BEFORE_AMBUSH_1, HELLO_BEFORE_AMBUSH_2, HELLO_BEFORE_AMBUSH_3, HELLO_BEFORE_AMBUSH_4, we_are_vice_squad, OK_VICE, we_are_the_one_for_you_baby, MAYBE_CAPTAIN, we_are_vindicator0, we_are_vindicator1, we_are_vindicator2, WELCOME_VINDICATOR0, WELCOME_VINDICATOR1, WELCOME_VINDICATOR2, we_are_impressed, SO_AM_I_CAPTAIN, HOW_CAN_YOU_BE_HERE, we_here_to_help, NO_NEED_HELP, we_need_help, CANT_GIVE_HELP, i_need_you, OK_NEED, i_need_touch_o_vision, TOUCH_O_VISION, know_about_deep_children, WHAT_ABOUT_DEEP_CHILDREN, mycons_involved, WHAT_PROOF, have_no_proof, NEED_PROOF, have_proof, SEE_PROOF, look_at_egg_sacks, HORRIBLE_TRUTH, what_doing_here, OUR_NEW_WORLD, what_about_war, ABOUT_WAR, help_us, WONT_HELP, what_about_history, BEFORE_WAR, what_about_homeworld, ABOUT_HOMEWORLD, what_happened, DONT_KNOW_HOW, what_about_outfit, HOPE_YOU_LIKE_IT, where_mates, MATES_KILLED, get_lonely, MAKE_OUT_ALL_RIGHT, bye, GOODBYE, MUST_ACT, whats_next_step, OPEN_VAULT, where_is_it, DONT_KNOW_WHERE, been_there, GREAT, GIVE_SHUTTLE, im_on_my_way, doing_this_for_you, if_i_die, GOOD_LUCK, OK_FOUND_VAULT, what_now, HERES_THE_PLAN, whats_my_reward, HERES_REWARD, bye_after_vault, GOODBYE_AFTER_VAULT, HELLO_AFTER_AMBUSH_1, HELLO_AFTER_AMBUSH_2, HELLO_AFTER_AMBUSH_3, HELLO_AFTER_AMBUSH_4, what_now_after_ambush, DO_THIS_AFTER_AMBUSH, what_about_you, ABOUT_ME, whats_up_after_ambush, GENERAL_INFO_AFTER_AMBUSH_1, GENERAL_INFO_AFTER_AMBUSH_2, GENERAL_INFO_AFTER_AMBUSH_3, GENERAL_INFO_AFTER_AMBUSH_4, bye_after_ambush, GOODBYE_AFTER_AMBUSH, FOUND_VAULT_YET_1, FOUND_VAULT_YET_2, vault_hint, OK_HINT, found_vault, bye_before_vault, GOODBYE_BEFORE_VAULT, what_do_i_get_for_this, GRATITUDE, not_sure, PLEASE, READY_FOR_AMBUSH, repeat_plan, OK_REPEAT_PLAN, bye_before_ambush, GOODBYE_BEFORE_AMBUSH, what_about_us, ABOUT_US, MORE_COMFORTABLE, in_the_spirit, OK_SPIRIT, what_in_mind, SOMETHING_LIKE_THIS, hands_off, OK_WONT_USE_HANDS, why_lights_off, LIGHTS_OFF_BECAUSE, evil_monster, NOT_EVIL_MONSTER, disease, JUST_RELAX, what_happens_if_i_touch_this, THIS_HAPPENS, are_you_sure_this_is_ok, YES_SURE, boy_they_never_taught, THEN_LET_ME_TEACH, not_much_more_to_say, THEN_STOP_TALKING, LATER, SEX_GOODBYE, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/syreen/igfxres.h0000600000175000017500000000004710543202027017663 0ustar joeyjoey#define SYREEN_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/syreen/istrtab.h0000600000175000017500000000012710543202027017663 0ustar joeyjoey#define SYREEN_CONVERSATION_PHRASES 0x00200004L #define SYREEN_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/syreen/imusicre.h0000600000175000017500000000004310543202027020030 0ustar joeyjoey#define SYREEN_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/syreen/Makeinfo0000600000175000017500000000002710543202027017515 0ustar joeyjoeyuqm_CFILES="syreenc.c" uqm-0.6.2/sc2/src/sc2code/comm/syreen/respkg.h0000600000175000017500000000003710543202027017506 0ustar joeyjoeyenum { SYREEN_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/syreen/resinst.h0000600000175000017500000000012610543202027017701 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/slyhome/0000755000175000017500000000000010552600275016234 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/slyhome/ifontres.h0000600000175000017500000000004510543202020020207 0ustar joeyjoey#define SLYLANDRO_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/slyhome/restypes.h0000600000175000017500000000024110543202020020232 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/slyhome/strings.h0000600000175000017500000000553010543202020020053 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, HELLO_1, HELLO_2, HELLO_3, HELLO_4, RECALL_PROGRAM_1, we_are_us0, we_are_us1, we_are_us2, TERRIBLY_EXCITING, happy_to_tell_more, TELL_MORE, would_you_like_to_know_more, YES_TELL_MORE, we_come_from_earth, OK_EARTH, we_explore, OK_EXPLORE, we_fight_urquan, URQUAN_NICE_GUYS, not_same_urquan, PERSONALITY_CHANGE, we_gather, MAYBE_INTERESTED, enough_about_me, OK_ENOUGH_YOU, what_other_visitors, VISITORS, any_other_visitors, LONG_AGO, what_about_sentient_milieu, MET_TAALO_THEY_ARE_FROM, who_else, PRECURSORS, precursors_yow, ABOUT_PRECURSORS, must_know_more, ALL_WE_KNOW, who_are_you, WE_ARE_SLY, like_more_about_you, SURE_KNOW_WHAT, what_about_home, ABOUT_HOME, what_about_culture, ABOUT_CULTURE, what_about_history, ABOUT_HISTORY, what_about_biology, ABOUT_BIOLOGY, enough_info, OK_ENOUGH_INFO, where_are_you, DOWN_HERE, thats_impossible_1, NO_ITS_NOT_1, thats_impossible_2, NO_ITS_NOT_2, bye, GOODBYE_1, GOODBYE_2, what_are_probes, PROBES_ARE, know_more_probe, OK_WHAT_MORE_PROBE, where_probes_from, PROBES_FROM_MELNORME, why_sell, SELL_FOR_INFO, how_long_ago, FIFTY_THOUSAND_ROTATIONS, whats_probes_mission, SEEK_OUT_NEW_LIFE, if_only_one, THEY_REPLICATE, enough_probe, OK_ENOUGH_PROBE, why_probe_always_attack, ONLY_DEFEND, talk_more_probe_attack, NO_PROBLEM_BUT_SURE, tell_me_about_basics, BASIC_COMMANDS, tell_basics_again, OK_BASICS_AGAIN, what_effect, AFFECTS_BEHAVIOR, how_does_probe_defend, ONLY_SELF_DEFENSE, combat_behavior, MISSILE_BATTERIES, what_missile_batteries, LIGHTNING_ONLY_FOR_HARVESTING, tell_me_about_rep_1, ABOUT_REP, what_set_priority, MAXIMUM, enough_problem, OK_ENOUGH_PROBLEM, probe_has_bug, NO_IT_DOESNT, tell_me_about_attack, ATTACK_NO_PROBLEM, tell_me_about_rep_2, REP_NO_PROBLEM, what_about_rep_priorities, MAXIMUM_SO_WHAT, think_about_rep_priorities, UH_OH, hunt_them_down, GROW_TOO_FAST, sue_melnorme, SIGNED_WAIVER, recall_signal, NOT_THIS_MODEL, mega_self_destruct, WHY_YES_THERE_IS, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/slyhome/igfxres.h0000600000175000017500000000005210543202020020023 0ustar joeyjoey#define SLYLANDRO_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/slyhome/istrtab.h0000600000175000017500000000013510543202020020026 0ustar joeyjoey#define SLYLANDRO_CONVERSATION_PHRASES 0x00200004L #define SLYLANDRO_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/slyhome/imusicre.h0000600000175000017500000000004610543202020020177 0ustar joeyjoey#define SLYLANDRO_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/slyhome/slyhome.c0000600000175000017500000004631710543202020020045 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gameev.h" #include "comm/commall.h" #include "comm/slyhome/resinst.h" #include "comm/slyhome/strings.h" static LOCDATA slylandro_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)SLYLANDRO_PMAP_ANIM, /* AlienFrame */ (FONT)SLYLANDRO_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)SLYLANDRO_COLOR_MAP, /* AlienColorMap */ SLYLANDRO_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ SLYLANDRO_CONVERSATION_PHRASES, /* PlayerPhrases */ 13, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 0, /* StartIndex */ 5, /* NumFrames */ RANDOM_ANIM | COLORXFORM_ANIM, /* AnimFlags */ ONE_SECOND / 8, ONE_SECOND * 5 / 8, /* FrameRate */ ONE_SECOND / 8, ONE_SECOND * 5 / 8, /* RestartRate */ 0, /* BlockMask */ }, { 1, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 6, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 11, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 16, /* StartIndex */ 6, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 22, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 15, 0, /* RestartRate */ 0, /* BlockMask */ }, { 30, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 8) | (1 << 9), /* BlockMask */ }, { 39, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 43, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 6), /* BlockMask */ }, { 48, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 6), /* BlockMask */ }, { 54, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 12), /* BlockMask */ }, { 60, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 12), /* BlockMask */ }, { 67, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 10) | (1 << 11), /* BlockMask */ }, }, { /* AlienTransitionDesc - empty */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc - empty */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void ExitConversation (RESPONSE_REF R) { (void) R; // ignored SET_GAME_STATE (BATTLE_SEGUE, 0); switch (GET_GAME_STATE (SLYLANDRO_HOME_VISITS)) { case 1: NPCPhrase (GOODBYE_1); break; default: NPCPhrase (GOODBYE_2); break; } } static void HomeWorld (RESPONSE_REF R); static void HumanInfo (RESPONSE_REF R) { BYTE InfoLeft; if (PLAYER_SAID (R, happy_to_tell_more)) { NPCPhrase (TELL_MORE); SET_GAME_STATE (SLYLANDRO_STACK4, 1); } else if (PLAYER_SAID (R, would_you_like_to_know_more)) { NPCPhrase (YES_TELL_MORE); } else if (PLAYER_SAID (R, we_come_from_earth)) { NPCPhrase (OK_EARTH); SET_GAME_STATE (SLYLANDRO_KNOW_EARTH, 1); } else if (PLAYER_SAID (R, we_explore)) { NPCPhrase (OK_EXPLORE); SET_GAME_STATE (SLYLANDRO_KNOW_EXPLORE, 1); } else if (PLAYER_SAID (R, we_fight_urquan)) { NPCPhrase (URQUAN_NICE_GUYS); SET_GAME_STATE (SLYLANDRO_KNOW_URQUAN, 1); } else if (PLAYER_SAID (R, not_same_urquan)) { NPCPhrase (PERSONALITY_CHANGE); SET_GAME_STATE (SLYLANDRO_KNOW_URQUAN, 2); } else if (PLAYER_SAID (R, we_gather)) { NPCPhrase (MAYBE_INTERESTED); SET_GAME_STATE (SLYLANDRO_KNOW_GATHER, 1); } InfoLeft = FALSE; if (GET_GAME_STATE (SLYLANDRO_KNOW_URQUAN) == 1) { InfoLeft = TRUE; Response (not_same_urquan, HumanInfo); } if (!GET_GAME_STATE (SLYLANDRO_KNOW_EARTH)) { InfoLeft = TRUE; Response (we_come_from_earth, HumanInfo); } if (!GET_GAME_STATE (SLYLANDRO_KNOW_EXPLORE)) { InfoLeft = TRUE; Response (we_explore, HumanInfo); } if (!GET_GAME_STATE (SLYLANDRO_KNOW_URQUAN)) { InfoLeft = TRUE; Response (we_fight_urquan, HumanInfo); } if (!GET_GAME_STATE (SLYLANDRO_KNOW_GATHER)) { InfoLeft = TRUE; Response (we_gather, HumanInfo); } Response (enough_about_me, HomeWorld); if (!InfoLeft) { SET_GAME_STATE (SLYLANDRO_STACK4, 2); } } static void SlylandroInfo (RESPONSE_REF R) { BYTE InfoLeft; if (PLAYER_SAID (R, like_more_about_you)) { NPCPhrase (SURE_KNOW_WHAT); } else if (PLAYER_SAID (R, what_about_home)) { NPCPhrase (ABOUT_HOME); DISABLE_PHRASE (what_about_home); } else if (PLAYER_SAID (R, what_about_culture)) { NPCPhrase (ABOUT_CULTURE); DISABLE_PHRASE (what_about_culture); } else if (PLAYER_SAID (R, what_about_history)) { NPCPhrase (ABOUT_HISTORY); DISABLE_PHRASE (what_about_history); } else if (PLAYER_SAID (R, what_about_biology)) { NPCPhrase (ABOUT_BIOLOGY); DISABLE_PHRASE (what_about_biology); } InfoLeft = FALSE; if (PHRASE_ENABLED (what_about_home)) { InfoLeft = TRUE; Response (what_about_home, SlylandroInfo); } if (PHRASE_ENABLED (what_about_culture)) { InfoLeft = TRUE; Response (what_about_culture, SlylandroInfo); } if (PHRASE_ENABLED (what_about_history)) { InfoLeft = TRUE; Response (what_about_history, SlylandroInfo); } if (PHRASE_ENABLED (what_about_biology)) { InfoLeft = TRUE; Response (what_about_biology, SlylandroInfo); } Response (enough_info, HomeWorld); if (!InfoLeft) { DISABLE_PHRASE (like_more_about_you); } } static void FixBug (RESPONSE_REF R) { if (PLAYER_SAID (R, think_about_rep_priorities)) NPCPhrase (UH_OH); else if (PLAYER_SAID (R, hunt_them_down)) { NPCPhrase (GROW_TOO_FAST); DISABLE_PHRASE (hunt_them_down); } else if (PLAYER_SAID (R, sue_melnorme)) { NPCPhrase (SIGNED_WAIVER); DISABLE_PHRASE (sue_melnorme); } else if (PLAYER_SAID (R, recall_signal)) { NPCPhrase (NOT_THIS_MODEL); DISABLE_PHRASE (recall_signal); } if (PHRASE_ENABLED (hunt_them_down)) Response (hunt_them_down, FixBug); if (PHRASE_ENABLED (sue_melnorme)) Response (sue_melnorme, FixBug); if (PHRASE_ENABLED (recall_signal)) Response (recall_signal, FixBug); Response (mega_self_destruct, HomeWorld); } static void ProbeBug (RESPONSE_REF R) { if (PLAYER_SAID (R, probe_has_bug)) NPCPhrase (NO_IT_DOESNT); else if (PLAYER_SAID (R, tell_me_about_rep_2)) { NPCPhrase (REP_NO_PROBLEM); DISABLE_PHRASE (tell_me_about_rep_2); } else if (PLAYER_SAID (R, what_about_rep_priorities)) { NPCPhrase (MAXIMUM_SO_WHAT); DISABLE_PHRASE (what_about_rep_priorities); } else if (PLAYER_SAID (R, tell_me_about_attack)) { NPCPhrase (ATTACK_NO_PROBLEM); DISABLE_PHRASE (tell_me_about_attack); } if (PHRASE_ENABLED (tell_me_about_rep_2)) Response (tell_me_about_rep_2, ProbeBug); else if (PHRASE_ENABLED (what_about_rep_priorities)) Response (what_about_rep_priorities, ProbeBug); else { Response (think_about_rep_priorities, FixBug); } if (PHRASE_ENABLED (tell_me_about_attack)) Response (tell_me_about_attack, ProbeBug); } static void ProbeInfo (RESPONSE_REF R); static void ProbeFunction (RESPONSE_REF R) { BYTE LastStack; RESPONSE_REF pStr[2]; LastStack = 0; pStr[0] = pStr[1] = 0; if (PLAYER_SAID (R, talk_more_probe_attack)) { NPCPhrase (NO_PROBLEM_BUT_SURE); } else if (PLAYER_SAID (R, tell_me_about_basics)) { NPCPhrase (BASIC_COMMANDS); SET_GAME_STATE (PLAYER_KNOWS_PROGRAM, 1); DISABLE_PHRASE (tell_basics_again); } else if (PLAYER_SAID (R, tell_basics_again)) { NPCPhrase (OK_BASICS_AGAIN); DISABLE_PHRASE (tell_basics_again); } else if (PLAYER_SAID (R, what_effect)) { NPCPhrase (AFFECTS_BEHAVIOR); SET_GAME_STATE (PLAYER_KNOWS_EFFECTS, 1); DISABLE_PHRASE (what_effect); } else if (PLAYER_SAID (R, tell_me_about_rep_1)) { NPCPhrase (ABOUT_REP); LastStack = 2; SET_GAME_STATE (SLYLANDRO_STACK8, 3); } else if (PLAYER_SAID (R, what_set_priority)) { NPCPhrase (MAXIMUM); SET_GAME_STATE (PLAYER_KNOWS_PRIORITY, 1); DISABLE_PHRASE (what_set_priority); } else if (PLAYER_SAID (R, how_does_probe_defend)) { NPCPhrase (ONLY_SELF_DEFENSE); LastStack = 1; SET_GAME_STATE (SLYLANDRO_STACK9, 1); } else if (PLAYER_SAID (R, combat_behavior)) { NPCPhrase (MISSILE_BATTERIES); LastStack = 1; SET_GAME_STATE (SLYLANDRO_STACK9, 2); } else if (PLAYER_SAID (R, what_missile_batteries)) { NPCPhrase (LIGHTNING_ONLY_FOR_HARVESTING); SET_GAME_STATE (SLYLANDRO_STACK9, 3); } switch (GET_GAME_STATE (SLYLANDRO_STACK9)) { case 0: pStr[0] = how_does_probe_defend; break; case 1: pStr[0] = combat_behavior; break; case 2: pStr[0] = what_missile_batteries; break; } switch (GET_GAME_STATE (SLYLANDRO_STACK8)) { case 2: pStr[1] = tell_me_about_rep_1; break; case 3: if (PHRASE_ENABLED (what_set_priority)) pStr[1] = what_set_priority; break; } if (LastStack && pStr[LastStack - 1]) Response (pStr[LastStack - 1], ProbeFunction); if (!GET_GAME_STATE (PLAYER_KNOWS_PROGRAM)) Response (tell_me_about_basics, ProbeFunction); else { if (GET_GAME_STATE (PLAYER_KNOWS_PRIORITY)) { if (GET_GAME_STATE (PLAYER_KNOWS_EFFECTS)) { Response (probe_has_bug, ProbeBug); } if (PHRASE_ENABLED (what_effect)) Response (what_effect, ProbeFunction); } if (PHRASE_ENABLED (tell_basics_again)) Response (tell_basics_again, ProbeFunction); } if (LastStack == 0) { do { if (pStr[LastStack]) Response (pStr[LastStack], ProbeFunction); } while (++LastStack < 2); } else { LastStack = (LastStack - 1) ^ 1; if (pStr[LastStack]) Response (pStr[LastStack], ProbeFunction); } Response (enough_problem, ProbeInfo); } static void ProbeInfo (RESPONSE_REF R) { BYTE i, LastStack, InfoLeft; RESPONSE_REF pStr[3]; LastStack = 0; pStr[0] = pStr[1] = pStr[2] = 0; if (PLAYER_SAID (R, what_are_probes)) { NPCPhrase (PROBES_ARE); SET_GAME_STATE (SLYLANDRO_STACK5, 1); } else if (PLAYER_SAID (R, know_more_probe)) NPCPhrase (OK_WHAT_MORE_PROBE); else if (PLAYER_SAID (R, why_probe_always_attack)) { NPCPhrase (ONLY_DEFEND); SET_GAME_STATE (SLYLANDRO_STACK6, 1); } else if (PLAYER_SAID (R, talk_more_probe_attack)) { ProbeFunction (R); return; } else if (PLAYER_SAID (R, where_probes_from)) { NPCPhrase (PROBES_FROM_MELNORME); LastStack = 1; SET_GAME_STATE (SLYLANDRO_STACK7, 1); } else if (PLAYER_SAID (R, why_sell)) { NPCPhrase (SELL_FOR_INFO); LastStack = 1; SET_GAME_STATE (SLYLANDRO_STACK7, 2); } else if (PLAYER_SAID (R, how_long_ago)) { NPCPhrase (FIFTY_THOUSAND_ROTATIONS); SET_GAME_STATE (SLYLANDRO_STACK7, 3); } else if (PLAYER_SAID (R, whats_probes_mission)) { NPCPhrase (SEEK_OUT_NEW_LIFE); LastStack = 2; SET_GAME_STATE (SLYLANDRO_STACK8, 1); } else if (PLAYER_SAID (R, if_only_one)) { NPCPhrase (THEY_REPLICATE); SET_GAME_STATE (SLYLANDRO_STACK8, 2); } else if (PLAYER_SAID (R, enough_problem)) NPCPhrase (OK_ENOUGH_PROBLEM); if (!GET_GAME_STATE (SLYLANDRO_KNOW_BROKEN) && GET_GAME_STATE (PROBE_EXHIBITED_BUG)) { switch (GET_GAME_STATE (SLYLANDRO_STACK6)) { case 0: pStr[0] = why_probe_always_attack; break; case 1: pStr[0] = talk_more_probe_attack; break; } } switch (GET_GAME_STATE (SLYLANDRO_STACK7)) { case 0: pStr[1] = where_probes_from; break; case 1: pStr[1] = why_sell; break; case 2: pStr[1] = how_long_ago; break; } switch (GET_GAME_STATE (SLYLANDRO_STACK8)) { case 0: pStr[2] = whats_probes_mission; break; case 1: pStr[2] = if_only_one; break; } InfoLeft = FALSE; if (pStr[LastStack]) { InfoLeft = TRUE; Response (pStr[LastStack], ProbeInfo); } for (i = 0; i < 3; ++i) { if (i != LastStack && pStr[i]) { InfoLeft = TRUE; Response (pStr[i], ProbeInfo); } } Response (enough_probe, HomeWorld); if (!InfoLeft) { DISABLE_PHRASE (know_more_probe); } } static void HomeWorld (RESPONSE_REF R) { BYTE i, LastStack; RESPONSE_REF pStr[3]; LastStack = 0; pStr[0] = pStr[1] = pStr[2] = 0; if (PLAYER_SAID (R, we_are_us0)) { NPCPhrase (TERRIBLY_EXCITING); SET_GAME_STATE (SLYLANDRO_STACK1, 1); DISABLE_PHRASE (we_are_us0); } else if (PLAYER_SAID (R, what_other_visitors)) { NPCPhrase (VISITORS); SET_GAME_STATE (PLAYER_KNOWS_PROBE, 1); SET_GAME_STATE (SLYLANDRO_STACK1, 2); } else if (PLAYER_SAID (R, any_other_visitors)) { NPCPhrase (LONG_AGO); SET_GAME_STATE (SLYLANDRO_STACK1, 3); } else if (PLAYER_SAID (R, what_about_sentient_milieu)) { NPCPhrase (MET_TAALO_THEY_ARE_FROM); SET_GAME_STATE (SLYLANDRO_STACK1, 4); } else if (PLAYER_SAID (R, who_else)) { NPCPhrase (PRECURSORS); SET_GAME_STATE (SLYLANDRO_STACK1, 5); } else if (PLAYER_SAID (R, precursors_yow)) { NPCPhrase (ABOUT_PRECURSORS); SET_GAME_STATE (SLYLANDRO_STACK1, 6); } else if (PLAYER_SAID (R, must_know_more)) { NPCPhrase (ALL_WE_KNOW); SET_GAME_STATE (SLYLANDRO_STACK1, 7); } else if (PLAYER_SAID (R, who_are_you)) { NPCPhrase (WE_ARE_SLY); LastStack = 1; SET_GAME_STATE (SLYLANDRO_STACK2, 1); } else if (PLAYER_SAID (R, where_are_you)) { NPCPhrase (DOWN_HERE); LastStack = 2; SET_GAME_STATE (SLYLANDRO_STACK3, 1); } else if (PLAYER_SAID (R, thats_impossible_1)) { NPCPhrase (NO_ITS_NOT_1); LastStack = 2; SET_GAME_STATE (SLYLANDRO_STACK3, 2); } else if (PLAYER_SAID (R, thats_impossible_2)) { NPCPhrase (NO_ITS_NOT_2); LastStack = 2; SET_GAME_STATE (SLYLANDRO_STACK3, 3); } else if (PLAYER_SAID (R, like_more_about_you)) { SlylandroInfo (R); return; } else if (PLAYER_SAID (R, enough_about_me)) NPCPhrase (OK_ENOUGH_YOU); else if (PLAYER_SAID (R, enough_info)) NPCPhrase (OK_ENOUGH_INFO); else if (PLAYER_SAID (R, enough_probe)) NPCPhrase (OK_ENOUGH_PROBE); else if (PLAYER_SAID (R, mega_self_destruct)) { NPCPhrase (WHY_YES_THERE_IS); SET_GAME_STATE (SLYLANDRO_KNOW_BROKEN, 1); SET_GAME_STATE (DESTRUCT_CODE_ON_SHIP, 1); i = GET_GAME_STATE (SLYLANDRO_MULTIPLIER) + 1; SET_GAME_STATE (SLYLANDRO_MULTIPLIER, i); AddEvent (RELATIVE_EVENT, 0, 0, 0, SLYLANDRO_RAMP_DOWN); } switch (GET_GAME_STATE (SLYLANDRO_STACK1)) { case 0: construct_response (shared_phrase_buf, we_are_us0, GLOBAL_SIS (CommanderName), we_are_us1, GLOBAL_SIS (ShipName), we_are_us2, NULL_PTR); pStr[0] = we_are_us0; break; case 1: pStr[0] = what_other_visitors; break; case 2: pStr[0] = any_other_visitors; break; case 3: pStr[0] = what_about_sentient_milieu; break; case 4: pStr[0] = who_else; break; case 5: pStr[0] = precursors_yow; break; case 6: pStr[0] = must_know_more; break; } switch (GET_GAME_STATE (SLYLANDRO_STACK2)) { case 0: pStr[1] = who_are_you; break; case 1: if (PHRASE_ENABLED (like_more_about_you)) pStr[1] = like_more_about_you; break; } switch (GET_GAME_STATE (SLYLANDRO_STACK3)) { case 0: pStr[2] = where_are_you; break; case 1: pStr[2] = thats_impossible_1; break; case 2: pStr[2] = thats_impossible_2; break; } if (pStr[LastStack]) { if (pStr[LastStack] != we_are_us0) Response (pStr[LastStack], HomeWorld); else DoResponsePhrase (pStr[LastStack], HomeWorld, shared_phrase_buf); } for (i = 0; i < 3; ++i) { if (i != LastStack && pStr[i]) { if (pStr[i] != we_are_us0) Response (pStr[i], HomeWorld); else DoResponsePhrase (pStr[i], HomeWorld, shared_phrase_buf); } } if (GET_GAME_STATE (SLYLANDRO_STACK1)) { switch (GET_GAME_STATE (SLYLANDRO_STACK4)) { case 0: Response (happy_to_tell_more, HumanInfo); break; case 1: Response (would_you_like_to_know_more, HumanInfo); break; } } if (GET_GAME_STATE (PLAYER_KNOWS_PROBE) && !GET_GAME_STATE (SLYLANDRO_KNOW_BROKEN)) { switch (GET_GAME_STATE (SLYLANDRO_STACK5)) { case 0: Response (what_are_probes, ProbeInfo); break; case 1: if (PHRASE_ENABLED (know_more_probe)) Response (know_more_probe, ProbeInfo); break; } } Response (bye, ExitConversation); } static void Intro (void) { BYTE NumVisits; if (GET_GAME_STATE (SLYLANDRO_KNOW_BROKEN) && (NumVisits = GET_GAME_STATE (RECALL_VISITS)) == 0) { NPCPhrase (RECALL_PROGRAM_1); ++NumVisits; SET_GAME_STATE (RECALL_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (SLYLANDRO_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_1); break; case 1: NPCPhrase (HELLO_2); break; case 2: NPCPhrase (HELLO_3); break; case 3: NPCPhrase (HELLO_4); --NumVisits; break; } SET_GAME_STATE (SLYLANDRO_HOME_VISITS, NumVisits); } HomeWorld ((RESPONSE_REF)0); } static COUNT uninit_slylandro (void) { return (0); } static void post_slylandro_enc (void) { // nothing defined so far } LOCDATAPTR init_slylandro_comm (void) { LOCDATAPTR retval; slylandro_desc.init_encounter_func = Intro; slylandro_desc.post_encounter_func = post_slylandro_enc; slylandro_desc.uninit_encounter_func = uninit_slylandro; slylandro_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); slylandro_desc.AlienTextBaseline.y = 0; slylandro_desc.AlienTextWidth = SIS_TEXT_WIDTH; SET_GAME_STATE (BATTLE_SEGUE, 0); retval = &slylandro_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/slyhome/Makeinfo0000600000175000017500000000002710543202020017661 0ustar joeyjoeyuqm_CFILES="slyhome.c" uqm-0.6.2/sc2/src/sc2code/comm/slyhome/respkg.h0000600000175000017500000000004210543202020017646 0ustar joeyjoeyenum { SLYLANDRO_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/slyhome/slyhome.res0000600000175000017500000000045710543202020020407 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/slyhome PACKAGE SLYLANDRO_PACKAGE slyhome.con GFXRES SLYLANDRO_PMAP_ANIM slyhome.ani FONTRES SLYLANDRO_FONT slyhome.fon MUSICRES SLYLANDRO_MUSIC slyhome.mod STRTAB SLYLANDRO_CONVERSATION_PHRASES slyhome.txt STRTAB SLYLANDRO_COLOR_MAP slyhome.ct uqm-0.6.2/sc2/src/sc2code/comm/slyhome/resinst.h0000600000175000017500000000012610543202020020045 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/orz/0000755000175000017500000000000010552600275015366 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/orz/ifontres.h0000600000175000017500000000003710543202032017345 0ustar joeyjoey#define ORZ_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/orz/restypes.h0000600000175000017500000000024110543202032017367 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/orz/orzc.c0000600000175000017500000004644510543202032016501 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/orz/resinst.h" #include "comm/orz/strings.h" #include "build.h" static LOCDATA orz_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)ORZ_PMAP_ANIM, /* AlienFrame */ (FONT)ORZ_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)ORZ_COLOR_MAP, /* AlienColorMap */ ORZ_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ ORZ_CONVERSATION_PHRASES, /* PlayerPhrases */ 12 /* 13 */, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 4, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 10, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 15, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 10, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 17, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 10, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 20, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND / 10, ONE_SECOND * 3, /* RestartRate */ (1 << 7), /* BlockMask */ }, { 22, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND / 10, ONE_SECOND * 3, /* RestartRate */ (1 << 6), /* BlockMask */ }, { 30, /* StartIndex */ 3, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND / 10, ONE_SECOND * 3, /* RestartRate */ (1 << 5), /* BlockMask */ }, { 33, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND / 10, ONE_SECOND * 3, /* RestartRate */ (1 << 4), /* BlockMask */ }, { 36, /* StartIndex */ 25, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 60, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 61, /* StartIndex */ 15, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 60, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 76, /* StartIndex */ 17, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 60, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 12), /* BlockMask */ }, { 93, /* StartIndex */ 25, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 60, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 118, /* StartIndex */ 11, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 60, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 10), /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 3, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND / 12, ONE_SECOND * 3 / 8, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (PLAYER_SAID (R, bye_ally)) NPCPhrase (GOODBYE_ALLY); else if (PLAYER_SAID (R, bye_neutral)) NPCPhrase (GOODBYE_NEUTRAL); else if (PLAYER_SAID (R, bye_angry)) NPCPhrase (GOODBYE_ANGRY); else if (PLAYER_SAID (R, bye_taalo)) { if (GET_GAME_STATE (ORZ_MANNER) == 1) NPCPhrase (ANGRY_TAALO_GOODBYE); else NPCPhrase (FRIENDLY_TAALO_GOODBYE); } else if (PLAYER_SAID (R, hostile_2)) { NPCPhrase (HOSTILITY_IS_BAD_2); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, may_we_land)) { NPCPhrase (SURE_LAND); SET_GAME_STATE (TAALO_UNPROTECTED, 1); } else if (PLAYER_SAID (R, yes_alliance) || PLAYER_SAID (R, were_sorry)) { if (PLAYER_SAID (R, yes_alliance)) NPCPhrase (GREAT); else NPCPhrase (APOLOGY_ACCEPTED); SET_GAME_STATE (ORZ_ANDRO_STATE, 0); SET_GAME_STATE (ORZ_GENERAL_INFO, 0); SET_GAME_STATE (ORZ_PERSONAL_INFO, 0); SET_GAME_STATE (ORZ_MANNER, 3); ActivateStarShip (ORZ_SHIP, 0); } else if (PLAYER_SAID (R, demand_to_land)) { NPCPhrase (NO_DEMAND); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, about_andro_3) || PLAYER_SAID (R, must_know_about_androsyn)) { if (PLAYER_SAID (R, about_andro_3)) NPCPhrase (BLEW_IT); else NPCPhrase (KNOW_TOO_MUCH); SET_GAME_STATE (ORZ_VISITS, 0); SET_GAME_STATE (ORZ_MANNER, 2); SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, about_andro_3)) ActivateStarShip (ORZ_SHIP, -1); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 1) ), ONE_SECOND / 2); } else /* insults */ { BYTE NumVisits; NumVisits = GET_GAME_STATE (ORZ_PERSONAL_INFO); switch (NumVisits++) { case 0: NPCPhrase (INSULTED_1); break; case 1: NPCPhrase (INSULTED_2); break; case 2: NPCPhrase (INSULTED_3); SET_GAME_STATE (BATTLE_SEGUE, 1); break; case 7: --NumVisits; default: NPCPhrase (INSULTED_4); SET_GAME_STATE (BATTLE_SEGUE, 1); break; } SET_GAME_STATE (ORZ_PERSONAL_INFO, NumVisits); } } static void TaaloWorld (RESPONSE_REF R) { // We can only get here when ORZ_MANNER != HOSTILE (2) BYTE Manner; Manner = GET_GAME_STATE (ORZ_MANNER); if (PLAYER_SAID (R, demand_to_land)) { NPCPhrase (ASK_NICELY); DISABLE_PHRASE (demand_to_land); } else if (PLAYER_SAID (R, why_you_here)) { if (Manner != 1) NPCPhrase (FRIENDLY_EXPLANATION); else NPCPhrase (ANGRY_EXPLANATION); DISABLE_PHRASE (why_you_here); } else if (PLAYER_SAID (R, what_is_this_place)) { if (Manner != 1) NPCPhrase (FRIENDLY_PLACE); else NPCPhrase (ANGRY_PLACE); DISABLE_PHRASE (what_is_this_place); } else if (PLAYER_SAID (R, may_we_land)) { NPCPhrase (ALLIES_CAN_VISIT); DISABLE_PHRASE (may_we_land); } else if (PLAYER_SAID (R, make_alliance)) { NPCPhrase (CANT_ALLY_HERE); DISABLE_PHRASE (make_alliance); } else if (PLAYER_SAID (R, why_busy)) { NPCPhrase (BUSY_BECAUSE); DISABLE_PHRASE (why_busy); } if (PHRASE_ENABLED (may_we_land)) { if (Manner == 3 && (ActivateStarShip ( ORZ_SHIP, CHECK_ALLIANCE ) & GOOD_GUY)) Response (may_we_land, ExitConversation); else Response (may_we_land, TaaloWorld); } else if (PHRASE_ENABLED (make_alliance)) Response (make_alliance, TaaloWorld); else if (PHRASE_ENABLED (why_busy)) Response (why_busy, TaaloWorld); if (PHRASE_ENABLED (demand_to_land)) { if (Manner == 1) Response (demand_to_land, ExitConversation); else Response (demand_to_land, TaaloWorld); } if (PHRASE_ENABLED (why_you_here)) Response (why_you_here, TaaloWorld); if (PHRASE_ENABLED (what_is_this_place)) Response (what_is_this_place, TaaloWorld); Response (bye_taalo, ExitConversation); } static void OrzAllied (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, whats_up_ally)) { NumVisits = GET_GAME_STATE (ORZ_GENERAL_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_ALLY_1); break; case 1: NPCPhrase (GENERAL_INFO_ALLY_2); break; case 2: NPCPhrase (GENERAL_INFO_ALLY_3); break; case 3: NPCPhrase (GENERAL_INFO_ALLY_4); --NumVisits; break; } SET_GAME_STATE (ORZ_GENERAL_INFO, NumVisits); DISABLE_PHRASE (whats_up_ally); } else if (PLAYER_SAID (R, more_about_you)) { NumVisits = GET_GAME_STATE (ORZ_PERSONAL_INFO); switch (NumVisits++) { case 0: NPCPhrase (ABOUT_US_1); break; case 1: NPCPhrase (ABOUT_US_2); break; case 2: NPCPhrase (ABOUT_US_3); break; case 3: NPCPhrase (ABOUT_US_4); --NumVisits; break; } SET_GAME_STATE (ORZ_PERSONAL_INFO, NumVisits); DISABLE_PHRASE (more_about_you); } else if (PLAYER_SAID (R, about_andro_1)) { NPCPhrase (FORGET_ANDRO_1); SET_GAME_STATE (ORZ_ANDRO_STATE, 1); } else if (PLAYER_SAID (R, about_andro_2)) { NPCPhrase (FORGET_ANDRO_2); SET_GAME_STATE (ORZ_ANDRO_STATE, 2); } if (GET_GAME_STATE (ORZ_ANDRO_STATE) == 0) Response (about_andro_1, OrzAllied); else if (GET_GAME_STATE (ORZ_ANDRO_STATE) == 1) Response (about_andro_2, OrzAllied); else { Response (about_andro_3, ExitConversation); } if (PHRASE_ENABLED (whats_up_ally)) Response (whats_up_ally, OrzAllied); if (PHRASE_ENABLED (more_about_you)) Response (more_about_you, OrzAllied); Response (bye_ally, ExitConversation); } static void OrzNeutral (RESPONSE_REF R); static void WhereAndrosyn (RESPONSE_REF R) { (void) R; // ignored NPCPhrase (DISEMBLE_ABOUT_ANDROSYN); DISABLE_PHRASE (where_androsyn); Response (must_know_about_androsyn, ExitConversation); Response (dont_really_care, OrzNeutral); } static void OfferAlliance (RESPONSE_REF R) { if (PLAYER_SAID (R, seem_like_nice_guys)) NPCPhrase (ARE_NICE_WANT_ALLY); else if (PLAYER_SAID (R, talk_about_alliance)) NPCPhrase (OK_TALK_ALLIANCE); else if (PLAYER_SAID (R, why_so_trusting)) { NPCPhrase (TRUSTING_BECAUSE); SET_GAME_STATE (ORZ_STACK1, 1); } Response (no_alliance, OrzNeutral); Response (decide_later, OrzNeutral); if (GET_GAME_STATE (ORZ_STACK1) == 0) { Response (why_so_trusting, OfferAlliance); } Response (yes_alliance, ExitConversation); } static void OrzNeutral (RESPONSE_REF R) { BYTE i, LastStack; RESPONSE_REF pStr[3]; LastStack = 0; pStr[0] = pStr[1] = pStr[2] = 0; if (PLAYER_SAID (R, hostile_1)) { NPCPhrase (HOSTILITY_IS_BAD_1); DISABLE_PHRASE (hostile_1); LastStack = 2; } else if (PLAYER_SAID (R, we_are_vindicator0)) { NPCPhrase (NICE_TO_MEET_YOU); SET_GAME_STATE (ORZ_STACK0, 1); LastStack = 1; } else if (PLAYER_SAID (R, who_you)) { NPCPhrase (WE_ARE_ORZ); SET_GAME_STATE (ORZ_ANDRO_STATE, 1); } else if (PLAYER_SAID (R, why_here)) { NPCPhrase (HERE_BECAUSE); SET_GAME_STATE (ORZ_ANDRO_STATE, 2); } else if (PLAYER_SAID (R, no_alliance)) { NPCPhrase (MAYBE_LATER); DISABLE_PHRASE (talk_about_alliance); SET_GAME_STATE (REFUSED_ORZ_ALLIANCE, 1); } else if (PLAYER_SAID (R, decide_later)) { NPCPhrase (OK_LATER); DISABLE_PHRASE (talk_about_alliance); SET_GAME_STATE (REFUSED_ORZ_ALLIANCE, 1); } else if (PLAYER_SAID (R, dont_really_care)) NPCPhrase (YOU_ARE_OUR_FRIENDS); else if (PLAYER_SAID (R, where_androsyn)) { WhereAndrosyn (R); return; } else if (PLAYER_SAID (R, talk_about_alliance) || PLAYER_SAID (R, seem_like_nice_guys)) { OfferAlliance (R); return; } else if (PLAYER_SAID (R, hostile_2)) { ExitConversation (R); return; } if (GET_GAME_STATE (ORZ_ANDRO_STATE) == 0) pStr[0] = who_you; else if (GET_GAME_STATE (ORZ_ANDRO_STATE) == 1) pStr[0] = why_here; else if (PHRASE_ENABLED (where_androsyn) && GET_GAME_STATE (ORZ_ANDRO_STATE) == 2) pStr[0] = where_androsyn; if (GET_GAME_STATE (REFUSED_ORZ_ALLIANCE)) { if (PHRASE_ENABLED (talk_about_alliance)) pStr[1] = talk_about_alliance; } else if (GET_GAME_STATE (ORZ_STACK0) == 0) { construct_response (shared_phrase_buf, we_are_vindicator0, GLOBAL_SIS (CommanderName), we_are_vindicator1, GLOBAL_SIS (ShipName), we_are_vindicator2, NULL_PTR); pStr[1] = we_are_vindicator0; } else pStr[1] = seem_like_nice_guys; if (PHRASE_ENABLED (hostile_1)) pStr[2] = hostile_1; else pStr[2] = hostile_2; if (pStr[LastStack]) { if (pStr[LastStack] != we_are_vindicator0) Response (pStr[LastStack], OrzNeutral); else DoResponsePhrase (pStr[LastStack], OrzNeutral, shared_phrase_buf); } for (i = 0; i < 3; ++i) { if (i != LastStack && pStr[i]) { if (pStr[i] != we_are_vindicator0) Response (pStr[i], OrzNeutral); else DoResponsePhrase (pStr[i], OrzNeutral, shared_phrase_buf); } } Response (bye_neutral, ExitConversation); } static void OrzAngry (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_up_angry)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (ORZ_GENERAL_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_ANGRY_1); break; case 1: NPCPhrase (GENERAL_INFO_ANGRY_2); --NumVisits; break; } SET_GAME_STATE (ORZ_GENERAL_INFO, NumVisits); DISABLE_PHRASE (whats_up_angry); } if (PHRASE_ENABLED (whats_up_angry)) { Response (whats_up_angry, OrzAngry); } Response (were_sorry, ExitConversation); switch (GET_GAME_STATE (ORZ_PERSONAL_INFO)) { case 0: Response (insult_1, ExitConversation); break; case 1: Response (insult_2, ExitConversation); break; case 2: Response (insult_3, ExitConversation); break; case 3: Response (insult_4, ExitConversation); break; case 4: Response (insult_5, ExitConversation); break; case 5: Response (insult_6, ExitConversation); break; case 6: Response (insult_7, ExitConversation); break; case 7: Response (insult_8, ExitConversation); break; } Response (bye_angry, ExitConversation); } static void Intro (void) { BYTE NumVisits, Manner; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (!GET_GAME_STATE (MET_ORZ_BEFORE)) NPCPhrase (INIT_HELLO); Manner = GET_GAME_STATE (ORZ_MANNER); if (Manner == 2) { CommData.AlienColorMap = SetAbsColorMapIndex (CommData.AlienColorMap, 1); NumVisits = GET_GAME_STATE (ORZ_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_HELLO_1); break; case 1: NPCPhrase (HOSTILE_HELLO_2); --NumVisits; break; } SET_GAME_STATE (ORZ_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { NumVisits = GET_GAME_STATE (TAALO_VISITS); if (Manner != 1) { switch (NumVisits++) { case 0: NPCPhrase (FRIENDLY_ALLIED_TAALO_HELLO_1); break; case 1: NPCPhrase (FRIENDLY_ALLIED_TAALO_HELLO_2); --NumVisits; break; } } else { switch (NumVisits++) { case 0: NPCPhrase (ANGRY_TAALO_HELLO_1); break; case 1: NPCPhrase (ANGRY_TAALO_HELLO_2); --NumVisits; break; } } SET_GAME_STATE (TAALO_VISITS, NumVisits); TaaloWorld ((RESPONSE_REF)0); } else if (Manner == 3 && (ActivateStarShip ( ORZ_SHIP, CHECK_ALLIANCE ) & GOOD_GUY)) { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (ORZ_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (ALLIED_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (ALLIED_HOMEWORLD_HELLO_2); break; case 2: NPCPhrase (ALLIED_HOMEWORLD_HELLO_3); break; case 3: NPCPhrase (ALLIED_HOMEWORLD_HELLO_4); --NumVisits; break; } SET_GAME_STATE (ORZ_HOME_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (ORZ_VISITS); switch (NumVisits++) { case 0: NPCPhrase (ALLIED_SPACE_HELLO_1); break; case 1: NPCPhrase (ALLIED_SPACE_HELLO_2); break; case 2: NPCPhrase (ALLIED_SPACE_HELLO_3); break; case 3: NPCPhrase (ALLIED_SPACE_HELLO_4); --NumVisits; break; } SET_GAME_STATE (ORZ_VISITS, NumVisits); } OrzAllied ((RESPONSE_REF)0); } else if (Manner != 1) { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (ORZ_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_2); break; case 2: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_3); break; case 3: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_4); --NumVisits; break; } SET_GAME_STATE (ORZ_HOME_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (ORZ_VISITS); switch (NumVisits++) { case 0: NPCPhrase (NEUTRAL_SPACE_HELLO_1); break; case 1: NPCPhrase (NEUTRAL_SPACE_HELLO_2); break; case 2: NPCPhrase (NEUTRAL_SPACE_HELLO_3); break; case 3: NPCPhrase (NEUTRAL_SPACE_HELLO_4); --NumVisits; break; } SET_GAME_STATE (ORZ_VISITS, NumVisits); } OrzNeutral ((RESPONSE_REF)0); } else { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (ORZ_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (ANGRY_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (ANGRY_HOMEWORLD_HELLO_2); --NumVisits; break; } SET_GAME_STATE (ORZ_HOME_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (ORZ_VISITS); switch (NumVisits++) { case 0: NPCPhrase (ANGRY_SPACE_HELLO_1); break; case 1: NPCPhrase (ANGRY_SPACE_HELLO_2); --NumVisits; break; } SET_GAME_STATE (ORZ_VISITS, NumVisits); } OrzAngry ((RESPONSE_REF)0); } if (!GET_GAME_STATE (MET_ORZ_BEFORE)) { BYTE N; SET_GAME_STATE (MET_ORZ_BEFORE, 1); N = CommData.AlienTalkDesc.NumFrames; CommData.AlienTalkDesc.NumFrames = 0; AlienTalkSegue (1); CommData.AlienTalkDesc.NumFrames = N; } } static COUNT uninit_orz (void) { return (0); } static void post_orz_enc (void) { BYTE Manner; if (GET_GAME_STATE (BATTLE_SEGUE) == 1 && (Manner = GET_GAME_STATE (ORZ_MANNER)) != 2) { SET_GAME_STATE (ORZ_MANNER, 1); if (Manner != 1) { SET_GAME_STATE (ORZ_VISITS, 0); SET_GAME_STATE (ORZ_HOME_VISITS, 0); SET_GAME_STATE (TAALO_VISITS, 0); } } } LOCDATAPTR init_orz_comm (void) { LOCDATAPTR retval; orz_desc.init_encounter_func = Intro; orz_desc.post_encounter_func = post_orz_enc; orz_desc.uninit_encounter_func = uninit_orz; orz_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); orz_desc.AlienTextBaseline.y = 0; orz_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if (GET_GAME_STATE (ORZ_MANNER) == 3 || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &orz_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/orz/strings.h0000600000175000017500000000562410543202032017214 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, INIT_HELLO, who_you, WE_ARE_ORZ, why_here, HERE_BECAUSE, ALLIED_HOMEWORLD_HELLO_1, ALLIED_HOMEWORLD_HELLO_2, ALLIED_HOMEWORLD_HELLO_3, ALLIED_HOMEWORLD_HELLO_4, ALLIED_SPACE_HELLO_1, ALLIED_SPACE_HELLO_2, ALLIED_SPACE_HELLO_3, ALLIED_SPACE_HELLO_4, whats_up_ally, GENERAL_INFO_ALLY_1, GENERAL_INFO_ALLY_2, GENERAL_INFO_ALLY_3, GENERAL_INFO_ALLY_4, more_about_you, ABOUT_US_1, ABOUT_US_2, ABOUT_US_3, ABOUT_US_4, where_androsyn, DISEMBLE_ABOUT_ANDROSYN, must_know_about_androsyn, KNOW_TOO_MUCH, dont_really_care, YOU_ARE_OUR_FRIENDS, about_andro_1, FORGET_ANDRO_1, about_andro_2, FORGET_ANDRO_2, about_andro_3, BLEW_IT, NEUTRAL_HOMEWORLD_HELLO_1, NEUTRAL_HOMEWORLD_HELLO_2, NEUTRAL_HOMEWORLD_HELLO_3, NEUTRAL_HOMEWORLD_HELLO_4, NEUTRAL_SPACE_HELLO_1, NEUTRAL_SPACE_HELLO_2, NEUTRAL_SPACE_HELLO_3, NEUTRAL_SPACE_HELLO_4, hostile_1, HOSTILITY_IS_BAD_1, hostile_2, HOSTILITY_IS_BAD_2, we_are_vindicator0, we_are_vindicator1, we_are_vindicator2, NICE_TO_MEET_YOU, seem_like_nice_guys, ARE_NICE_WANT_ALLY, talk_about_alliance, OK_TALK_ALLIANCE, yes_alliance, GREAT, no_alliance, MAYBE_LATER, decide_later, OK_LATER, why_so_trusting, TRUSTING_BECAUSE, bye_neutral, GOODBYE_NEUTRAL, ANGRY_SPACE_HELLO_1, ANGRY_SPACE_HELLO_2, ANGRY_HOMEWORLD_HELLO_1, ANGRY_HOMEWORLD_HELLO_2, whats_up_angry, GENERAL_INFO_ANGRY_1, GENERAL_INFO_ANGRY_2, were_sorry, APOLOGY_ACCEPTED, insult_1, insult_2, insult_3, insult_4, insult_5, insult_6, insult_7, insult_8, INSULTED_1, INSULTED_2, INSULTED_3, INSULTED_4, bye_angry, GOODBYE_ANGRY, ANGRY_TAALO_HELLO_1, ANGRY_TAALO_HELLO_2, FRIENDLY_ALLIED_TAALO_HELLO_1, FRIENDLY_ALLIED_TAALO_HELLO_2, demand_to_land, NO_DEMAND, ASK_NICELY, why_you_here, ANGRY_EXPLANATION, FRIENDLY_EXPLANATION, what_is_this_place, FRIENDLY_PLACE, ANGRY_PLACE, may_we_land, SURE_LAND, ALLIES_CAN_VISIT, make_alliance, CANT_ALLY_HERE, why_busy, BUSY_BECAUSE, bye_taalo, bye_ally, GOODBYE_ALLY, FRIENDLY_TAALO_GOODBYE, ANGRY_TAALO_GOODBYE, HOSTILE_HELLO_1, HOSTILE_HELLO_2, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/orz/igfxres.h0000600000175000017500000000004410543202032017161 0ustar joeyjoey#define ORZ_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/orz/istrtab.h0000600000175000017500000000012110543202032017156 0ustar joeyjoey#define ORZ_CONVERSATION_PHRASES 0x00200004L #define ORZ_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/orz/imusicre.h0000600000175000017500000000004010543202032017326 0ustar joeyjoey#define ORZ_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/orz/orz.res0000600000175000017500000000036210543202032016671 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/orz PACKAGE ORZ_PACKAGE orz.con GFXRES ORZ_PMAP_ANIM orz.ani FONTRES ORZ_FONT orz.fon MUSICRES ORZ_MUSIC orz.mod STRTAB ORZ_CONVERSATION_PHRASES orz.txt STRTAB ORZ_COLOR_MAP orz.ct uqm-0.6.2/sc2/src/sc2code/comm/orz/Makeinfo0000600000175000017500000000002410543202032017013 0ustar joeyjoeyuqm_CFILES="orzc.c" uqm-0.6.2/sc2/src/sc2code/comm/orz/respkg.h0000600000175000017500000000003410543202032017004 0ustar joeyjoeyenum { ORZ_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/orz/resinst.h0000600000175000017500000000012610543202032017202 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/chmmr/0000755000175000017500000000000010552600275015662 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/chmmr/ifontres.h0000600000175000017500000000004110543202030017632 0ustar joeyjoey#define CHMMR_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/chmmr/restypes.h0000600000175000017500000000024110543202030017661 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/chmmr/strings.h0000600000175000017500000000426310543202030017504 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, WHY_YOU_HERE_1, WHY_YOU_HERE_2, WHY_YOU_HERE_3, WHY_YOU_HERE_4, find_out_whats_up, HYBRID_PROCESS, need_help, CANT_HELP, why_no_help, LONG_TIME, what_if_more_energy, DANGER_TO_US, need_advice, WHAT_ADVICE, how_defeat_urquan, DEFEAT_LIKE_SO, what_about_tpet, SCARY_BUT_USEFUL, what_about_bomb, ABOUT_BOMB, what_about_sun_device, ABOUT_SUN_DEVICE, what_about_samatra, ABOUT_SAMATRA, enough_advice, OK_ENOUGH_ADVICE, bye_shielded, GOODBYE_SHIELDED, WE_ARE_FREE, WHO_ARE_YOU, i_am_captain0, i_am_captain1, i_am_captain2, i_am_savior, i_am_silly, WHY_HAVE_YOU_FREED_US, serious_1, serious_2, silly, WILL_HELP_ANALYZE_LOGS, YOU_KNOW_SAMATRA, DONT_KNOW_ABOUT_SAMATRA, NEED_DISTRACTION, HAVE_TALKING_PET, NEED_WEAPON, HAVE_BOMB, RETURN_WHEN_READY, YOU_ARE_READY, further_assistance, NO_FURTHER_ASSISTANCE, tech_help, USE_OUR_SHIPS_BEFORE, where_weapon, PRECURSOR_WEAPON, where_distraction, PSYCHIC_WEAPONRY, what_now, WE_WILL_IMPROVE_BOMB, MODIFY_VESSEL, wont_hurt_my_ship, WILL_DESTROY_IT, bummer_about_my_ship, DEAD_SILENCE, other_assistance, USE_OUR_SHIPS_AFTER, proceed, TAKE_2_WEEKS, HELLO_AFTER_BOMB_1, HELLO_AFTER_BOMB_2, whats_up_after_bomb, GENERAL_INFO_AFTER_BOMB_1, GENERAL_INFO_AFTER_BOMB_2, what_do_after_bomb, DO_AFTER_BOMB, bye_after_bomb, GOODBYE_AFTER_BOMB, bye, GOODBYE, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/chmmr/igfxres.h0000600000175000017500000000004610543202031017456 0ustar joeyjoey#define CHMMR_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/chmmr/chmmrc.c0000600000175000017500000003603510543202031017262 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/chmmr/resinst.h" #include "comm/chmmr/strings.h" #include "build.h" static LOCDATA chmmr_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)CHMMR_PMAP_ANIM, /* AlienFrame */ (FONT)CHMMR_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)CHMMR_COLOR_MAP, /* AlienColorMap */ CHMMR_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ CHMMR_CONVERSATION_PHRASES, /* PlayerPhrases */ 6, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 12, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 17, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 22, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 27, /* StartIndex */ 20, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 47, /* StartIndex */ 14, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 61, /* StartIndex */ 24, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 11, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 60, 0, /* FrameRate */ ONE_SECOND / 60, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (PLAYER_SAID (R, bye)) NPCPhrase (GOODBYE); else if (PLAYER_SAID (R, bye_shielded)) NPCPhrase (GOODBYE_SHIELDED); else if (PLAYER_SAID (R, bye_after_bomb)) NPCPhrase (GOODBYE_AFTER_BOMB); else if (PLAYER_SAID (R, proceed)) { int i; NPCPhrase (TAKE_2_WEEKS); ActivateStarShip (CHMMR_SHIP, 0); SET_GAME_STATE (CHMMR_HOME_VISITS, 0); SET_GAME_STATE (CHMMR_STACK, 0); SET_GAME_STATE (CHMMR_BOMB_STATE, 2); SET_GAME_STATE (UTWIG_BOMB_ON_SHIP, 0); GLOBAL_SIS (ResUnits) = 1000000L; GLOBAL_SIS (NumLanders) = 0; GLOBAL (ModuleCost[PLANET_LANDER]) = 0; #define EARTH_INDEX 2 /* earth is 3rd planet --> 3 - 1 = 2 */ /* Magic numbers for Earth */ #define EARTH_OUTER_X (-725) #define EARTH_OUTER_Y (597) #define EARTH_INNER_X (121) #define EARTH_INNER_Y (113) /* Magic numbers for Earth Starbase */ #define STARBASE_INNER_X (86) #define STARBASE_INNER_Y (113) /* transport player to Earth */ GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (SOL_X); GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (SOL_Y); GLOBAL (ShipStamp.frame) = (FRAME)MAKE_DWORD (1, EARTH_INDEX + 1); /* XXX : this should be unhardcoded eventually */ GLOBAL (ip_location.x) = EARTH_OUTER_X; GLOBAL (ip_location.y) = EARTH_OUTER_Y; if (GET_GAME_STATE (STARBASE_AVAILABLE)) { /* Normal game mode - you are transported to Starbase */ GLOBAL_SIS (FuelOnBoard) = FUEL_RESERVE; GLOBAL_SIS (CrewEnlisted) = 0; GLOBAL_SIS (TotalElementMass) = 0; GLOBAL (ModuleCost[STORAGE_BAY]) = 0; /* disable Storage Bay */ for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) GLOBAL_SIS (ElementAmounts[i]) = 0; for (i = NUM_BOMB_MODULES; i < NUM_MODULE_SLOTS; ++i) GLOBAL_SIS (ModuleSlots[i]) = EMPTY_SLOT + 2; /* XXX : this should be unhardcoded eventually */ /* transport to Starbase */ GLOBAL (ShipStamp.origin.x) = STARBASE_INNER_X - SAFE_X; GLOBAL (ShipStamp.origin.y) = STARBASE_INNER_Y - SAFE_Y; } else { /* 'Beating Game Differently' mode - never visited Starbase, * so you are transported to Earth */ /* compress the layout -- move all to front */ for (i = NUM_MODULE_SLOTS - 1; i > 0; --i) { int m; /* find next unused slot */ for (; i > 0 && GLOBAL_SIS (ModuleSlots[i]) != EMPTY_SLOT + 2; --i) ; if (i == 0) break; /* find next module to move */ for (m = i - 1; m >= 0 && GLOBAL_SIS (ModuleSlots[m]) == EMPTY_SLOT + 2; --m) ; if (m < 0) break; /* move the module */ GLOBAL_SIS (ModuleSlots[i]) = GLOBAL_SIS (ModuleSlots[m]); GLOBAL_SIS (ModuleSlots[m]) = EMPTY_SLOT + 2; } /* XXX : this should be unhardcoded eventually */ /* transport to Earth itself */ GLOBAL (ShipStamp.origin.x) = EARTH_INNER_X - SAFE_X; GLOBAL (ShipStamp.origin.y) = EARTH_INNER_Y - SAFE_Y; } /* install Chmmr-supplied modules */ for (i = 0; i < NUM_DRIVE_SLOTS; ++i) GLOBAL_SIS (DriveSlots[i]) = FUSION_THRUSTER; for (i = 0; i < NUM_JET_SLOTS; ++i) GLOBAL_SIS (JetSlots[i]) = TURNING_JETS; GLOBAL_SIS (ModuleSlots[0]) = BOMB_MODULE_4; GLOBAL_SIS (ModuleSlots[1]) = BOMB_MODULE_5; GLOBAL_SIS (ModuleSlots[2]) = BOMB_MODULE_3; GLOBAL_SIS (ModuleSlots[3]) = BOMB_MODULE_1; GLOBAL_SIS (ModuleSlots[4]) = BOMB_MODULE_0; GLOBAL_SIS (ModuleSlots[5]) = BOMB_MODULE_1; GLOBAL_SIS (ModuleSlots[6]) = BOMB_MODULE_3; GLOBAL_SIS (ModuleSlots[7]) = BOMB_MODULE_4; GLOBAL_SIS (ModuleSlots[8]) = BOMB_MODULE_5; GLOBAL_SIS (ModuleSlots[9]) = BOMB_MODULE_2; } } static void NotReady (RESPONSE_REF R) { if (R == 0) NPCPhrase (RETURN_WHEN_READY); else if (PLAYER_SAID (R, further_assistance)) { NPCPhrase (NO_FURTHER_ASSISTANCE); DISABLE_PHRASE (further_assistance); } else if (PLAYER_SAID (R, tech_help)) { NPCPhrase (USE_OUR_SHIPS_BEFORE); ActivateStarShip (CHMMR_SHIP, 0); } else if (PLAYER_SAID (R, where_weapon)) { NPCPhrase (PRECURSOR_WEAPON); DISABLE_PHRASE (where_weapon); } else if (PLAYER_SAID (R, where_distraction)) { NPCPhrase (PSYCHIC_WEAPONRY); DISABLE_PHRASE (where_distraction); } if (!(ActivateStarShip (CHMMR_SHIP, CHECK_ALLIANCE) & GOOD_GUY)) Response (tech_help, NotReady); else if (PHRASE_ENABLED (further_assistance)) Response (further_assistance, NotReady); if (PHRASE_ENABLED (where_weapon) && !GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) Response (where_weapon, NotReady); if (PHRASE_ENABLED (where_distraction) && !GET_GAME_STATE (TALKING_PET_ON_SHIP)) Response (where_distraction, NotReady); Response (bye, ExitConversation); } static void ImproveBomb (RESPONSE_REF R) { if (R == 0) NPCPhrase (WE_WILL_IMPROVE_BOMB); else if (PLAYER_SAID (R, what_now)) { NPCPhrase (MODIFY_VESSEL); DISABLE_PHRASE (what_now); } else if (PLAYER_SAID (R, wont_hurt_my_ship)) { NPCPhrase (WILL_DESTROY_IT); DISABLE_PHRASE (wont_hurt_my_ship); } else if (PLAYER_SAID (R, bummer_about_my_ship)) { NPCPhrase (DEAD_SILENCE); DISABLE_PHRASE (bummer_about_my_ship); } else if (PLAYER_SAID (R, other_assistance)) { NPCPhrase (USE_OUR_SHIPS_AFTER); ActivateStarShip (CHMMR_SHIP, 0); } if (PHRASE_ENABLED (what_now)) Response (what_now, ImproveBomb); else if (PHRASE_ENABLED (wont_hurt_my_ship)) Response (wont_hurt_my_ship, ImproveBomb); else if (PHRASE_ENABLED (bummer_about_my_ship)) Response (bummer_about_my_ship, ImproveBomb); if (!(ActivateStarShip (CHMMR_SHIP, CHECK_ALLIANCE) & GOOD_GUY)) Response (other_assistance, ImproveBomb); Response (proceed, ExitConversation); } static void ChmmrFree (RESPONSE_REF R) { if (R == 0 || PLAYER_SAID (R, i_am_captain0) || PLAYER_SAID (R, i_am_savior) || PLAYER_SAID (R, i_am_silly)) { NPCPhrase (WHY_HAVE_YOU_FREED_US); AlienTalkSegue ((COUNT)~0); SET_GAME_STATE (CHMMR_EMERGING, 0); Response (serious_1, ChmmrFree); Response (serious_2, ChmmrFree); Response (silly, ChmmrFree); } else { NPCPhrase (WILL_HELP_ANALYZE_LOGS); if (GET_GAME_STATE (AWARE_OF_SAMATRA)) NPCPhrase (YOU_KNOW_SAMATRA); else { NPCPhrase (DONT_KNOW_ABOUT_SAMATRA); SET_GAME_STATE (AWARE_OF_SAMATRA, 1); } if (GET_GAME_STATE (TALKING_PET_ON_SHIP)) NPCPhrase (HAVE_TALKING_PET); else NPCPhrase (NEED_DISTRACTION); if (GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) NPCPhrase (HAVE_BOMB); else NPCPhrase (NEED_WEAPON); if (!GET_GAME_STATE (TALKING_PET_ON_SHIP) || !GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) NotReady ((RESPONSE_REF)0); else ImproveBomb ((RESPONSE_REF)0); } } static void ChmmrShielded (RESPONSE_REF R); static void ChmmrAdvice (RESPONSE_REF R) { BYTE AdviceLeft; if (PLAYER_SAID (R, need_advice)) NPCPhrase (WHAT_ADVICE); else if (PLAYER_SAID (R, how_defeat_urquan)) { NPCPhrase (DEFEAT_LIKE_SO); SET_GAME_STATE (CHMMR_BOMB_STATE, 1); DISABLE_PHRASE (how_defeat_urquan); } else if (PLAYER_SAID (R, what_about_tpet)) { NPCPhrase (SCARY_BUT_USEFUL); DISABLE_PHRASE (what_about_tpet); } else if (PLAYER_SAID (R, what_about_bomb)) { NPCPhrase (ABOUT_BOMB); DISABLE_PHRASE (what_about_bomb); } else if (PLAYER_SAID (R, what_about_sun_device)) { NPCPhrase (ABOUT_SUN_DEVICE); DISABLE_PHRASE (what_about_sun_device); } else if (PLAYER_SAID (R, what_about_samatra)) { NPCPhrase (ABOUT_SUN_DEVICE); DISABLE_PHRASE (what_about_samatra); } AdviceLeft = 0; if (PHRASE_ENABLED (how_defeat_urquan)) { Response (how_defeat_urquan, ChmmrAdvice); AdviceLeft = TRUE; } if (PHRASE_ENABLED (what_about_tpet) && GET_GAME_STATE (TALKING_PET_ON_SHIP)) { Response (what_about_tpet, ChmmrAdvice); AdviceLeft = TRUE; } if (PHRASE_ENABLED (what_about_bomb) && GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) { Response (what_about_bomb, ChmmrAdvice); AdviceLeft = TRUE; } if (PHRASE_ENABLED (what_about_sun_device) && GET_GAME_STATE (SUN_DEVICE_ON_SHIP)) { Response (what_about_sun_device, ChmmrAdvice); AdviceLeft = TRUE; } if (PHRASE_ENABLED (what_about_samatra) && GET_GAME_STATE (AWARE_OF_SAMATRA)) { Response (what_about_samatra, ChmmrAdvice); AdviceLeft = TRUE; } Response (enough_advice, ChmmrShielded); if (!AdviceLeft) DISABLE_PHRASE (need_advice); } static void ChmmrShielded (RESPONSE_REF R) { if (PLAYER_SAID (R, find_out_whats_up)) { NPCPhrase (HYBRID_PROCESS); DISABLE_PHRASE (find_out_whats_up); } else if (PLAYER_SAID (R, need_help)) { NPCPhrase (CANT_HELP); SET_GAME_STATE (CHMMR_STACK, 1); } else if (PLAYER_SAID (R, why_no_help)) { NPCPhrase (LONG_TIME); SET_GAME_STATE (CHMMR_STACK, 2); } else if (PLAYER_SAID (R, what_if_more_energy)) { NPCPhrase (DANGER_TO_US); SET_GAME_STATE (CHMMR_STACK, 3); } else if (PLAYER_SAID (R, enough_advice)) NPCPhrase (OK_ENOUGH_ADVICE); switch (GET_GAME_STATE (CHMMR_STACK)) { case 0: Response (need_help, ChmmrShielded); break; case 1: Response (why_no_help, ChmmrShielded); break; case 2: Response (what_if_more_energy, ChmmrShielded); break; } if (PHRASE_ENABLED (find_out_whats_up)) Response (find_out_whats_up, ChmmrShielded); if (PHRASE_ENABLED (need_advice)) { Response (need_advice, ChmmrAdvice); } Response (bye_shielded, ExitConversation); } static void AfterBomb (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_up_after_bomb)) { if (GET_GAME_STATE (CHMMR_STACK)) NPCPhrase (GENERAL_INFO_AFTER_BOMB_2); else { NPCPhrase (GENERAL_INFO_AFTER_BOMB_1); SET_GAME_STATE (CHMMR_STACK, 1); } DISABLE_PHRASE (whats_up_after_bomb); } else if (PLAYER_SAID (R, what_do_after_bomb)) { NPCPhrase (DO_AFTER_BOMB); DISABLE_PHRASE (what_do_after_bomb); } if (PHRASE_ENABLED (whats_up_after_bomb)) Response (whats_up_after_bomb, AfterBomb); if (PHRASE_ENABLED (what_do_after_bomb)) Response (what_do_after_bomb, AfterBomb); Response (bye_after_bomb, ExitConversation); } static void Intro (void) { BYTE NumVisits; if (GET_GAME_STATE (CHMMR_BOMB_STATE) >= 2) { NumVisits = GET_GAME_STATE (CHMMR_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_AFTER_BOMB_1); break; case 1: NPCPhrase (HELLO_AFTER_BOMB_2); --NumVisits; break; } SET_GAME_STATE (CHMMR_HOME_VISITS, NumVisits); AfterBomb ((RESPONSE_REF)0); } else if (GET_GAME_STATE (CHMMR_UNLEASHED)) { if (!GET_GAME_STATE (TALKING_PET_ON_SHIP) || !GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) NotReady ((RESPONSE_REF)0); else { NPCPhrase (YOU_ARE_READY); ImproveBomb ((RESPONSE_REF)0); } } else { NumVisits = GET_GAME_STATE (CHMMR_HOME_VISITS); if (!GET_GAME_STATE (CHMMR_EMERGING)) { CommData.AlienColorMap = SetAbsColorMapIndex ( CommData.AlienColorMap, 1 ); switch (NumVisits++) { case 0: NPCPhrase (WHY_YOU_HERE_1); break; case 1: NPCPhrase (WHY_YOU_HERE_2); break; case 2: NPCPhrase (WHY_YOU_HERE_3); break; case 3: NPCPhrase (WHY_YOU_HERE_4); --NumVisits; break; } ChmmrShielded ((RESPONSE_REF)0); } else { NPCPhrase (WE_ARE_FREE); if (NumVisits) { ChmmrFree ((RESPONSE_REF)0); NumVisits = 0; } else { NPCPhrase (WHO_ARE_YOU); construct_response (shared_phrase_buf, i_am_captain0, GLOBAL_SIS (CommanderName), i_am_captain1, GLOBAL_SIS (ShipName), i_am_captain2, NULL_PTR); DoResponsePhrase (i_am_captain0, ChmmrFree, shared_phrase_buf); Response (i_am_savior, ChmmrFree); Response (i_am_silly, ChmmrFree); } SET_GAME_STATE (CHMMR_UNLEASHED, 1); } SET_GAME_STATE (CHMMR_HOME_VISITS, NumVisits); } } static COUNT uninit_chmmr (void) { return (0); } static void post_chmmr_enc (void) { // nothing defined so far } LOCDATAPTR init_chmmr_comm (void) { LOCDATAPTR retval; chmmr_desc.init_encounter_func = Intro; chmmr_desc.post_encounter_func = post_chmmr_enc; chmmr_desc.uninit_encounter_func = uninit_chmmr; chmmr_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); chmmr_desc.AlienTextBaseline.y = 0; chmmr_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; SET_GAME_STATE (BATTLE_SEGUE, 0); retval = &chmmr_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/chmmr/istrtab.h0000600000175000017500000000012510543202031017455 0ustar joeyjoey#define CHMMR_CONVERSATION_PHRASES 0x00200004L #define CHMMR_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/chmmr/imusicre.h0000600000175000017500000000004210543202030017622 0ustar joeyjoey#define CHMMR_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/chmmr/Makeinfo0000600000175000017500000000002610543202030017307 0ustar joeyjoeyuqm_CFILES="chmmrc.c" uqm-0.6.2/sc2/src/sc2code/comm/chmmr/chmmr.res0000600000175000017500000000041410543202031017456 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/chmmr PACKAGE CHMMR_PACKAGE chmmr.con GFXRES CHMMR_PMAP_ANIM chmmr.ani FONTRES CHMMR_FONT chmmr.fon MUSICRES CHMMR_MUSIC chmmr.mod STRTAB CHMMR_CONVERSATION_PHRASES chmmr.txt STRTAB CHMMR_COLOR_MAP chmmr.ct uqm-0.6.2/sc2/src/sc2code/comm/chmmr/respkg.h0000600000175000017500000000003610543202030017300 0ustar joeyjoeyenum { CHMMR_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/chmmr/resinst.h0000600000175000017500000000012610543202031017475 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/spathi/0000755000175000017500000000000010552600275016044 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/spathi/ifontres.h0000600000175000017500000000004210543202024020020 0ustar joeyjoey#define SPATHI_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/spathi/restypes.h0000600000175000017500000000024110543202024020046 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/spathi/strings.h0000600000175000017500000000645410543202024017675 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, SORRY_ABOUT_THAT, identify, I_FWIFFO, hi_there, ARE_YOU_SURE, dont_kill, we_fight_1, we_fight_2, OK_WONT, do_cultural, WEZZY_WEZZAH, die_slugboy, begin_ritual, MUST_DO_RITUAL_AT_HOME, you_wont_die_yet, ETERNAL_GRATITUDE, we_fight, pay_for_crimes, CLUTCH_MAVEN, you_may_live, HONEST_AND_FRIENDLY, what_are_coordinates, COORDINATES_ARE, tell_me_coordinates, FAKE_COORDINATES, TOO_SCARY, youve_got_me_all_wrong, SORRY_NO_COORDS, what_doing_on_pluto_1, ABOUT_20_YEARS_AGO, what_doing_on_pluto_2, WHEN_URQUAN_ARRIVED, where_are_urquan, URQUAN_LEFT, what_about_other_races, ABOUT_OTHER_RACES, what_doing_on_pluto_3, what_about_yourself, ABOUT_MYSELF, STATIONED_ON_EARTH_MOON, what_blaze_of_glory, BLAZE_IS, what_about_moonbase, SET_UP_BASE, what_about_ilwrath, ABOUT_ILWRATH, what_about_other_spathi, really_thousands, SPATHI_ARE, what_enemy, ENEMY_IS, when_ilwrath, THEN_ILWRATH, why_you_here, DREW_SHORT_STRAW, how_many_crew, JUST_ME, THOUSANDS, full_of_monsters, HOW_TRUE, join_us, WILL_JOIN, WONT_JOIN_1, give_ship_or_die, WONT_JOIN_2, WONT_JOIN_3, GEE_THANKS, changed_mind, youre_forgiven, THANKS_FOR_FORGIVENESS, HATE_YOU_FOREVER_SPACE, INIT_ANGRY_HELLO_SPACE, SUBSEQUENT_ANGRY_HELLO_SPACE, INIT_NEUTRAL_HELLO_SPACE, SUBSEQUENT_NEUTRAL_HELLO_SPACE, INIT_FRIENDLY_HELLO_SPACE, SUBSEQUENT_FRIENDLY_HELLO_SPACE, INIT_ALLIED_HELLO_SPACE, SUBSEQUENT_ALLIED_HELLO_SPACE, give_info_space, HERES_SOME_INFO, we_sorry_space, APOLOGIZE_AT_HOMEWORLD, we_fight_again_space, OK_FIGHT_AGAIN_SPACE, bye_angry_space, GOODBYE_ANGRY_SPACE, look_weird, YOU_LOOK_WEIRD, no_look_really_weird, NO_YOU_LOOK_REALLY_WEIRD, come_in_peace, AGAINST_NATURE, prepare_to_die, ALWAYS_PREPARED, since_friendly_give_stuff, GIVE_ADVICE, whats_up_space_1, GENERAL_INFO_SPACE_1, bye_friendly_space, GOODBYE_FRIENDLY_SPACE, looking_for_a_few_good_squids, URQUAN_SLAVES, why_slaves, UMGAH_TRICK, tell_us_about_you, ABOUT_US, what_you_really_want, WANT_THIS, how_about_alliance, SURE, part_in_peace, KEEP_IT_SECRET, heard_youre_cowards, DARN_TOOTIN, wanna_fight, YES_WE_DO, so_lets_fight, OK_LETS_FIGHT, so_lets_fight_already, DONT_REALLY_WANT_TO_FIGHT, attack_you_now, YIPES, whats_up_space_2, GENERAL_INFO_SPACE_2, give_us_info_from_space, GET_INFO_FROM_SPATHIWA, give_us_resources_space, GET_RESOURCES_FROM_SPATHIWA, what_do_for_fun, DO_THIS_FOR_FUN, bye_ally_space, GOODBYE_ALLY_SPACE, OK_WE_FIGHT_AT_PLUTO, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/spathi/igfxres.h0000600000175000017500000000012110543202024017634 0ustar joeyjoey#define SPATHI_PMAP_ANIM 0x00200002L #define SPATHI_HOME_PMAP_ANIM 0x00400102L uqm-0.6.2/sc2/src/sc2code/comm/spathi/spathi.res0000600000175000017500000000100210543202024020016 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/spathi PACKAGE SPATHI_ART_PACKAGE spathi.con GFXRES SPATHI_PMAP_ANIM spathi.ani FONTRES SPATHI_FONT spathi.fon STRTAB SPATHI_CONVERSATION_PHRASES spathi.txt PATH comm/spahome PACKAGE SPATHI_HOME_ART_PACKAGE spathi.con GFXRES SPATHI_HOME_PMAP_ANIM spahome.ani STRTAB SPATHI_HOME_COLOR_MAP spahome.ct STRTAB SPATHI_HOME_CONVERSATION_PHRASES spahome.txt PATH comm/spathi PACKAGE SPATHI_COMMON_PACKAGE spathi.con MUSICRES SPATHI_MUSIC spathi.mod uqm-0.6.2/sc2/src/sc2code/comm/spathi/istrtab.h0000600000175000017500000000026610543202024017647 0ustar joeyjoey#define SPATHI_CONVERSATION_PHRASES 0x00200004L #define SPATHI_HOME_COLOR_MAP 0x00400104L #define SPATHI_HOME_CONVERSATION_PHRASES 0x00400204L #define SPATHI_COLOR_MAP 0x00200304L uqm-0.6.2/sc2/src/sc2code/comm/spathi/imusicre.h0000600000175000017500000000014710543202024020015 0ustar joeyjoey#define SPATHI_MUSIC 0x00600006L #define SPAHOME_MUSIC 0x00800106L #define FWIFFO_MUSIC 0x00a00206L uqm-0.6.2/sc2/src/sc2code/comm/spathi/spathic.c0000600000175000017500000004622610543202024017633 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/spathi/resinst.h" #include "comm/spathi/strings.h" #include "build.h" static LOCDATA spathi_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)SPATHI_PMAP_ANIM, /* AlienFrame */ (FONT)SPATHI_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)SPATHI_COLOR_MAP, /* AlienColorMap */ SPATHI_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ SPATHI_CONVERSATION_PHRASES, /* PlayerPhrases */ 8, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 1, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ 0, ONE_SECOND, /* RestartRate */ (1 << 1), /* BlockMask */ }, { 7, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND / 20, 0, /* RestartRate */ (1 << 0), /* BlockMask */ }, { 16, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND / 10, ONE_SECOND / 15, /* RestartRate */ (1 << 4), /* BlockMask */ }, { 20, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ (1 << 5) }, { 24, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 2), /* BlockMask */ }, { 34, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 3), /* BlockMask */ }, { 38, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 41, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, #ifdef NEVER { /* AlienTalkDesc */ 29, /* StartIndex */ 5, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, #else { /* AlienTalkDesc - empty */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, #endif /* NEVER */ NULL_PTR, /* AlienNumberSpeech - none */ }; static void ExitConversation (RESPONSE_REF Response) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (PLAYER_SAID (Response, bye_ally_space)) NPCPhrase (GOODBYE_ALLY_SPACE); else if (PLAYER_SAID (Response, bye_friendly_space)) NPCPhrase (GOODBYE_FRIENDLY_SPACE); else if (PLAYER_SAID (Response, part_in_peace)) NPCPhrase (KEEP_IT_SECRET); else if (PLAYER_SAID (Response, we_sorry_space)) NPCPhrase (APOLOGIZE_AT_HOMEWORLD); else if (PLAYER_SAID (Response, give_info_space)) NPCPhrase (HERES_SOME_INFO); else if (PLAYER_SAID (Response, bye_angry_space)) NPCPhrase (GOODBYE_ANGRY_SPACE); else if (PLAYER_SAID (Response, attack_you_now)) { NPCPhrase (YIPES); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (Response, we_fight_again_space)) { NPCPhrase (OK_FIGHT_AGAIN_SPACE); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (Response, die_slugboy) || PLAYER_SAID (Response, we_fight_1) || PLAYER_SAID (Response, we_fight_2) || PLAYER_SAID (Response, pay_for_crimes) || PLAYER_SAID (Response, tell_me_coordinates) || PLAYER_SAID (Response, changed_mind)) { if (PLAYER_SAID (Response, tell_me_coordinates)) NPCPhrase (FAKE_COORDINATES); NPCPhrase (OK_WE_FIGHT_AT_PLUTO); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (Response, join_us)) { if (ActivateStarShip (SPATHI_SHIP, FEASIBILITY_STUDY) == 0) NPCPhrase (TOO_SCARY); else { NPCPhrase (WILL_JOIN); AlienTalkSegue ((COUNT)~0); ActivateStarShip (SPATHI_SHIP, 1); } } } static BYTE join_us_refusals; static void SpathiOnPluto (RESPONSE_REF R) { if (PLAYER_SAID (R, hi_there)) NPCPhrase (ARE_YOU_SURE); else if (PLAYER_SAID (R, dont_kill)) NPCPhrase (OK_WONT); else if (PLAYER_SAID (R, youre_forgiven)) NPCPhrase (THANKS_FOR_FORGIVENESS); else if (PLAYER_SAID (R, you_wont_die_yet)) NPCPhrase (ETERNAL_GRATITUDE); else if (PLAYER_SAID (R, you_may_live)) NPCPhrase (GEE_THANKS); else if (PLAYER_SAID (R, youve_got_me_all_wrong)) NPCPhrase (SORRY_NO_COORDS); else if (PLAYER_SAID (R, what_doing_on_pluto_1)) { NPCPhrase (ABOUT_20_YEARS_AGO); DISABLE_PHRASE (what_doing_on_pluto_1); } else if (PLAYER_SAID (R, what_doing_on_pluto_2)) { NPCPhrase (WHEN_URQUAN_ARRIVED); DISABLE_PHRASE (what_doing_on_pluto_2); } else if (PLAYER_SAID (R, what_doing_on_pluto_3)) { NPCPhrase (STATIONED_ON_EARTH_MOON); DISABLE_PHRASE (what_doing_on_pluto_3); } else if (PLAYER_SAID (R, what_about_ilwrath)) { NPCPhrase (ABOUT_ILWRATH); DISABLE_PHRASE (what_about_ilwrath); } else if (PLAYER_SAID (R, when_ilwrath)) { NPCPhrase (THEN_ILWRATH); DISABLE_PHRASE (when_ilwrath); } else if (PLAYER_SAID (R, what_about_moonbase)) { NPCPhrase (SET_UP_BASE); DISABLE_PHRASE (what_about_moonbase); } else if (PLAYER_SAID (R, what_about_other_spathi)) { NPCPhrase (SPATHI_ARE); DISABLE_PHRASE (what_about_other_spathi); } else if (PLAYER_SAID (R, what_about_other_spathi)) { NPCPhrase (THEN_ILWRATH); DISABLE_PHRASE (what_about_other_spathi); } else if (PLAYER_SAID (R, how_many_crew)) { NPCPhrase (THOUSANDS); DISABLE_PHRASE (how_many_crew); } else if (PLAYER_SAID (R, really_thousands)) { NPCPhrase (JUST_ME); DISABLE_PHRASE (really_thousands); } else if (PLAYER_SAID (R, full_of_monsters)) { NPCPhrase (HOW_TRUE); DISABLE_PHRASE (full_of_monsters); } else if (PLAYER_SAID (R, what_enemy)) { NPCPhrase (ENEMY_IS); DISABLE_PHRASE (what_enemy); } else if (PLAYER_SAID (R, why_you_here)) { NPCPhrase (DREW_SHORT_STRAW); DISABLE_PHRASE (why_you_here); } else if (PLAYER_SAID (R, where_are_urquan)) { NPCPhrase (URQUAN_LEFT); DISABLE_PHRASE (where_are_urquan); } else if (PLAYER_SAID (R, what_about_other_races)) { NPCPhrase (ABOUT_OTHER_RACES); DISABLE_PHRASE (what_about_other_races); } else if (PLAYER_SAID (R, what_blaze_of_glory)) { NPCPhrase (BLAZE_IS); DISABLE_PHRASE (what_blaze_of_glory); } else if (PLAYER_SAID (R, what_about_yourself)) { NPCPhrase (ABOUT_MYSELF); DISABLE_PHRASE (what_about_yourself); } else if (PLAYER_SAID (R, join_us)) { if (join_us_refusals == 0) { NPCPhrase (WONT_JOIN_1); ++join_us_refusals; } else if (join_us_refusals == 1) { NPCPhrase (WONT_JOIN_2); ++join_us_refusals; } else NPCPhrase (WONT_JOIN_3); } if (PHRASE_ENABLED (what_doing_on_pluto_1)) Response (what_doing_on_pluto_1, SpathiOnPluto); else if (PHRASE_ENABLED (what_doing_on_pluto_2)) Response (what_doing_on_pluto_2, SpathiOnPluto); else if (PHRASE_ENABLED (what_doing_on_pluto_3)) Response (what_doing_on_pluto_3, SpathiOnPluto); else { if (PHRASE_ENABLED (what_about_ilwrath)) Response (what_about_ilwrath, SpathiOnPluto); else if (PHRASE_ENABLED (when_ilwrath)) Response (when_ilwrath, SpathiOnPluto); if (PHRASE_ENABLED (what_about_moonbase)) Response (what_about_moonbase, SpathiOnPluto); else if (PHRASE_ENABLED (what_about_other_spathi)) Response (what_about_other_spathi, SpathiOnPluto); else { if (PHRASE_ENABLED (how_many_crew)) Response (how_many_crew, SpathiOnPluto); else if (PHRASE_ENABLED (really_thousands)) Response (really_thousands, SpathiOnPluto); else if (PHRASE_ENABLED (full_of_monsters)) Response (full_of_monsters, SpathiOnPluto); if (PHRASE_ENABLED (what_enemy)) Response (what_enemy, SpathiOnPluto); else if (PHRASE_ENABLED (why_you_here)) Response (why_you_here, SpathiOnPluto); } } if (PHRASE_ENABLED (where_are_urquan)) Response (where_are_urquan, SpathiOnPluto); else if (PHRASE_ENABLED (what_about_other_races)) Response (what_about_other_races, SpathiOnPluto); else if (PHRASE_ENABLED (what_blaze_of_glory)) Response (what_blaze_of_glory, SpathiOnPluto); else if (PHRASE_ENABLED (what_about_yourself)) Response (what_about_yourself, SpathiOnPluto); if (!PHRASE_ENABLED (full_of_monsters)) Response (join_us, ExitConversation); else Response (join_us, SpathiOnPluto); Response (changed_mind, ExitConversation); } static void SpathiMustGrovel (RESPONSE_REF R) { if (PLAYER_SAID (R, identify)) { NPCPhrase (I_FWIFFO); Response (do_cultural, SpathiMustGrovel); Response (youre_forgiven, SpathiOnPluto); Response (die_slugboy, ExitConversation); } else if (PLAYER_SAID (R, do_cultural)) { NPCPhrase (WEZZY_WEZZAH); Response (begin_ritual, SpathiMustGrovel); Response (you_wont_die_yet, SpathiOnPluto); Response (we_fight_2, ExitConversation); } else if (PLAYER_SAID (R, begin_ritual)) { NPCPhrase (MUST_DO_RITUAL_AT_HOME); Response (you_may_live, SpathiOnPluto); Response (pay_for_crimes, ExitConversation); Response (what_are_coordinates, SpathiMustGrovel); } else /* if (R == what_are_coordinates) */ { NPCPhrase (COORDINATES_ARE); Response (youve_got_me_all_wrong, SpathiOnPluto); Response (tell_me_coordinates, ExitConversation); } } static void SpathiAllies (RESPONSE_REF R) { if (R == 0) { BYTE NumVisits; NumVisits = GET_GAME_STATE (SPATHI_VISITS); switch (NumVisits++) { case 0: NPCPhrase (INIT_ALLIED_HELLO_SPACE); break; case 1: NPCPhrase (SUBSEQUENT_ALLIED_HELLO_SPACE); --NumVisits; break; } SET_GAME_STATE (SPATHI_VISITS, NumVisits); } else if (PLAYER_SAID (R, whats_up_space_2)) { NPCPhrase (GENERAL_INFO_SPACE_2); DISABLE_PHRASE (whats_up_space_2); } else if (PLAYER_SAID (R, give_us_info_from_space)) { NPCPhrase (GET_INFO_FROM_SPATHIWA); DISABLE_PHRASE (give_us_info_from_space); } else if (PLAYER_SAID (R, give_us_resources_space)) { NPCPhrase (GET_RESOURCES_FROM_SPATHIWA); DISABLE_PHRASE (give_us_resources_space); } else if (PLAYER_SAID (R, what_do_for_fun)) { NPCPhrase (DO_THIS_FOR_FUN); DISABLE_PHRASE (what_do_for_fun); } if (PHRASE_ENABLED (whats_up_space_2)) Response (whats_up_space_2, SpathiAllies); if (PHRASE_ENABLED (give_us_info_from_space)) Response (give_us_info_from_space, SpathiAllies); if (PHRASE_ENABLED (give_us_resources_space)) Response (give_us_resources_space, SpathiAllies); if (PHRASE_ENABLED (what_do_for_fun)) Response (what_do_for_fun, SpathiAllies); Response (bye_ally_space, ExitConversation); } static void SpathiFriendly (RESPONSE_REF R) { if (R == 0) { BYTE NumVisits; NumVisits = GET_GAME_STATE (SPATHI_VISITS); switch (NumVisits++) { case 0: NPCPhrase (INIT_FRIENDLY_HELLO_SPACE); break; case 1: NPCPhrase (SUBSEQUENT_FRIENDLY_HELLO_SPACE); --NumVisits; break; } SET_GAME_STATE (SPATHI_VISITS, NumVisits); } else if (PLAYER_SAID (R, since_friendly_give_stuff)) { NPCPhrase (GIVE_ADVICE); DISABLE_PHRASE (since_friendly_give_stuff); } else if (PLAYER_SAID (R, whats_up_space_1)) { NPCPhrase (GENERAL_INFO_SPACE_1); DISABLE_PHRASE (whats_up_space_1); } if (PHRASE_ENABLED (whats_up_space_1)) Response (whats_up_space_1, SpathiFriendly); if (PHRASE_ENABLED (since_friendly_give_stuff)) Response (since_friendly_give_stuff, SpathiFriendly); Response (bye_friendly_space, ExitConversation); } static void SpathiNeutral (RESPONSE_REF R); static void SpathiBefriend (RESPONSE_REF R) { BYTE InfoLeft, LastStack; RESPONSE_REF pStr[2]; InfoLeft = FALSE; LastStack = 0; pStr[0] = pStr[1] = 0; if (PLAYER_SAID (R, come_in_peace)) NPCPhrase (AGAINST_NATURE); else if (PLAYER_SAID (R, looking_for_a_few_good_squids)) { NPCPhrase (URQUAN_SLAVES); DISABLE_PHRASE (looking_for_a_few_good_squids); } else if (PLAYER_SAID (R, why_slaves)) { NPCPhrase (UMGAH_TRICK); DISABLE_PHRASE (why_slaves); } else if (PLAYER_SAID (R, tell_us_about_you)) { NPCPhrase (ABOUT_US); DISABLE_PHRASE (tell_us_about_you); LastStack = 1; } else if (PLAYER_SAID (R, what_you_really_want)) { NPCPhrase (WANT_THIS); DISABLE_PHRASE (what_you_really_want); } else if (PLAYER_SAID (R, how_about_alliance)) { NPCPhrase (SURE); DISABLE_PHRASE (how_about_alliance); } if (PHRASE_ENABLED (looking_for_a_few_good_squids)) pStr[0] = looking_for_a_few_good_squids; else if (PHRASE_ENABLED (why_slaves)) pStr[0] = why_slaves; if (PHRASE_ENABLED (tell_us_about_you)) pStr[1] = tell_us_about_you; else if (PHRASE_ENABLED (what_you_really_want)) pStr[1] = what_you_really_want; if (pStr[LastStack]) { InfoLeft = TRUE; Response (pStr[LastStack], SpathiBefriend); } LastStack ^= 1; if (pStr[LastStack]) { InfoLeft = TRUE; Response (pStr[LastStack], SpathiBefriend); } if (PHRASE_ENABLED (how_about_alliance)) { InfoLeft = TRUE; Response (how_about_alliance, SpathiBefriend); } if (!InfoLeft) { SET_GAME_STATE (SPATHI_STACK1, 1); SpathiNeutral (R); } } static void SpathiAntagonize (RESPONSE_REF R) { if (PLAYER_SAID (R, prepare_to_die)) { NPCPhrase (ALWAYS_PREPARED); SET_GAME_STATE (SPATHI_STACK2, 1); } else if (PLAYER_SAID (R, heard_youre_cowards)) { NPCPhrase (DARN_TOOTIN); DISABLE_PHRASE (heard_youre_cowards); } else if (PLAYER_SAID (R, wanna_fight)) { NPCPhrase (YES_WE_DO); DISABLE_PHRASE (wanna_fight); } else if (PLAYER_SAID (R, so_lets_fight)) { NPCPhrase (OK_LETS_FIGHT); DISABLE_PHRASE (so_lets_fight); } else if (PLAYER_SAID (R, so_lets_fight_already)) { NPCPhrase (DONT_REALLY_WANT_TO_FIGHT); DISABLE_PHRASE (so_lets_fight_already); } if (PHRASE_ENABLED (wanna_fight)) Response (wanna_fight, SpathiAntagonize); else if (PHRASE_ENABLED (so_lets_fight)) Response (so_lets_fight, SpathiAntagonize); else if (PHRASE_ENABLED (so_lets_fight_already)) Response (so_lets_fight_already, SpathiAntagonize); if (PHRASE_ENABLED (heard_youre_cowards)) Response (heard_youre_cowards, SpathiAntagonize); Response (attack_you_now, ExitConversation); } static void SpathiNeutral (RESPONSE_REF R) { if (R == 0) { BYTE NumVisits; NumVisits = GET_GAME_STATE (SPATHI_VISITS); switch (NumVisits++) { case 0: NPCPhrase (INIT_NEUTRAL_HELLO_SPACE); break; case 1: NPCPhrase (SUBSEQUENT_NEUTRAL_HELLO_SPACE); --NumVisits; break; } SET_GAME_STATE (SPATHI_VISITS, NumVisits); } else if (PLAYER_SAID (R, look_weird)) { NPCPhrase (YOU_LOOK_WEIRD); SET_GAME_STATE (SPATHI_STACK0, 1); } else if (PLAYER_SAID (R, no_look_really_weird)) { NPCPhrase (NO_YOU_LOOK_REALLY_WEIRD); SET_GAME_STATE (SPATHI_STACK0, 2); } switch (GET_GAME_STATE (SPATHI_STACK0)) { case 0: Response (look_weird, SpathiNeutral); break; case 1: Response (no_look_really_weird, SpathiNeutral); break; } if (GET_GAME_STATE (SPATHI_STACK1) == 0) { Response (come_in_peace, SpathiBefriend); } if (GET_GAME_STATE (SPATHI_STACK2) == 0) { Response (prepare_to_die, SpathiAntagonize); } else { Response (attack_you_now, ExitConversation); } Response (part_in_peace, ExitConversation); } static void Intro (void) { BYTE Manner; Manner = GET_GAME_STATE (SPATHI_MANNER); if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) { join_us_refusals = 0; NPCPhrase (SORRY_ABOUT_THAT); /* if already know password from Melnorme, * but haven't visited Spathiwa yet . . . */ if (GET_GAME_STATE (SPATHI_HOME_VISITS) == 7) { SET_GAME_STATE (KNOW_SPATHI_PASSWORD, 0); SET_GAME_STATE (SPATHI_HOME_VISITS, 0); } Response (identify, SpathiMustGrovel); Response (hi_there, SpathiOnPluto); Response (dont_kill, SpathiOnPluto); Response (we_fight_1, ExitConversation); } else if (Manner == 2) { NPCPhrase (HATE_YOU_FOREVER_SPACE); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (Manner == 1) { BYTE NumVisits; NumVisits = GET_GAME_STATE (SPATHI_VISITS); switch (NumVisits++) { case 0: NPCPhrase (INIT_ANGRY_HELLO_SPACE); break; case 1: NPCPhrase (SUBSEQUENT_ANGRY_HELLO_SPACE); --NumVisits; break; } SET_GAME_STATE (SPATHI_VISITS, NumVisits); Response (give_info_space, ExitConversation); Response (we_sorry_space,ExitConversation); Response (we_fight_again_space, ExitConversation); Response (bye_angry_space, ExitConversation); } else if (ActivateStarShip (SPATHI_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { SpathiAllies ((RESPONSE_REF)0); } else if (GET_GAME_STATE (SPATHI_QUEST)) { SpathiFriendly ((RESPONSE_REF)0); } else { SpathiNeutral ((RESPONSE_REF)0); } } static COUNT uninit_spathi (void) { return (0); } static void post_spathi_enc (void) { BYTE Manner; if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) { SET_GAME_STATE (FOUND_PLUTO_SPATHI, 2); } else if (GET_GAME_STATE (BATTLE_SEGUE) == 1 && (Manner = GET_GAME_STATE (SPATHI_MANNER)) != 2) { SET_GAME_STATE (SPATHI_MANNER, 1); if (Manner != 1) { SET_GAME_STATE (SPATHI_VISITS, 0); /* if don't know about Spathi via Melnorme . . . */ if (GET_GAME_STATE (SPATHI_HOME_VISITS) != 7) { SET_GAME_STATE (SPATHI_HOME_VISITS, 0); } } } } LOCDATAPTR init_spathi_comm (void) { LOCDATAPTR retval; spathi_desc.init_encounter_func = Intro; spathi_desc.post_encounter_func = post_spathi_enc; spathi_desc.uninit_encounter_func = uninit_spathi; spathi_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); spathi_desc.AlienTextBaseline.y = 0; spathi_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) { // use alternate Fwiffo track if available spathi_desc.AlienAltSong = FWIFFO_MUSIC; spathi_desc.AlienSongFlags |= LDASF_USE_ALTERNATE; } else { // regular track -- let's make sure spathi_desc.AlienSongFlags &= ~LDASF_USE_ALTERNATE; } if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1 || GET_GAME_STATE (SPATHI_MANNER) == 3 || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &spathi_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/spathi/Makeinfo0000600000175000017500000000002710543202024017475 0ustar joeyjoeyuqm_CFILES="spathic.c" uqm-0.6.2/sc2/src/sc2code/comm/spathi/respkg.h0000600000175000017500000000022010543202024017460 0ustar joeyjoeyenum { SPATHI_ART_PACKAGE = 1, SPATHI_HOME_ART_PACKAGE, SPATHI_COMMON_PACKAGE, SPATHI_HOME_MUSIC_PACKAGE, SPATHI_FWIFFO_MUSIC_PACKAGE, }; uqm-0.6.2/sc2/src/sc2code/comm/spathi/resinst.h0000600000175000017500000000012610543202024017661 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/0000755000175000017500000000000010552600275016076 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/zoqfot/ifontres.h0000600000175000017500000000004510543202021020052 0ustar joeyjoey#define ZOQFOTPIK_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/restypes.h0000600000175000017500000000024110543202021020075 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/zoqfot.res0000600000175000017500000000040010543202021020100 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/zoqfot PACKAGE ZOQFOTPIK_PACKAGE zoqfot.con GFXRES ZOQFOTPIK_PMAP_ANIM zoqfot.ani FONTRES ZOQFOTPIK_FONT zoqfot.fon MUSICRES ZOQFOTPIK_MUSIC zoqfot.mod STRTAB ZOQFOTPIK_CONVERSATION_PHRASES zoqfot.txt uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/strings.h0000600000175000017500000001417510543202021017723 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, WE_ARE0, WE_ARE1, WE_ARE2, WE_ARE3, WE_ARE4, WE_ARE5, WE_ARE6, WE_ARE7, SCOUT_HELLO0, SCOUT_HELLO1, SCOUT_HELLO2, SCOUT_HELLO3, INIT_HOME_HELLO0, INIT_HOME_HELLO1, INIT_HOME_HELLO2, INIT_HOME_HELLO3, which_fot, HE_IS0, HE_IS1, HE_IS2, HE_IS3, HE_IS4, HE_IS5, HE_IS6, HE_IS7, we_are_vindicator0, we_are_vindicator1, we_are_vindicator2, WE_GLAD0, WE_GLAD1, WE_GLAD2, WE_GLAD3, WE_GLAD4, WE_GLAD5, quiet_toadies, TOLD_YOU0, TOLD_YOU1, TOLD_YOU2, TOLD_YOU3, TOLD_YOU4, TOLD_YOU5, TOLD_YOU6, TOLD_YOU7, your_race, YEARS_AGO0, YEARS_AGO1, YEARS_AGO2, YEARS_AGO3, YEARS_AGO4, YEARS_AGO5, YEARS_AGO6, YEARS_AGO7, YEARS_AGO8, YEARS_AGO9, YEARS_AGO10, YEARS_AGO11, YEARS_AGO12, YEARS_AGO13, where_from, TRAVELED_FAR0, TRAVELED_FAR1, TRAVELED_FAR2, TRAVELED_FAR3, TRAVELED_FAR4, TRAVELED_FAR5, what_emergency, UNDER_ATTACK0, UNDER_ATTACK1, UNDER_ATTACK2, UNDER_ATTACK3, UNDER_ATTACK4, UNDER_ATTACK5, UNDER_ATTACK6, UNDER_ATTACK7, UNDER_ATTACK8, UNDER_ATTACK9, UNDER_ATTACK10, UNDER_ATTACK11, tough_luck, NOT_HELPFUL0, NOT_HELPFUL1, NOT_HELPFUL2, NOT_HELPFUL3, NOT_HELPFUL4, NOT_HELPFUL5, what_look_like, LOOK_LIKE0, LOOK_LIKE1, LOOK_LIKE2, LOOK_LIKE3, valuable_info, GOODBYE0, GOODBYE1, GOODBYE2, GOODBYE3, all_very_interesting, SEE_TOLD_YOU0, SEE_TOLD_YOU1, SEE_TOLD_YOU2, SEE_TOLD_YOU3, how_can_i_help, ALLY_WITH_US0, ALLY_WITH_US1, ALLY_WITH_US2, ALLY_WITH_US3, ALLY_WITH_US4, ALLY_WITH_US5, decide_later, PLEASE_HURRY0, PLEASE_HURRY1, EMMISSARIES0, EMMISSARIES1, EMMISSARIES2, EMMISSARIES3, EMMISSARIES4, EMMISSARIES5, EMMISSARIES6, EMMISSARIES7, sure, WE_ALLY0, WE_ALLY1, WE_ALLY2, WE_ALLY3, WE_ALLY4, WE_ALLY5, never, WE_ENEMIES0, WE_ENEMIES1, HOSTILE_HELLO_10, HOSTILE_HELLO_11, HOSTILE_HELLO_20, HOSTILE_HELLO_21, HOSTILE_HELLO_22, HOSTILE_HELLO_23, HOSTILE_HELLO_24, HOSTILE_HELLO_25, HOSTILE_HELLO_30, HOSTILE_HELLO_31, HOSTILE_HELLO_40, HOSTILE_HELLO_41, NEUTRAL_HOME_HELLO_10, NEUTRAL_HOME_HELLO_11, NEUTRAL_HOME_HELLO_12, NEUTRAL_HOME_HELLO_13, NEUTRAL_HOME_HELLO_20, NEUTRAL_HOME_HELLO_21, NEUTRAL_HOME_HELLO_22, NEUTRAL_HOME_HELLO_23, ALLIED_HOME_HELLO_10, ALLIED_HOME_HELLO_11, ALLIED_HOME_HELLO_12, ALLIED_HOME_HELLO_13, ALLIED_HOME_HELLO_20, ALLIED_HOME_HELLO_21, ALLIED_HOME_HELLO_22, ALLIED_HOME_HELLO_23, ALLIED_HOME_HELLO_24, ALLIED_HOME_HELLO_25, ALLIED_HOME_HELLO_26, ALLIED_HOME_HELLO_27, ALLIED_HOME_HELLO_30, ALLIED_HOME_HELLO_31, ALLIED_HOME_HELLO_40, ALLIED_HOME_HELLO_41, THANKS_FOR_RESCUE0, THANKS_FOR_RESCUE1, THANKS_FOR_RESCUE2, THANKS_FOR_RESCUE3, THANKS_FOR_RESCUE4, THANKS_FOR_RESCUE5, THANKS_FOR_RESCUE6, THANKS_FOR_RESCUE7, THANKS_FOR_RESCUE8, THANKS_FOR_RESCUE9, THANKS_FOR_RESCUE10, THANKS_FOR_RESCUE11, bye_homeworld, GOODBYE_HOME0, GOODBYE_HOME1, whats_up_homeworld, GENERAL_INFO_10, GENERAL_INFO_11, GENERAL_INFO_12, GENERAL_INFO_13, GENERAL_INFO_20, GENERAL_INFO_21, GENERAL_INFO_22, GENERAL_INFO_23, GENERAL_INFO_24, GENERAL_INFO_25, GENERAL_INFO_26, GENERAL_INFO_27, GENERAL_INFO_30, GENERAL_INFO_31, GENERAL_INFO_32, GENERAL_INFO_33, GENERAL_INFO_34, GENERAL_INFO_35, GENERAL_INFO_40, GENERAL_INFO_41, GENERAL_INFO_42, GENERAL_INFO_43, GENERAL_INFO_44, GENERAL_INFO_45, GENERAL_INFO_46, GENERAL_INFO_47, GENERAL_INFO_48, GENERAL_INFO_49, GENERAL_INFO_410, GENERAL_INFO_411, any_war_news, UTWIG_DELAY0, UTWIG_DELAY1, UTWIG_DELAY2, UTWIG_DELAY3, UTWIG_DELAY4, UTWIG_DELAY5, UTWIG_DELAY6, UTWIG_DELAY7, UTWIG_DELAY8, UTWIG_DELAY9, UTWIG_DELAY10, UTWIG_DELAY11, UTWIG_DELAY12, UTWIG_DELAY13, KOHRAH_WINNING0, KOHRAH_WINNING1, KOHRAH_WINNING2, KOHRAH_WINNING3, KOHRAH_WINNING4, KOHRAH_WINNING5, KOHRAH_WINNING6, KOHRAH_WINNING7, KOHRAH_WINNING8, KOHRAH_WINNING9, URQUAN_NEARLY_GONE0, URQUAN_NEARLY_GONE1, URQUAN_NEARLY_GONE2, URQUAN_NEARLY_GONE3, URQUAN_NEARLY_GONE4, URQUAN_NEARLY_GONE5, KOHRAH_FRENZY0, KOHRAH_FRENZY1, KOHRAH_FRENZY2, KOHRAH_FRENZY3, KOHRAH_FRENZY4, KOHRAH_FRENZY5, KOHRAH_FRENZY6, KOHRAH_FRENZY7, KOHRAH_FRENZY8, KOHRAH_FRENZY9, KOHRAH_FRENZY10, KOHRAH_FRENZY11, NO_WAR_NEWS0, NO_WAR_NEWS1, i_want_alliance, GOOD0, GOOD1, GOOD2, GOOD3, GOOD4, GOOD5, GOOD6, GOOD7, GOOD8, GOOD9, want_specific_info, WHAT_SPECIFIC_INFO0, WHAT_SPECIFIC_INFO1, enough_info, OK_ENOUGH_INFO, what_about_others, ABOUT_OTHERS0, ABOUT_OTHERS1, ABOUT_OTHERS2, ABOUT_OTHERS3, ABOUT_OTHERS4, ABOUT_OTHERS5, ABOUT_OTHERS6, ABOUT_OTHERS7, ABOUT_OTHERS8, ABOUT_OTHERS9, ABOUT_OTHERS10, ABOUT_OTHERS11, ABOUT_OTHERS12, ABOUT_OTHERS13, what_about_zebranky, ABOUT_ZEBRANKY0, ABOUT_ZEBRANKY1, ABOUT_ZEBRANKY2, ABOUT_ZEBRANKY3, ABOUT_ZEBRANKY4, ABOUT_ZEBRANKY5, ABOUT_ZEBRANKY6, ABOUT_ZEBRANKY7, what_about_past, ABOUT_PAST0, ABOUT_PAST1, ABOUT_PAST2, ABOUT_PAST3, ABOUT_PAST4, ABOUT_PAST5, ABOUT_PAST6, ABOUT_PAST7, ABOUT_PAST8, ABOUT_PAST9, ABOUT_PAST10, ABOUT_PAST11, what_about_stinger, ABOUT_STINGER0, ABOUT_STINGER1, ABOUT_STINGER2, ABOUT_STINGER3, ABOUT_STINGER4, ABOUT_STINGER5, what_about_guy_in_back, ABOUT_GUY0, ABOUT_GUY1, name_1, name_2, name_3, name_40, name_41, OUT_TAKES0, OUT_TAKES1, OUT_TAKES2, OUT_TAKES3, OUT_TAKES4, OUT_TAKES5, OUT_TAKES6, OUT_TAKES7, OUT_TAKES8, OUT_TAKES9, OUT_TAKES10, OUT_TAKES11, OUT_TAKES12, OUT_TAKES13, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/igfxres.h0000600000175000017500000000005210543202021017666 0ustar joeyjoey#define ZOQFOTPIK_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/istrtab.h0000600000175000017500000000013410543202021017670 0ustar joeyjoey#define ZOQFOTPIK_CONVERSATION_PHRASES 0x00200004L #define ZOQFOTPIK_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/imusicre.h0000600000175000017500000000004610543202021020042 0ustar joeyjoey#define ZOQFOTPIK_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/Makeinfo0000600000175000017500000000002710543202021017524 0ustar joeyjoeyuqm_CFILES="zoqfotc.c" uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/respkg.h0000600000175000017500000000004210543202021017511 0ustar joeyjoeyenum { ZOQFOTPIK_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/resinst.h0000600000175000017500000000012610543202021017710 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/zoqfot/zoqfotc.c0000600000175000017500000007150210543202021017707 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/zoqfot/resinst.h" #include "comm/zoqfot/strings.h" #include "build.h" #include "gameev.h" #define ZOQ_FG_COLOR WHITE_COLOR #define ZOQ_BG_COLOR BLACK_COLOR #define ZOQ_BASE_X (TEXT_X_OFFS + ((SIS_TEXT_WIDTH >> 1) >> 1)) #define ZOQ_BASE_Y 24 #define ZOQ_TALK_INDEX 18 #define ZOQ_TALK_FRAMES 5 #define FOT_TO_ZOQ 23 #define PIK_FG_COLOR WHITE_COLOR #define PIK_BG_COLOR BLACK_COLOR #define PIK_BASE_X (SIS_SCREEN_WIDTH - (TEXT_X_OFFS + ((SIS_TEXT_WIDTH >> 1) >> 1))) #define PIK_BASE_Y 24 #define PIK_TALK_INDEX 29 #define PIK_TALK_FRAMES 2 #define FOT_TO_PIK 26 static LOCDATA zoqfot_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)ZOQFOTPIK_PMAP_ANIM, /* AlienFrame */ (FONT)ZOQFOTPIK_FONT, /* AlienFont */ 0, /* AlienTextFColor */ 0, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_MIDDLE, /* AlienTextValign */ (COLORMAP)ZOQFOTPIK_COLOR_MAP, /* AlienColorMap */ ZOQFOTPIK_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ ZOQFOTPIK_CONVERSATION_PHRASES, /* PlayerPhrases */ 3, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { /* Eye blink */ 1, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM /* AnimFlags */ | WAIT_TALKING, ONE_SECOND / 24, 0, /* FrameRate */ 0, ONE_SECOND * 10, /* RestartRate */ 0, /* BlockMask */ }, { /* Blow smoke */ 5, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 7 / 120, 0, /* FrameRate */ ONE_SECOND * 2, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* Gulp */ 10, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ 0, ONE_SECOND * 10, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc - Move Eye */ FOT_TO_ZOQ, /* StartIndex */ 3, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ ZOQ_TALK_INDEX, /* StartIndex */ ZOQ_TALK_FRAMES, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; enum { ZOQ_ALIEN, FOT_ALIEN, PIK_ALIEN }; static int LastAlien; static void SelectAlienZOQ (void) { if (LastAlien != ZOQ_ALIEN) { LastAlien = ZOQ_ALIEN; CommData.AlienTransitionDesc.StartIndex = FOT_TO_ZOQ; CommData.AlienTalkDesc.AnimFlags |= TALK_INTRO; CommData.AlienTalkDesc.StartIndex = ZOQ_TALK_INDEX; CommData.AlienTalkDesc.NumFrames = ZOQ_TALK_FRAMES; CommData.AlienAmbientArray[1].AnimFlags &= ~WAIT_TALKING; CommData.AlienTextBaseline.x = (SWORD)ZOQ_BASE_X; CommData.AlienTextBaseline.y = ZOQ_BASE_Y; CommData.AlienTextFColor = ZOQ_FG_COLOR; CommData.AlienTextBColor = ZOQ_BG_COLOR; } } static void SelectAlienPIK (void) { if (LastAlien != PIK_ALIEN) { LastAlien = PIK_ALIEN; CommData.AlienTransitionDesc.StartIndex = FOT_TO_PIK; CommData.AlienTalkDesc.AnimFlags |= TALK_INTRO; CommData.AlienTalkDesc.StartIndex = PIK_TALK_INDEX; CommData.AlienTalkDesc.NumFrames = PIK_TALK_FRAMES; CommData.AlienAmbientArray[1].AnimFlags |= WAIT_TALKING; CommData.AlienTextBaseline.x = (SWORD)PIK_BASE_X; CommData.AlienTextBaseline.y = PIK_BASE_Y; CommData.AlienTextFColor = PIK_FG_COLOR; CommData.AlienTextBColor = PIK_BG_COLOR; } } static void ZFPTalkSegue (COUNT wait_track) { LastAlien = FOT_ALIEN; SelectAlienZOQ (); AlienTalkSegue (wait_track); } static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (PLAYER_SAID (R, bye_homeworld)) { NPCPhrase_cb (GOODBYE_HOME0, &SelectAlienZOQ); NPCPhrase_cb (GOODBYE_HOME1, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); } else if (PLAYER_SAID (R, decide_later)) { NPCPhrase_cb (PLEASE_HURRY0, &SelectAlienZOQ); NPCPhrase_cb (PLEASE_HURRY1, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); } else if (PLAYER_SAID (R, valuable_info)) { NPCPhrase_cb (GOODBYE0, &SelectAlienZOQ); NPCPhrase_cb (GOODBYE1, &SelectAlienPIK); NPCPhrase_cb (GOODBYE2, &SelectAlienZOQ); NPCPhrase_cb (GOODBYE3, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); } else if (PLAYER_SAID (R, how_can_i_help)) { NPCPhrase_cb (EMMISSARIES0, &SelectAlienZOQ); NPCPhrase_cb (EMMISSARIES1, &SelectAlienPIK); NPCPhrase_cb (EMMISSARIES2, &SelectAlienZOQ); NPCPhrase_cb (EMMISSARIES3, &SelectAlienPIK); NPCPhrase_cb (EMMISSARIES4, &SelectAlienZOQ); NPCPhrase_cb (EMMISSARIES5, &SelectAlienPIK); NPCPhrase_cb (EMMISSARIES6, &SelectAlienZOQ); NPCPhrase_cb (EMMISSARIES7, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); } else if (PLAYER_SAID (R, sure)) { NPCPhrase_cb (WE_ALLY0, &SelectAlienZOQ); NPCPhrase_cb (WE_ALLY1, &SelectAlienPIK); NPCPhrase_cb (WE_ALLY2, &SelectAlienZOQ); NPCPhrase_cb (WE_ALLY3, &SelectAlienPIK); NPCPhrase_cb (WE_ALLY4, &SelectAlienZOQ); NPCPhrase_cb (WE_ALLY5, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); ActivateStarShip (ZOQFOTPIK_SHIP, 0); AddEvent (RELATIVE_EVENT, 3, 0, 0, ZOQFOT_DISTRESS_EVENT); SET_GAME_STATE (ZOQFOT_HOME_VISITS, 0); } else if (PLAYER_SAID (R, all_very_interesting)) { NPCPhrase_cb (SEE_TOLD_YOU0, &SelectAlienZOQ); NPCPhrase_cb (SEE_TOLD_YOU1, &SelectAlienPIK); NPCPhrase_cb (SEE_TOLD_YOU2, &SelectAlienZOQ); NPCPhrase_cb (SEE_TOLD_YOU3, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); SET_GAME_STATE (ZOQFOT_HOSTILE, 1); SET_GAME_STATE (ZOQFOT_HOME_VISITS, 0); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, never)) { NPCPhrase_cb (WE_ENEMIES0, &SelectAlienZOQ); NPCPhrase_cb (WE_ENEMIES1, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); SET_GAME_STATE (ZOQFOT_HOME_VISITS, 0); SET_GAME_STATE (ZOQFOT_HOSTILE, 1); SET_GAME_STATE (BATTLE_SEGUE, 1); } } static void FormAlliance (RESPONSE_REF R) { (void) R; // ignored NPCPhrase_cb (ALLY_WITH_US0, &SelectAlienZOQ); NPCPhrase_cb (ALLY_WITH_US1, &SelectAlienPIK); NPCPhrase_cb (ALLY_WITH_US2, &SelectAlienZOQ); NPCPhrase_cb (ALLY_WITH_US3, &SelectAlienPIK); NPCPhrase_cb (ALLY_WITH_US4, &SelectAlienZOQ); NPCPhrase_cb (ALLY_WITH_US5, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); Response (sure, ExitConversation); Response (never, ExitConversation); Response (decide_later, ExitConversation); } static void ZoqFotIntro (RESPONSE_REF R) { if (PLAYER_SAID (R, we_are_vindicator0)) { NPCPhrase_cb (WE_GLAD0, &SelectAlienZOQ); NPCPhrase_cb (WE_GLAD1, &SelectAlienPIK); NPCPhrase_cb (WE_GLAD2, &SelectAlienZOQ); NPCPhrase_cb (WE_GLAD3, &SelectAlienPIK); NPCPhrase_cb (WE_GLAD4, &SelectAlienZOQ); NPCPhrase_cb (WE_GLAD5, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (we_are_vindicator0); } else if (PLAYER_SAID (R, your_race)) { NPCPhrase_cb (YEARS_AGO0, &SelectAlienZOQ); NPCPhrase_cb (YEARS_AGO1, &SelectAlienPIK); NPCPhrase_cb (YEARS_AGO2, &SelectAlienZOQ); NPCPhrase_cb (YEARS_AGO3, &SelectAlienPIK); NPCPhrase_cb (YEARS_AGO4, &SelectAlienZOQ); NPCPhrase_cb (YEARS_AGO5, &SelectAlienPIK); NPCPhrase_cb (YEARS_AGO6, &SelectAlienZOQ); NPCPhrase_cb (YEARS_AGO7, &SelectAlienPIK); NPCPhrase_cb (YEARS_AGO8, &SelectAlienZOQ); NPCPhrase_cb (YEARS_AGO9, &SelectAlienPIK); NPCPhrase_cb (YEARS_AGO10, &SelectAlienZOQ); NPCPhrase_cb (YEARS_AGO11, &SelectAlienPIK); NPCPhrase_cb (YEARS_AGO12, &SelectAlienZOQ); NPCPhrase_cb (YEARS_AGO13, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (your_race); } else if (PLAYER_SAID (R, where_from)) { NPCPhrase_cb (TRAVELED_FAR0, &SelectAlienZOQ); NPCPhrase_cb (TRAVELED_FAR1, &SelectAlienPIK); NPCPhrase_cb (TRAVELED_FAR2, &SelectAlienZOQ); NPCPhrase_cb (TRAVELED_FAR3, &SelectAlienPIK); NPCPhrase_cb (TRAVELED_FAR4, &SelectAlienZOQ); NPCPhrase_cb (TRAVELED_FAR5, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (where_from); } else if (PLAYER_SAID (R, what_emergency)) { NPCPhrase_cb (UNDER_ATTACK0, &SelectAlienZOQ); NPCPhrase_cb (UNDER_ATTACK1, &SelectAlienPIK); NPCPhrase_cb (UNDER_ATTACK2, &SelectAlienZOQ); NPCPhrase_cb (UNDER_ATTACK3, &SelectAlienPIK); NPCPhrase_cb (UNDER_ATTACK4, &SelectAlienZOQ); NPCPhrase_cb (UNDER_ATTACK5, &SelectAlienPIK); NPCPhrase_cb (UNDER_ATTACK6, &SelectAlienZOQ); NPCPhrase_cb (UNDER_ATTACK7, &SelectAlienPIK); NPCPhrase_cb (UNDER_ATTACK8, &SelectAlienZOQ); NPCPhrase_cb (UNDER_ATTACK9, &SelectAlienPIK); NPCPhrase_cb (UNDER_ATTACK10, &SelectAlienZOQ); NPCPhrase_cb (UNDER_ATTACK11, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (what_emergency); } else if (PLAYER_SAID (R, tough_luck)) { NPCPhrase_cb (NOT_HELPFUL0, &SelectAlienZOQ); NPCPhrase_cb (NOT_HELPFUL1, &SelectAlienPIK); NPCPhrase_cb (NOT_HELPFUL2, &SelectAlienZOQ); NPCPhrase_cb (NOT_HELPFUL3, &SelectAlienPIK); NPCPhrase_cb (NOT_HELPFUL4, &SelectAlienZOQ); NPCPhrase_cb (NOT_HELPFUL5, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (tough_luck); } else if (PLAYER_SAID (R, what_look_like)) { NPCPhrase_cb (LOOK_LIKE0, &SelectAlienZOQ); NPCPhrase_cb (LOOK_LIKE1, &SelectAlienPIK); NPCPhrase_cb (LOOK_LIKE2, &SelectAlienZOQ); NPCPhrase_cb (LOOK_LIKE3, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (what_look_like); } if (PHRASE_ENABLED (your_race) || PHRASE_ENABLED (where_from) || PHRASE_ENABLED (what_emergency)) { if (PHRASE_ENABLED (your_race)) Response (your_race, ZoqFotIntro); if (PHRASE_ENABLED (where_from)) Response (where_from, ZoqFotIntro); if (PHRASE_ENABLED (what_emergency)) Response (what_emergency, ZoqFotIntro); } else { if (PHRASE_ENABLED (tough_luck)) Response (tough_luck, ZoqFotIntro); if (PHRASE_ENABLED (what_look_like)) Response (what_look_like, ZoqFotIntro); Response (all_very_interesting, ExitConversation); if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { Response (how_can_i_help, FormAlliance); } else { Response (how_can_i_help, ExitConversation); } Response (valuable_info, ExitConversation); } } static void AquaintZoqFot (RESPONSE_REF R) { if (PLAYER_SAID (R, which_fot)) { NPCPhrase_cb (HE_IS0, &SelectAlienZOQ); NPCPhrase_cb (HE_IS1, &SelectAlienPIK); NPCPhrase_cb (HE_IS2, &SelectAlienZOQ); NPCPhrase_cb (HE_IS3, &SelectAlienPIK); NPCPhrase_cb (HE_IS4, &SelectAlienZOQ); NPCPhrase_cb (HE_IS5, &SelectAlienPIK); NPCPhrase_cb (HE_IS6, &SelectAlienZOQ); NPCPhrase_cb (HE_IS7, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (which_fot); } else if (PLAYER_SAID (R, quiet_toadies)) { NPCPhrase_cb (TOLD_YOU0, &SelectAlienZOQ); NPCPhrase_cb (TOLD_YOU1, &SelectAlienPIK); NPCPhrase_cb (TOLD_YOU2, &SelectAlienZOQ); NPCPhrase_cb (TOLD_YOU3, &SelectAlienPIK); NPCPhrase_cb (TOLD_YOU4, &SelectAlienZOQ); NPCPhrase_cb (TOLD_YOU5, &SelectAlienPIK); NPCPhrase_cb (TOLD_YOU6, &SelectAlienZOQ); NPCPhrase_cb (TOLD_YOU7, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (quiet_toadies); } if (PHRASE_ENABLED (we_are_vindicator0)) { UNICODE buf[ALLIANCE_NAME_BUFSIZE]; GetAllianceName (buf, name_1); construct_response ( shared_phrase_buf, we_are_vindicator0, buf, we_are_vindicator1, GLOBAL_SIS (ShipName), we_are_vindicator2, NULL_PTR ); } if (PHRASE_ENABLED (which_fot)) Response (which_fot, AquaintZoqFot); if (PHRASE_ENABLED (we_are_vindicator0)) DoResponsePhrase (we_are_vindicator0, ZoqFotIntro, shared_phrase_buf); if (PHRASE_ENABLED (quiet_toadies)) Response (quiet_toadies, AquaintZoqFot); Response (all_very_interesting, ExitConversation); Response (valuable_info, ExitConversation); } static void ZoqFotHome (RESPONSE_REF R); static void ZoqFotInfo (RESPONSE_REF R) { BYTE InfoLeft; if (PLAYER_SAID (R, want_specific_info)) { NPCPhrase_cb (WHAT_SPECIFIC_INFO0, &SelectAlienZOQ); NPCPhrase_cb (WHAT_SPECIFIC_INFO1, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); } else if (PLAYER_SAID (R, what_about_others)) { NPCPhrase_cb (ABOUT_OTHERS0, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_OTHERS1, &SelectAlienPIK); NPCPhrase_cb (ABOUT_OTHERS2, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_OTHERS3, &SelectAlienPIK); NPCPhrase_cb (ABOUT_OTHERS4, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_OTHERS5, &SelectAlienPIK); NPCPhrase_cb (ABOUT_OTHERS6, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_OTHERS7, &SelectAlienPIK); NPCPhrase_cb (ABOUT_OTHERS8, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_OTHERS9, &SelectAlienPIK); NPCPhrase_cb (ABOUT_OTHERS10, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_OTHERS11, &SelectAlienPIK); NPCPhrase_cb (ABOUT_OTHERS12, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_OTHERS13, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (what_about_others); } else if (PLAYER_SAID (R, what_about_zebranky)) { NPCPhrase_cb (ABOUT_ZEBRANKY0, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_ZEBRANKY1, &SelectAlienPIK); NPCPhrase_cb (ABOUT_ZEBRANKY2, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_ZEBRANKY3, &SelectAlienPIK); NPCPhrase_cb (ABOUT_ZEBRANKY4, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_ZEBRANKY5, &SelectAlienPIK); NPCPhrase_cb (ABOUT_ZEBRANKY6, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_ZEBRANKY7, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (what_about_zebranky); } else if (PLAYER_SAID (R, what_about_stinger)) { NPCPhrase_cb (ABOUT_STINGER0, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_STINGER1, &SelectAlienPIK); NPCPhrase_cb (ABOUT_STINGER2, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_STINGER3, &SelectAlienPIK); NPCPhrase_cb (ABOUT_STINGER4, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_STINGER5, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (what_about_stinger); } else if (PLAYER_SAID (R, what_about_guy_in_back)) { NPCPhrase_cb (ABOUT_GUY0, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_GUY1, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (what_about_guy_in_back); } else if (PLAYER_SAID (R, what_about_past)) { NPCPhrase_cb (ABOUT_PAST0, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_PAST1, &SelectAlienPIK); NPCPhrase_cb (ABOUT_PAST2, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_PAST3, &SelectAlienPIK); NPCPhrase_cb (ABOUT_PAST4, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_PAST5, &SelectAlienPIK); NPCPhrase_cb (ABOUT_PAST6, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_PAST7, &SelectAlienPIK); NPCPhrase_cb (ABOUT_PAST8, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_PAST9, &SelectAlienPIK); NPCPhrase_cb (ABOUT_PAST10, &SelectAlienZOQ); NPCPhrase_cb (ABOUT_PAST11, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); DISABLE_PHRASE (what_about_past); } InfoLeft = FALSE; if (PHRASE_ENABLED (what_about_others)) { Response (what_about_others, ZoqFotInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_zebranky)) { Response (what_about_zebranky, ZoqFotInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_stinger)) { Response (what_about_stinger, ZoqFotInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_guy_in_back)) { Response (what_about_guy_in_back, ZoqFotInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_past)) { Response (what_about_past, ZoqFotInfo); InfoLeft = TRUE; } Response (enough_info, ZoqFotHome); if (!InfoLeft) { DISABLE_PHRASE (want_specific_info); } } static void ZoqFotHome (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, whats_up_homeworld)) { NumVisits = GET_GAME_STATE (ZOQFOT_INFO); switch (NumVisits++) { case 0: NPCPhrase_cb (GENERAL_INFO_10, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_11, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_12, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_13, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); break; case 1: NPCPhrase_cb (GENERAL_INFO_20, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_21, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_22, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_23, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_24, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_25, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_26, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_27, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); break; case 2: NPCPhrase_cb (GENERAL_INFO_30, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_31, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_32, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_33, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_34, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_35, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); break; case 3: NPCPhrase_cb (GENERAL_INFO_40, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_41, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_42, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_43, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_44, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_45, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_46, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_47, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_48, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_49, &SelectAlienPIK); NPCPhrase_cb (GENERAL_INFO_410, &SelectAlienZOQ); NPCPhrase_cb (GENERAL_INFO_411, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); --NumVisits; break; } SET_GAME_STATE (ZOQFOT_INFO, NumVisits); DISABLE_PHRASE (whats_up_homeworld); } else if (PLAYER_SAID (R, any_war_news)) { #define UTWIG_BUY_TIME (1 << 0) #define KOHR_AH_WIN (1 << 1) #define URQUAN_LOSE (1 << 2) #define KOHR_AH_KILL (1 << 3) #define KNOW_ALL (UTWIG_BUY_TIME | KOHR_AH_WIN | URQUAN_LOSE | KOHR_AH_KILL) BYTE KnowMask; NumVisits = GET_GAME_STATE (UTWIG_SUPOX_MISSION); KnowMask = GET_GAME_STATE (ZOQFOT_KNOW_MASK); if (!(KnowMask & KOHR_AH_KILL) && GET_GAME_STATE (KOHR_AH_FRENZY)) { NPCPhrase_cb (KOHRAH_FRENZY0, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_FRENZY1, &SelectAlienPIK); NPCPhrase_cb (KOHRAH_FRENZY2, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_FRENZY3, &SelectAlienPIK); NPCPhrase_cb (KOHRAH_FRENZY4, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_FRENZY5, &SelectAlienPIK); NPCPhrase_cb (KOHRAH_FRENZY6, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_FRENZY7, &SelectAlienPIK); NPCPhrase_cb (KOHRAH_FRENZY8, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_FRENZY9, &SelectAlienPIK); NPCPhrase_cb (KOHRAH_FRENZY10, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_FRENZY11, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); KnowMask = KNOW_ALL; } else if (!(KnowMask & UTWIG_BUY_TIME) && NumVisits > 0 && NumVisits < 5) { NPCPhrase_cb (UTWIG_DELAY0, &SelectAlienZOQ); NPCPhrase_cb (UTWIG_DELAY1, &SelectAlienPIK); NPCPhrase_cb (UTWIG_DELAY2, &SelectAlienZOQ); NPCPhrase_cb (UTWIG_DELAY3, &SelectAlienPIK); NPCPhrase_cb (UTWIG_DELAY4, &SelectAlienZOQ); NPCPhrase_cb (UTWIG_DELAY5, &SelectAlienPIK); NPCPhrase_cb (UTWIG_DELAY6, &SelectAlienZOQ); NPCPhrase_cb (UTWIG_DELAY7, &SelectAlienPIK); NPCPhrase_cb (UTWIG_DELAY8, &SelectAlienZOQ); NPCPhrase_cb (UTWIG_DELAY9, &SelectAlienPIK); NPCPhrase_cb (UTWIG_DELAY10, &SelectAlienZOQ); NPCPhrase_cb (UTWIG_DELAY11, &SelectAlienPIK); NPCPhrase_cb (UTWIG_DELAY12, &SelectAlienZOQ); NPCPhrase_cb (UTWIG_DELAY13, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); KnowMask |= UTWIG_BUY_TIME; } else { SIZE i; i = START_YEAR + YEARS_TO_KOHRAH_VICTORY; if (NumVisits) ++i; if ((i -= GLOBAL (GameClock.year_index)) == 1 && GLOBAL (GameClock.month_index) > 2) i = 0; if (!(KnowMask & URQUAN_LOSE) && i <= 0) { NPCPhrase_cb (URQUAN_NEARLY_GONE0, &SelectAlienZOQ); NPCPhrase_cb (URQUAN_NEARLY_GONE1, &SelectAlienPIK); NPCPhrase_cb (URQUAN_NEARLY_GONE2, &SelectAlienZOQ); NPCPhrase_cb (URQUAN_NEARLY_GONE3, &SelectAlienPIK); NPCPhrase_cb (URQUAN_NEARLY_GONE4, &SelectAlienZOQ); NPCPhrase_cb (URQUAN_NEARLY_GONE5, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); KnowMask |= KOHR_AH_WIN | URQUAN_LOSE; } else if (!(KnowMask & KOHR_AH_WIN) && i == 1) { NPCPhrase_cb (KOHRAH_WINNING0, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_WINNING1, &SelectAlienPIK); NPCPhrase_cb (KOHRAH_WINNING2, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_WINNING3, &SelectAlienPIK); NPCPhrase_cb (KOHRAH_WINNING4, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_WINNING5, &SelectAlienPIK); NPCPhrase_cb (KOHRAH_WINNING6, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_WINNING7, &SelectAlienPIK); NPCPhrase_cb (KOHRAH_WINNING8, &SelectAlienZOQ); NPCPhrase_cb (KOHRAH_WINNING9, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); KnowMask |= KOHR_AH_WIN; } else { NPCPhrase_cb (NO_WAR_NEWS0, &SelectAlienZOQ); NPCPhrase_cb (NO_WAR_NEWS1, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); } } SET_GAME_STATE (ZOQFOT_KNOW_MASK, KnowMask); DISABLE_PHRASE (any_war_news); } else if (PLAYER_SAID (R, i_want_alliance)) { NPCPhrase_cb (GOOD0, &SelectAlienZOQ); NPCPhrase_cb (GOOD1, &SelectAlienPIK); NPCPhrase_cb (GOOD2, &SelectAlienZOQ); NPCPhrase_cb (GOOD3, &SelectAlienPIK); NPCPhrase_cb (GOOD4, &SelectAlienZOQ); NPCPhrase_cb (GOOD5, &SelectAlienPIK); NPCPhrase_cb (GOOD6, &SelectAlienZOQ); NPCPhrase_cb (GOOD7, &SelectAlienPIK); NPCPhrase_cb (GOOD8, &SelectAlienZOQ); NPCPhrase_cb (GOOD9, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); ActivateStarShip (ZOQFOTPIK_SHIP, 0); AddEvent (RELATIVE_EVENT, 3, 0, 0, ZOQFOT_DISTRESS_EVENT); } else if (PLAYER_SAID (R, enough_info)) { NPCPhrase_cb (OK_ENOUGH_INFO, &SelectAlienZOQ); ZFPTalkSegue ((COUNT)~0); } if (PHRASE_ENABLED (whats_up_homeworld)) Response (whats_up_homeworld, ZoqFotHome); if (PHRASE_ENABLED (any_war_news)) Response (any_war_news, ZoqFotHome); if (!(ActivateStarShip (ZOQFOTPIK_SHIP, CHECK_ALLIANCE) & GOOD_GUY)) Response (i_want_alliance, ZoqFotHome); else if (PHRASE_ENABLED (want_specific_info)) { Response (want_specific_info, ZoqFotInfo); } Response (bye_homeworld, ExitConversation); } static void Intro (void) { BYTE NumVisits; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase_cb (OUT_TAKES0, &SelectAlienZOQ); NPCPhrase_cb (OUT_TAKES1, &SelectAlienPIK); NPCPhrase_cb (OUT_TAKES2, &SelectAlienZOQ); NPCPhrase_cb (OUT_TAKES3, &SelectAlienPIK); NPCPhrase_cb (OUT_TAKES4, &SelectAlienZOQ); NPCPhrase_cb (OUT_TAKES5, &SelectAlienPIK); NPCPhrase_cb (OUT_TAKES6, &SelectAlienZOQ); NPCPhrase_cb (OUT_TAKES7, &SelectAlienPIK); NPCPhrase_cb (OUT_TAKES8, &SelectAlienZOQ); NPCPhrase_cb (OUT_TAKES9, &SelectAlienPIK); NPCPhrase_cb (OUT_TAKES10, &SelectAlienZOQ); NPCPhrase_cb (OUT_TAKES11, &SelectAlienPIK); NPCPhrase_cb (OUT_TAKES12, &SelectAlienZOQ); NPCPhrase_cb (OUT_TAKES13, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (GET_GAME_STATE (ZOQFOT_HOSTILE)) { NumVisits = GET_GAME_STATE (ZOQFOT_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase_cb (HOSTILE_HELLO_10, &SelectAlienZOQ); NPCPhrase_cb (HOSTILE_HELLO_11, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); break; case 1: NPCPhrase_cb (HOSTILE_HELLO_20, &SelectAlienZOQ); NPCPhrase_cb (HOSTILE_HELLO_21, &SelectAlienPIK); NPCPhrase_cb (HOSTILE_HELLO_22, &SelectAlienZOQ); NPCPhrase_cb (HOSTILE_HELLO_23, &SelectAlienPIK); NPCPhrase_cb (HOSTILE_HELLO_24, &SelectAlienZOQ); NPCPhrase_cb (HOSTILE_HELLO_25, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); break; case 2: NPCPhrase_cb (HOSTILE_HELLO_30, &SelectAlienZOQ); NPCPhrase_cb (HOSTILE_HELLO_31, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); break; case 3: NPCPhrase_cb (HOSTILE_HELLO_40, &SelectAlienZOQ); NPCPhrase_cb (HOSTILE_HELLO_41, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); --NumVisits; break; } SET_GAME_STATE (ZOQFOT_HOME_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (!GET_GAME_STATE (MET_ZOQFOT)) { SET_GAME_STATE (MET_ZOQFOT, 1); NPCPhrase_cb (WE_ARE0, &SelectAlienZOQ); NPCPhrase_cb (WE_ARE1, &SelectAlienPIK); NPCPhrase_cb (WE_ARE2, &SelectAlienZOQ); NPCPhrase_cb (WE_ARE3, &SelectAlienPIK); NPCPhrase_cb (WE_ARE4, &SelectAlienZOQ); NPCPhrase_cb (WE_ARE5, &SelectAlienPIK); NPCPhrase_cb (WE_ARE6, &SelectAlienZOQ); NPCPhrase_cb (WE_ARE7, &SelectAlienPIK); if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NPCPhrase_cb (INIT_HOME_HELLO0, &SelectAlienZOQ); NPCPhrase_cb (INIT_HOME_HELLO1, &SelectAlienPIK); NPCPhrase_cb (INIT_HOME_HELLO2, &SelectAlienZOQ); NPCPhrase_cb (INIT_HOME_HELLO3, &SelectAlienPIK); } else { NPCPhrase_cb (SCOUT_HELLO0, &SelectAlienZOQ); NPCPhrase_cb (SCOUT_HELLO1, &SelectAlienPIK); NPCPhrase_cb (SCOUT_HELLO2, &SelectAlienZOQ); NPCPhrase_cb (SCOUT_HELLO3, &SelectAlienPIK); } ZFPTalkSegue ((COUNT)~0); AquaintZoqFot (0); } else { if (GET_GAME_STATE (ZOQFOT_DISTRESS)) { #define MAX_ZFP_SHIPS 4 NPCPhrase_cb (THANKS_FOR_RESCUE0, &SelectAlienZOQ); NPCPhrase_cb (THANKS_FOR_RESCUE1, &SelectAlienPIK); NPCPhrase_cb (THANKS_FOR_RESCUE2, &SelectAlienZOQ); NPCPhrase_cb (THANKS_FOR_RESCUE3, &SelectAlienPIK); NPCPhrase_cb (THANKS_FOR_RESCUE4, &SelectAlienZOQ); NPCPhrase_cb (THANKS_FOR_RESCUE5, &SelectAlienPIK); NPCPhrase_cb (THANKS_FOR_RESCUE6, &SelectAlienZOQ); NPCPhrase_cb (THANKS_FOR_RESCUE7, &SelectAlienPIK); NPCPhrase_cb (THANKS_FOR_RESCUE8, &SelectAlienZOQ); NPCPhrase_cb (THANKS_FOR_RESCUE9, &SelectAlienPIK); NPCPhrase_cb (THANKS_FOR_RESCUE10, &SelectAlienZOQ); NPCPhrase_cb (THANKS_FOR_RESCUE11, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); SET_GAME_STATE (ZOQFOT_DISTRESS, 0); ActivateStarShip (ZOQFOTPIK_SHIP, MAX_ZFP_SHIPS); } else { NumVisits = GET_GAME_STATE (ZOQFOT_HOME_VISITS); if (!(ActivateStarShip (ZOQFOTPIK_SHIP, CHECK_ALLIANCE) & GOOD_GUY)) { switch (NumVisits++) { case 0: NPCPhrase_cb (NEUTRAL_HOME_HELLO_10, &SelectAlienZOQ); NPCPhrase_cb (NEUTRAL_HOME_HELLO_11, &SelectAlienPIK); NPCPhrase_cb (NEUTRAL_HOME_HELLO_12, &SelectAlienZOQ); NPCPhrase_cb (NEUTRAL_HOME_HELLO_13, &SelectAlienPIK); break; case 1: NPCPhrase_cb (NEUTRAL_HOME_HELLO_20, &SelectAlienZOQ); NPCPhrase_cb (NEUTRAL_HOME_HELLO_21, &SelectAlienPIK); NPCPhrase_cb (NEUTRAL_HOME_HELLO_22, &SelectAlienZOQ); NPCPhrase_cb (NEUTRAL_HOME_HELLO_23, &SelectAlienPIK); --NumVisits; break; } ZFPTalkSegue ((COUNT)~0); } else { switch (NumVisits++) { case 0: NPCPhrase_cb (ALLIED_HOME_HELLO_10, &SelectAlienZOQ); NPCPhrase_cb (ALLIED_HOME_HELLO_11, &SelectAlienPIK); NPCPhrase_cb (ALLIED_HOME_HELLO_12, &SelectAlienZOQ); NPCPhrase_cb (ALLIED_HOME_HELLO_13, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); break; case 1: NPCPhrase_cb (ALLIED_HOME_HELLO_20, &SelectAlienZOQ); NPCPhrase_cb (ALLIED_HOME_HELLO_21, &SelectAlienPIK); NPCPhrase_cb (ALLIED_HOME_HELLO_22, &SelectAlienZOQ); NPCPhrase_cb (ALLIED_HOME_HELLO_23, &SelectAlienPIK); NPCPhrase_cb (ALLIED_HOME_HELLO_24, &SelectAlienZOQ); NPCPhrase_cb (ALLIED_HOME_HELLO_25, &SelectAlienPIK); NPCPhrase_cb (ALLIED_HOME_HELLO_26, &SelectAlienZOQ); NPCPhrase_cb (ALLIED_HOME_HELLO_27, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); break; case 2: NPCPhrase_cb (ALLIED_HOME_HELLO_30, &SelectAlienZOQ); NPCPhrase_cb (ALLIED_HOME_HELLO_31, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); break; case 3: NPCPhrase_cb (ALLIED_HOME_HELLO_40, &SelectAlienZOQ); NPCPhrase_cb (ALLIED_HOME_HELLO_41, &SelectAlienPIK); ZFPTalkSegue ((COUNT)~0); --NumVisits; break; } } SET_GAME_STATE (ZOQFOT_HOME_VISITS, NumVisits); } ZoqFotHome (0); } } static COUNT uninit_zoqfot (void) { return (0); } static void post_zoqfot_enc (void) { // nothing defined so far } LOCDATAPTR init_zoqfot_comm (void) { LOCDATAPTR retval; zoqfot_desc.init_encounter_func = Intro; zoqfot_desc.post_encounter_func = post_zoqfot_enc; zoqfot_desc.uninit_encounter_func = uninit_zoqfot; zoqfot_desc.AlienTextWidth = (SIS_TEXT_WIDTH >> 1) - TEXT_X_OFFS; if ((ActivateStarShip (ZOQFOTPIK_SHIP, CHECK_ALLIANCE) & GOOD_GUY) || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &zoqfot_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/thradd/0000755000175000017500000000000010552600275016022 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/thradd/thradd.res0000600000175000017500000000036210543202031017760 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/thradd PACKAGE THRADD_PACKAGE thradd.con GFXRES THRADD_PMAP_ANIM thradd.ani FONTRES THRADD_FONT thradd.fon MUSICRES THRADD_MUSIC thradd.mod STRTAB THRADD_CONVERSATION_PHRASES thradd.txt uqm-0.6.2/sc2/src/sc2code/comm/thradd/ifontres.h0000600000175000017500000000004210543202031017774 0ustar joeyjoey#define THRADD_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/thradd/restypes.h0000600000175000017500000000024110543202031020022 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/thradd/strings.h0000600000175000017500000000712510543202031017645 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, HOSTILE_SPACE_HELLO_1, HOSTILE_SPACE_HELLO_2, HOSTILE_SPACE_HELLO_3, HOSTILE_SPACE_HELLO_4, HOSTILE_HOMEWORLD_HELLO_1, HOSTILE_HOMEWORLD_HELLO_2, HOSTILE_HOMEWORLD_HELLO_3, HOSTILE_HOMEWORLD_HELLO_4, whats_up_hostile_1, whats_up_hostile_2, GENERAL_INFO_HOSTILE_1, GENERAL_INFO_HOSTILE_2, GENERAL_INFO_HOSTILE_3, GENERAL_INFO_HOSTILE_4, what_about_you_1, ABOUT_US_1, what_about_you_2, ABOUT_US_2, what_about_urquan_1, ABOUT_URQUAN_1, what_about_urquan_2, ABOUT_URQUAN_2, got_idea, GOOD_IDEA, WE_GO_TO_IMPRESS_URQUAN_1, WE_GO_TO_IMPRESS_URQUAN_2, WE_IMPRESSING_URQUAN_1, WE_IMPRESSING_URQUAN_2, WE_IMPRESSED_URQUAN_1, WE_IMPRESSED_URQUAN_2, HOSTILE_HELIX_HELLO_1, HOSTILE_HELIX_HELLO_2, submit_1, NO_SUBMIT_1, submit_2, NO_SUBMIT_2, be_friends_1, NO_FRIENDS_1, be_friends_2, NO_FRIENDS_2, how_impressed_urquan_1, IMPRESSED_LIKE_SO_1, how_impressed_urquan_2, IMPRESSED_LIKE_SO_2, bye_hostile_1, GOODBYE_HOSTILE_1, bye_hostile_2, GOODBYE_HOSTILE_2, why_you_here_hostile, NONE_OF_YOUR_CONCERN, demand_to_land, NO_DEMAND, what_about_this_world, BLUE_HELIX, whats_helix_hostile, HELIX_IS_HOSTILE, i_need_to_land_lie, CAUGHT_LIE, bye_hostile_helix, GOODBYE_HOSTILE_HELIX, DIE_THIEF_1, DIE_THIEF_2, AMAZING_PERFORMANCE, IMPRESSIVE_PERFORMANCE, ADEQUATE_PERFORMANCE, HELLO_POLITE_1, HELLO_POLITE_2, HELLO_POLITE_3, HELLO_POLITE_4, HELLO_RHYME_1, HELLO_RHYME_2, HELLO_RHYME_3, HELLO_RHYME_4, HELLO_PIG_LATIN_1, HELLO_PIG_LATIN_2, HELLO_PIG_LATIN_3, HELLO_PIG_LATIN_4, HELLO_LIKE_YOU_1, HELLO_LIKE_YOU_2, HELLO_LIKE_YOU_3, HELLO_LIKE_YOU_4, WELCOME_SPACE0, WELCOME_SPACE1, WELCOME_HOMEWORLD0, WELCOME_HOMEWORLD1, WELCOME_HELIX0, WELCOME_HELIX1, why_you_here_ally, GUARDING_HELIX_ALLY, whats_helix_ally, HELIX_IS_ALLY, may_i_land, SURE_LAND, whats_up_ally, GENERAL_INFO_ALLY_1, GENERAL_INFO_ALLY_2, GENERAL_INFO_ALLY_3, GENERAL_INFO_ALLY_4, HOW_SHOULD_WE_ACT, friendly, OK_FRIENDLY, wacky, OK_WACKY, just_like_us, OK_JUST_LIKE_YOU, WORK_TO_DO, contemplative, OK_CONTEMPLATIVE, how_goes_culture, CONTEMP_GOES_1, CONTEMP_GOES_2, FRIENDLY_GOES_1, FRIENDLY_GOES_2, WACKY_GOES_1, WACKY_GOES_2, LIKE_YOU_GOES_1, LIKE_YOU_GOES_2, bye_ally, GOODBYE_ALLY_1, GOODBYE_ALLY_2, GOODBYE_ALLY_3, GOODBYE_ALLY_4, be_polite, OK_POLITE, speak_pig_latin, OK_PIG_LATIN, use_rhymes, OK_RHYMES, just_the_way_we_do, OK_WAY_YOU_DO, WHAT_NAME_FOR_CULTURE, alliance_name, OK_ALLIANCE_NAME, NAME_TAIL, you_decide, OK_CULTURE_20, fat, OK_FAT, the_slave_empire0, the_slave_empire1, OK_SLAVE, FAT_JERKS, CULTURE, SLAVE_EMPIRE, name_1, name_2, name_3, name_40, name_41, HAVING_FUN_WITH_ILWRATH_1, HAVING_FUN_WITH_ILWRATH_2, GO_AWAY_FIGHTING_ILWRATH_1, GO_AWAY_FIGHTING_ILWRATH_2, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/thradd/igfxres.h0000600000175000017500000000004710543202031017617 0ustar joeyjoey#define THRADD_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/thradd/thraddc.c0000600000175000017500000004751010543202031017562 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/thradd/resinst.h" #include "comm/thradd/strings.h" #include "build.h" #include "gameev.h" static LOCDATA thradd_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)THRADD_PMAP_ANIM, /* AlienFrame */ (FONT)THRADD_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)THRADD_COLOR_MAP, /* AlienColorMap */ THRADD_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ THRADD_CONVERSATION_PHRASES, /* PlayerPhrases */ 8, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 8, /* StartIndex */ 4, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND / 15, ONE_SECOND / 15, /* RestartRate */ (1 << 4), /* BlockMask */ }, { 12, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 21, /* StartIndex */ 6, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 27, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 4), /* BlockMask */ }, { 30, /* StartIndex */ 12, /* NumFrames */ CIRCULAR_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 12, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND, /* RestartRate */ (1 << 0) | (1 << 3) | (1 << 5), }, { 42, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 4) | (1 << 6), /* BlockMask */ }, { 47, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 5), /* BlockMask */ }, { 52, /* StartIndex */ 4, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND / 20, 0, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 7, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static int GetCultureName (void) { int culture; switch (GET_GAME_STATE (THRADD_CULTURE)) { case 1: culture = CULTURE; break; case 2: culture = FAT_JERKS; break; case 3: culture = SLAVE_EMPIRE; break; } return (culture); } static void PolitePhrase (BYTE which_phrase) { switch (which_phrase) { case 0: NPCPhrase (HELLO_POLITE_1); break; case 1: NPCPhrase (HELLO_POLITE_2); break; case 2: NPCPhrase (HELLO_POLITE_3); break; case 3: NPCPhrase (HELLO_POLITE_4); break; } } static void RhymePhrase (BYTE which_phrase) { switch (which_phrase) { case 0: NPCPhrase (HELLO_RHYME_1); break; case 1: NPCPhrase (HELLO_RHYME_2); break; case 2: NPCPhrase (HELLO_RHYME_3); break; case 3: NPCPhrase (HELLO_RHYME_4); break; } } static void PigLatinPhrase (BYTE which_phrase) { switch (which_phrase) { case 0: NPCPhrase (HELLO_PIG_LATIN_1); break; case 1: NPCPhrase (HELLO_PIG_LATIN_2); break; case 2: NPCPhrase (HELLO_PIG_LATIN_3); break; case 3: NPCPhrase (HELLO_PIG_LATIN_4); break; } } static void LikeYouPhrase (BYTE which_phrase) { switch (which_phrase) { case 0: NPCPhrase (HELLO_LIKE_YOU_1); break; case 1: NPCPhrase (HELLO_LIKE_YOU_2); break; case 2: NPCPhrase (HELLO_LIKE_YOU_3); break; case 3: NPCPhrase (HELLO_LIKE_YOU_4); break; } } static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, bye_hostile_2)) NPCPhrase (GOODBYE_HOSTILE_2); else if (PLAYER_SAID (R, bye_hostile_1)) { NPCPhrase (GOODBYE_HOSTILE_1); SET_GAME_STATE (THRADD_HOSTILE_STACK_5, 1); } else if (PLAYER_SAID (R, submit_1)) { NPCPhrase (NO_SUBMIT_1); SET_GAME_STATE (THRADD_HOSTILE_STACK_2, 1); } else if (PLAYER_SAID (R, submit_2)) NPCPhrase (NO_SUBMIT_2); else if (PLAYER_SAID (R, got_idea)) { NPCPhrase (GOOD_IDEA); SET_GAME_STATE (BATTLE_SEGUE, 0); AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_THRADD_MISSION); SET_GAME_STATE (THRADD_STACK_1, 5); } else if (PLAYER_SAID (R, bye_hostile_helix)) NPCPhrase (GOODBYE_HOSTILE_HELIX); else if (PLAYER_SAID (R, bye_ally)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (THRADD_STACK_1); switch (NumVisits++) { case 0: NPCPhrase (GOODBYE_ALLY_1); break; case 1: NPCPhrase (GOODBYE_ALLY_2); break; case 2: NPCPhrase (GOODBYE_ALLY_3); break; case 3: NPCPhrase (GOODBYE_ALLY_4); --NumVisits; break; } SET_GAME_STATE (THRADD_STACK_1, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (PLAYER_SAID (R, may_i_land)) { NPCPhrase (SURE_LAND); SET_GAME_STATE (HELIX_UNPROTECTED, 1); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (PLAYER_SAID (R, demand_to_land)) NPCPhrase (NO_DEMAND); else if (PLAYER_SAID (R, i_need_to_land_lie)) NPCPhrase (CAUGHT_LIE); else { if (PLAYER_SAID (R, contemplative)) { NPCPhrase (OK_CONTEMPLATIVE); SET_GAME_STATE (THRADD_DEMEANOR, 0); } else if (PLAYER_SAID (R, friendly)) { NPCPhrase (OK_FRIENDLY); SET_GAME_STATE (THRADD_DEMEANOR, 1); } else if (PLAYER_SAID (R, wacky)) { NPCPhrase (OK_WACKY); SET_GAME_STATE (THRADD_DEMEANOR, 2); } else if (PLAYER_SAID (R, just_like_us)) { NPCPhrase (OK_JUST_LIKE_YOU); SET_GAME_STATE (THRADD_DEMEANOR, 3); } NPCPhrase (WORK_TO_DO); SET_GAME_STATE (BATTLE_SEGUE, 0); } } static void ThraddAllies (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, why_you_here_ally)) { NPCPhrase (GUARDING_HELIX_ALLY); DISABLE_PHRASE (why_you_here_ally); } else if (PLAYER_SAID (R, whats_helix_ally)) { NPCPhrase (HELIX_IS_ALLY); DISABLE_PHRASE (whats_helix_ally); } else if (PLAYER_SAID (R, whats_up_ally)) { NumVisits = GET_GAME_STATE (THRADD_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_ALLY_1); break; case 1: NPCPhrase (GENERAL_INFO_ALLY_2); break; case 2: NPCPhrase (GENERAL_INFO_ALLY_3); break; case 3: NPCPhrase (GENERAL_INFO_ALLY_4); --NumVisits; break; } SET_GAME_STATE (THRADD_INFO, NumVisits); DISABLE_PHRASE (whats_up_ally); } else if (PLAYER_SAID (R, how_goes_culture)) { NumVisits = GET_GAME_STATE (THRADD_DEMEANOR); switch (NumVisits & ((1 << 2) - 1)) { case 0: if (!(NumVisits & ~((1 << 2) - 1))) NPCPhrase (CONTEMP_GOES_1); else NPCPhrase (CONTEMP_GOES_2); break; case 1: if (!(NumVisits & ~((1 << 2) - 1))) NPCPhrase (FRIENDLY_GOES_1); else NPCPhrase (FRIENDLY_GOES_2); break; case 2: if (!(NumVisits & ~((1 << 2) - 1))) NPCPhrase (WACKY_GOES_1); else NPCPhrase (WACKY_GOES_2); break; case 3: if (!(NumVisits & ~((1 << 2) - 1))) NPCPhrase (LIKE_YOU_GOES_1); else NPCPhrase (LIKE_YOU_GOES_2); break; } NumVisits |= 1 << 2; SET_GAME_STATE (THRADD_DEMEANOR, NumVisits); DISABLE_PHRASE (how_goes_culture); } if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { if (PHRASE_ENABLED (why_you_here_ally)) Response (why_you_here_ally, ThraddAllies); else { if (PHRASE_ENABLED (whats_helix_ally)) Response (whats_helix_ally, ThraddAllies); Response (may_i_land, ExitConversation); } } if (PHRASE_ENABLED (whats_up_ally)) Response (whats_up_ally, ThraddAllies); if (PHRASE_ENABLED (how_goes_culture)) Response (how_goes_culture, ThraddAllies); Response (bye_ally, ExitConversation); } static void ThraddDemeanor (RESPONSE_REF R) { if (PLAYER_SAID (R, you_decide)) { NPCPhrase (OK_CULTURE_20); SET_GAME_STATE (THRADD_CULTURE, 1); } else if (PLAYER_SAID (R, fat)) { NPCPhrase (OK_FAT); SET_GAME_STATE (THRADD_CULTURE, 2); } else if (PLAYER_SAID (R, the_slave_empire0)) { SET_GAME_STATE (THRADD_CULTURE, 3); NPCPhrase (OK_SLAVE); } NPCPhrase (HOW_SHOULD_WE_ACT); Response (contemplative, ExitConversation); Response (friendly, ExitConversation); Response (wacky, ExitConversation); Response (just_like_us, ExitConversation); } static void ThraddCulture (RESPONSE_REF R) { if (PLAYER_SAID (R, be_polite)) { NPCPhrase (OK_POLITE); SET_GAME_STATE (THRADD_INTRO, 0); } else if (PLAYER_SAID (R, use_rhymes)) { NPCPhrase (OK_RHYMES); SET_GAME_STATE (THRADD_INTRO, 1); } else if (PLAYER_SAID (R, speak_pig_latin)) { NPCPhrase (OK_PIG_LATIN); SET_GAME_STATE (THRADD_INTRO, 2); } else if (PLAYER_SAID (R, just_the_way_we_do)) { NPCPhrase (OK_WAY_YOU_DO); SET_GAME_STATE (THRADD_INTRO, 3); } NPCPhrase (WHAT_NAME_FOR_CULTURE); construct_response ( shared_phrase_buf, the_slave_empire0, GLOBAL_SIS (CommanderName), the_slave_empire1, NULL_PTR); Response (you_decide, ThraddDemeanor); Response (fat, ThraddDemeanor); DoResponsePhrase (the_slave_empire0, ThraddDemeanor, shared_phrase_buf); } static void ThraddWorship (RESPONSE_REF R) { (void) R; // ignored SET_GAME_STATE (THRADD_VISITS, 0); SET_GAME_STATE (THRADD_MANNER, 1); SET_GAME_STATE (THRADD_STACK_1, 0); ActivateStarShip (THRADDASH_SHIP, 0); Response (be_polite, ThraddCulture); Response (speak_pig_latin, ThraddCulture); Response (use_rhymes, ThraddCulture); Response (just_the_way_we_do, ThraddCulture); } static void HelixWorld (RESPONSE_REF R) { if (PLAYER_SAID (R, why_you_here_hostile)) { NPCPhrase (NONE_OF_YOUR_CONCERN); SET_GAME_STATE (THRADD_CULTURE, 1); } else if (PLAYER_SAID (R, what_about_this_world)) { NPCPhrase (BLUE_HELIX); SET_GAME_STATE (THRADD_INTRO, 1); } else if (PLAYER_SAID (R, whats_helix_hostile)) { NPCPhrase (HELIX_IS_HOSTILE); SET_GAME_STATE (THRADD_INTRO, 2); } else if (PLAYER_SAID (R, i_need_to_land_lie)) { NPCPhrase (CAUGHT_LIE); SET_GAME_STATE (THRADD_DEMEANOR, 1); } if (!GET_GAME_STATE (THRADD_CULTURE)) Response (why_you_here_hostile, HelixWorld); else { Response (demand_to_land, ExitConversation); } switch (GET_GAME_STATE (THRADD_INTRO)) { case 0: Response (what_about_this_world, HelixWorld); break; case 1: Response (whats_helix_hostile, HelixWorld); break; } if (!GET_GAME_STATE (THRADD_DEMEANOR)) { Response (i_need_to_land_lie, ExitConversation); } Response (bye_hostile_helix, ExitConversation); } static void ThraddHostile (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_up_hostile_1)) { NPCPhrase (GENERAL_INFO_HOSTILE_1); SET_GAME_STATE (THRADD_INFO, 1); DISABLE_PHRASE (whats_up_hostile_2); } else if (PLAYER_SAID (R, whats_up_hostile_2)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (THRADD_INFO); switch (NumVisits++) { case 1: NPCPhrase (GENERAL_INFO_HOSTILE_2); break; case 2: NPCPhrase (GENERAL_INFO_HOSTILE_3); break; case 3: NPCPhrase (GENERAL_INFO_HOSTILE_4); --NumVisits; break; } SET_GAME_STATE (THRADD_INFO, NumVisits); DISABLE_PHRASE (whats_up_hostile_2); } else if (PLAYER_SAID (R, what_about_you_1)) { NPCPhrase (ABOUT_US_1); SET_GAME_STATE (THRADD_STACK_1, 1); } else if (PLAYER_SAID (R, what_about_you_2)) { NPCPhrase (ABOUT_US_2); SET_GAME_STATE (THRADD_STACK_1, 2); } else if (PLAYER_SAID (R, what_about_urquan_1)) { NPCPhrase (ABOUT_URQUAN_1); SET_GAME_STATE (THRADD_STACK_1, 3); } else if (PLAYER_SAID (R, what_about_urquan_2)) { NPCPhrase (ABOUT_URQUAN_2); SET_GAME_STATE (THRADD_STACK_1, 4); } else if (PLAYER_SAID (R, be_friends_1)) { NPCPhrase (NO_FRIENDS_1); SET_GAME_STATE (THRADD_HOSTILE_STACK_3, 1); } else if (PLAYER_SAID (R, be_friends_2)) { NPCPhrase (NO_FRIENDS_2); DISABLE_PHRASE (be_friends_2); } else if (PLAYER_SAID (R, how_impressed_urquan_1)) { NPCPhrase (IMPRESSED_LIKE_SO_1); SET_GAME_STATE (THRADD_HOSTILE_STACK_4, 1); } else if (PLAYER_SAID (R, how_impressed_urquan_2)) { NPCPhrase (IMPRESSED_LIKE_SO_2); SET_GAME_STATE (THRADD_MISSION, 5); } if (GET_GAME_STATE (THRADD_INFO) == 0) Response (whats_up_hostile_1, ThraddHostile); else if (PHRASE_ENABLED (whats_up_hostile_2)) Response (whats_up_hostile_2, ThraddHostile); switch (GET_GAME_STATE (THRADD_STACK_1)) { case 0: Response (what_about_you_1, ThraddHostile); break; case 1: Response (what_about_you_2, ThraddHostile); break; case 2: Response (what_about_urquan_1, ThraddHostile); break; case 3: Response (what_about_urquan_2, ThraddHostile); break; case 4: if (!GET_GAME_STATE (KOHR_AH_FRENZY)) Response (got_idea, ExitConversation); else { SET_GAME_STATE (THRADD_STACK_1, 5); } break; } if (GET_GAME_STATE (THRADD_HOSTILE_STACK_2) == 0) Response (submit_1, ExitConversation); else Response (submit_2, ExitConversation); if (GET_GAME_STATE (THRADD_HOSTILE_STACK_3) == 0) Response (be_friends_1, ThraddHostile); else if (PHRASE_ENABLED (be_friends_2)) Response (be_friends_2, ThraddHostile); if (GET_GAME_STATE (THRADD_MISSION) == 4) { if (GET_GAME_STATE (THRADD_HOSTILE_STACK_4) == 0) Response (how_impressed_urquan_1, ThraddHostile); else Response (how_impressed_urquan_2, ThraddHostile); } if (GET_GAME_STATE (THRADD_HOSTILE_STACK_5) == 0) Response (bye_hostile_1, ExitConversation); else Response (bye_hostile_2, ExitConversation); } static void Intro (void) { BYTE NumVisits; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (GET_GAME_STATE (AQUA_HELIX)) { NumVisits = GET_GAME_STATE (HELIX_VISITS); switch (NumVisits++) { case 0: NPCPhrase (DIE_THIEF_1); break; case 1: NPCPhrase (DIE_THIEF_2); --NumVisits; break; } SET_GAME_STATE (HELIX_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (GET_GAME_STATE (ILWRATH_FIGHT_THRADDASH)) { NumVisits = GET_GAME_STATE (THRADD_VISITS); if (GET_GAME_STATE (THRADD_MANNER)) { switch (NumVisits++) { case 0: NPCPhrase (HAVING_FUN_WITH_ILWRATH_1); break; case 1: NPCPhrase (HAVING_FUN_WITH_ILWRATH_2); --NumVisits; break; } } else { switch (NumVisits++) { case 0: NPCPhrase (GO_AWAY_FIGHTING_ILWRATH_1); break; case 1: NPCPhrase (GO_AWAY_FIGHTING_ILWRATH_2); --NumVisits; break; } } SET_GAME_STATE (THRADD_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (GET_GAME_STATE (THRADD_MANNER)) { RESPONSE_REF pStr0, pStr1; NumVisits = GET_GAME_STATE (THRADD_VISITS); switch (GET_GAME_STATE (THRADD_INTRO)) { case 0: PolitePhrase (NumVisits); break; case 1: RhymePhrase (NumVisits); break; case 2: PigLatinPhrase (NumVisits); break; case 3: LikeYouPhrase (NumVisits); break; } if (++NumVisits < 4) { SET_GAME_STATE (THRADD_VISITS, NumVisits); } if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { pStr0 = WELCOME_HELIX0; pStr1 = WELCOME_HELIX1; } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { pStr0 = WELCOME_HOMEWORLD0; pStr1 = WELCOME_HOMEWORLD1; } else { pStr0 = WELCOME_SPACE0; pStr1 = WELCOME_SPACE1; } NPCPhrase (pStr0); NPCPhrase (GetCultureName ()); NPCPhrase (pStr1); ThraddAllies ((RESPONSE_REF)0); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { NumVisits = GET_GAME_STATE (HELIX_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_HELIX_HELLO_1); break; case 1: NPCPhrase (HOSTILE_HELIX_HELLO_2); --NumVisits; break; } SET_GAME_STATE (HELIX_VISITS, NumVisits); HelixWorld ((RESPONSE_REF)0); } else if (GET_GAME_STATE (THRADDASH_BODY_COUNT) >= THRADDASH_BODY_THRESHOLD) { NPCPhrase (AMAZING_PERFORMANCE); ThraddWorship ((RESPONSE_REF)0); } else { NumVisits = GET_GAME_STATE (THRADDASH_BODY_COUNT); if (NumVisits >= 16 && GET_GAME_STATE (THRADD_BODY_LEVEL) == 1) { SET_GAME_STATE (THRADD_BODY_LEVEL, 2); NPCPhrase (IMPRESSIVE_PERFORMANCE); } else if (NumVisits >= 8 && GET_GAME_STATE (THRADD_BODY_LEVEL) == 0) { SET_GAME_STATE (THRADD_BODY_LEVEL, 1); NPCPhrase (ADEQUATE_PERFORMANCE); } { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (THRADD_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (HOSTILE_HOMEWORLD_HELLO_2); break; case 2: NPCPhrase (HOSTILE_HOMEWORLD_HELLO_3); break; case 3: NPCPhrase (HOSTILE_HOMEWORLD_HELLO_4); --NumVisits; break; } SET_GAME_STATE (THRADD_HOME_VISITS, NumVisits); } else if ((NumVisits = GET_GAME_STATE (THRADD_MISSION)) == 0 || NumVisits > 3) { NumVisits = GET_GAME_STATE (THRADD_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_SPACE_HELLO_1); break; case 1: NPCPhrase (HOSTILE_SPACE_HELLO_2); break; case 2: NPCPhrase (HOSTILE_SPACE_HELLO_3); break; case 3: NPCPhrase (HOSTILE_SPACE_HELLO_4); --NumVisits; break; } SET_GAME_STATE (THRADD_VISITS, NumVisits); } else { switch (NumVisits) { case 1: if (GET_GAME_STATE (THRADD_MISSION_VISITS) == 0) NPCPhrase (WE_GO_TO_IMPRESS_URQUAN_1); else NPCPhrase (WE_GO_TO_IMPRESS_URQUAN_2); break; case 2: if (GET_GAME_STATE (THRADD_MISSION_VISITS) == 0) NPCPhrase (WE_IMPRESSING_URQUAN_1); else NPCPhrase (WE_IMPRESSING_URQUAN_2); break; case 3: if (GET_GAME_STATE (THRADD_MISSION_VISITS) == 0) NPCPhrase (WE_IMPRESSED_URQUAN_1); else NPCPhrase (WE_IMPRESSED_URQUAN_2); break; } SET_GAME_STATE (THRADD_MISSION_VISITS, 1); } ThraddHostile ((RESPONSE_REF)0); } } } static COUNT uninit_thradd (void) { return (0); } static void post_thradd_enc (void) { // nothing defined so far } LOCDATAPTR init_thradd_comm (void) { LOCDATAPTR retval; thradd_desc.init_encounter_func = Intro; thradd_desc.post_encounter_func = post_thradd_enc; thradd_desc.uninit_encounter_func = uninit_thradd; thradd_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); thradd_desc.AlienTextBaseline.y = 0; thradd_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if (GET_GAME_STATE (THRADD_MANNER) || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &thradd_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/thradd/istrtab.h0000600000175000017500000000012610543202031017616 0ustar joeyjoey#define THRADD_CONVERSATION_PHRASES 0x00200004L #define THRADD_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/thradd/imusicre.h0000600000175000017500000000004310543202031017764 0ustar joeyjoey#define THRADD_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/thradd/Makeinfo0000600000175000017500000000002710543202031017451 0ustar joeyjoeyuqm_CFILES="thraddc.c" uqm-0.6.2/sc2/src/sc2code/comm/thradd/respkg.h0000600000175000017500000000003710543202031017442 0ustar joeyjoeyenum { THRADD_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/thradd/resinst.h0000600000175000017500000000012610543202031017635 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/slyland/0000755000175000017500000000000010552600275016222 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/slyland/ifontres.h0000600000175000017500000000004310543202027020202 0ustar joeyjoey#define SLYLAND_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/slyland/restypes.h0000600000175000017500000000024110543202027020227 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/slyland/strings.h0000600000175000017500000000336510543202027020054 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, WE_COME_IN_PEACE_1, WE_COME_IN_PEACE_2, WE_COME_IN_PEACE_3, WE_COME_IN_PEACE_4, WE_COME_IN_PEACE_5, WE_COME_IN_PEACE_6, WE_COME_IN_PEACE_7, WE_COME_IN_PEACE_8, threat_1, threat_2, threat_3, threat_4, PROGRAMMED_TO_DEFEND_1, PROGRAMMED_TO_DEFEND_2, PROGRAMMED_TO_DEFEND_3, PROGRAMMED_TO_DEFEND_4, something_wrong_1, something_wrong_2, something_wrong_3, something_wrong_4, NOMINAL_FUNCTION_1, NOMINAL_FUNCTION_2, NOMINAL_FUNCTION_3, NOMINAL_FUNCTION_4, we_are_us_1, we_are_us_2, we_are_us_3, we_are_us_4, THIS_IS_PROBE_1, THIS_IS_PROBE_2, THIS_IS_PROBE_3, THIS_IS_PROBE_40, THIS_IS_PROBE_41, THIS_IS_PROBE_42, why_attack_1, why_attack_2, why_attack_3, why_attack_4, PEACEFUL_MISSION_1, PEACEFUL_MISSION_2, PEACEFUL_MISSION_3, PEACEFUL_MISSION_4, bye_1, bye_2, bye_3, bye_4, GOODBYE_1, GOODBYE_2, GOODBYE_3, GOODBYE_4, HOSTILE, DESTRUCT_SEQUENCE, destruct_code, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/slyland/igfxres.h0000600000175000017500000000005010543202027020016 0ustar joeyjoey#define SLYLAND_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/slyland/istrtab.h0000600000175000017500000000013010543202027020016 0ustar joeyjoey#define SLYLAND_CONVERSATION_PHRASES 0x00200004L #define SLYLAND_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/slyland/imusicre.h0000600000175000017500000000004410543202027020172 0ustar joeyjoey#define SLYLAND_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/slyland/slyland.c0000600000175000017500000002160410543202027020020 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/slyland/resinst.h" #include "comm/slyland/strings.h" #include "options.h" #include "battle.h" #include "setup.h" static LOCDATA slylandro_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)SLYLAND_PMAP_ANIM, /* AlienFrame */ (FONT)SLYLAND_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)SLYLAND_COLOR_MAP, /* AlienColorMap */ SLYLAND_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ SLYLAND_CONVERSATION_PHRASES, /* PlayerPhrases */ 6, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 1, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 3, /* RestartRate */ (1 << 3) /* BlockMask */ }, { 10, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 3, /* RestartRate */ (1 << 4) /* BlockMask */ }, { 18, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 3, /* RestartRate */ (1 << 5) /* BlockMask */ }, { 26, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 3, /* RestartRate */ (1 << 0) /* BlockMask */ }, { 34, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 3, /* RestartRate */ (1 << 1) /* BlockMask */ }, { 42, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 3, /* RestartRate */ (1 << 2) /* BlockMask */ }, }, { /* AlienTransitionDesc - empty */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc - empty */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static RESPONSE_REF threat, something_wrong, we_are_us, why_attack, bye; static void CombatIsInevitable (RESPONSE_REF R) { if (R == 0) { if (GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP)) Response (destruct_code, CombatIsInevitable); switch (GET_GAME_STATE (SLYLANDRO_PROBE_THREAT)) { case 0: threat = threat_1; break; case 1: threat = threat_2; break; case 2: threat = threat_3; break; default: threat = threat_4; break; } Response (threat, CombatIsInevitable); switch (GET_GAME_STATE (SLYLANDRO_PROBE_WRONG)) { case 0: something_wrong = something_wrong_1; break; case 1: something_wrong = something_wrong_2; break; case 2: something_wrong = something_wrong_3; break; default: something_wrong = something_wrong_4; break; } Response (something_wrong, CombatIsInevitable); switch (GET_GAME_STATE (SLYLANDRO_PROBE_ID)) { case 0: we_are_us = we_are_us_1; break; case 1: we_are_us = we_are_us_2; break; case 2: we_are_us = we_are_us_3; break; default: we_are_us = we_are_us_4; break; } Response (we_are_us, CombatIsInevitable); switch (GET_GAME_STATE (SLYLANDRO_PROBE_INFO)) { case 0: why_attack = why_attack_1; break; case 1: why_attack = why_attack_2; break; case 2: why_attack = why_attack_3; break; default: why_attack = why_attack_4; break; } Response (why_attack, CombatIsInevitable); switch (GET_GAME_STATE (SLYLANDRO_PROBE_EXIT)) { case 0: bye = bye_1; break; case 1: bye = bye_2; break; case 2: bye = bye_3; break; default: bye = bye_4; break; } Response (bye, CombatIsInevitable); } else if (PLAYER_SAID (R, destruct_code)) { NPCPhrase (DESTRUCT_SEQUENCE); instantVictory = TRUE; SET_GAME_STATE (BATTLE_SEGUE, 1); } else { BYTE NumVisits; if (PLAYER_SAID (R, threat)) { NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_THREAT); switch (NumVisits++) { case 0: NPCPhrase (PROGRAMMED_TO_DEFEND_1); break; case 1: NPCPhrase (PROGRAMMED_TO_DEFEND_2); break; case 2: NPCPhrase (PROGRAMMED_TO_DEFEND_3); break; case 3: NPCPhrase (PROGRAMMED_TO_DEFEND_4); --NumVisits; break; } SET_GAME_STATE (SLYLANDRO_PROBE_THREAT, NumVisits); } else if (PLAYER_SAID (R, something_wrong)) { NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_WRONG); switch (NumVisits++) { case 0: NPCPhrase (NOMINAL_FUNCTION_1); break; case 1: NPCPhrase (NOMINAL_FUNCTION_2); break; case 2: NPCPhrase (NOMINAL_FUNCTION_3); break; case 3: NPCPhrase (NOMINAL_FUNCTION_4); --NumVisits; break; } SET_GAME_STATE (SLYLANDRO_PROBE_WRONG, NumVisits); } else if (PLAYER_SAID (R, we_are_us)) { NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_ID); if (NumVisits == 3 && !optSubtitles) { /* If playing without subtitles, don't use the * last item in the conversation tree, which mentions * coordinates which can't be spoken. */ NumVisits--; } switch (NumVisits++) { case 0: NPCPhrase (THIS_IS_PROBE_1); break; case 1: NPCPhrase (THIS_IS_PROBE_2); break; case 2: NPCPhrase (THIS_IS_PROBE_3); break; case 3: { NPCPhrase (THIS_IS_PROBE_40); NPCPhrase (THIS_IS_PROBE_41); NPCPhrase (GLOBAL_PLAYER_LOCATION); NPCPhrase (THIS_IS_PROBE_42); --NumVisits; break; } } SET_GAME_STATE (SLYLANDRO_PROBE_ID, NumVisits); } else if (PLAYER_SAID (R, why_attack)) { NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_INFO); switch (NumVisits++) { case 0: NPCPhrase (PEACEFUL_MISSION_1); break; case 1: NPCPhrase (PEACEFUL_MISSION_2); break; case 2: NPCPhrase (PEACEFUL_MISSION_3); break; case 3: NPCPhrase (PEACEFUL_MISSION_4); --NumVisits; break; } SET_GAME_STATE (SLYLANDRO_PROBE_INFO, NumVisits); } else if (PLAYER_SAID (R, bye)) { NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_EXIT); switch (NumVisits++) { case 0: NPCPhrase (GOODBYE_1); break; case 1: NPCPhrase (GOODBYE_2); break; case 2: NPCPhrase (GOODBYE_3); break; case 3: NPCPhrase (GOODBYE_4); --NumVisits; break; } SET_GAME_STATE (SLYLANDRO_PROBE_EXIT, NumVisits); } NPCPhrase (HOSTILE); SET_GAME_STATE (PROBE_EXHIBITED_BUG, 1); SET_GAME_STATE (BATTLE_SEGUE, 1); } } static void Intro (void) { BYTE NumVisits; NumVisits = GET_GAME_STATE (SLYLANDRO_PROBE_VISITS); switch (NumVisits++) { case 0: NPCPhrase (WE_COME_IN_PEACE_1); break; case 1: NPCPhrase (WE_COME_IN_PEACE_2); break; case 2: NPCPhrase (WE_COME_IN_PEACE_3); break; case 3: NPCPhrase (WE_COME_IN_PEACE_4); break; case 4: NPCPhrase (WE_COME_IN_PEACE_5); break; case 5: NPCPhrase (WE_COME_IN_PEACE_6); break; case 6: NPCPhrase (WE_COME_IN_PEACE_7); break; case 7: NPCPhrase (WE_COME_IN_PEACE_8); --NumVisits; break; } SET_GAME_STATE (SLYLANDRO_PROBE_VISITS, NumVisits); CombatIsInevitable ((RESPONSE_REF)0); } static COUNT uninit_slyland (void) { return (0); } static void post_slyland_enc (void) { // nothing defined so far } LOCDATAPTR init_slyland_comm (void) { LOCDATAPTR retval; slylandro_desc.init_encounter_func = Intro; slylandro_desc.post_encounter_func = post_slyland_enc; slylandro_desc.uninit_encounter_func = uninit_slyland; slylandro_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); slylandro_desc.AlienTextBaseline.y = 0; slylandro_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; SET_GAME_STATE (BATTLE_SEGUE, 1); retval = &slylandro_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/slyland/slyland.res0000600000175000017500000000037410543202027020370 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/slyland PACKAGE SLYLAND_PACKAGE slyland.con GFXRES SLYLAND_PMAP_ANIM slyland.ani FONTRES SLYLAND_FONT slyland.fon MUSICRES SLYLAND_MUSIC slyland.mod STRTAB SLYLAND_CONVERSATION_PHRASES slyland.txt uqm-0.6.2/sc2/src/sc2code/comm/slyland/Makeinfo0000600000175000017500000000002710543202027017656 0ustar joeyjoeyuqm_CFILES="slyland.c" uqm-0.6.2/sc2/src/sc2code/comm/slyland/respkg.h0000600000175000017500000000004010543202027017641 0ustar joeyjoeyenum { SLYLAND_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/slyland/resinst.h0000600000175000017500000000012610543202027020042 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/comandr/0000755000175000017500000000000010552600275016177 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/comandr/ifontres.h0000600000175000017500000000004510543202021020153 0ustar joeyjoey#define COMMANDER_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/comandr/restypes.h0000600000175000017500000000024110543202021020176 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/comandr/strings.h0000600000175000017500000000531310543202021020016 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, GLAD_WHEN_YOU_COME_BACK, GIVE_FUEL, GIVE_FUEL_AGAIN, ARE_YOU_SUPPLY_SHIP, DO_YOU_HAVE_RADIO_THIS_TIME, HERE_IS_ANOTHER_LANDER, THE_WHAT_FROM_WHERE, ABOUT_TIME, MESSAGE_GARBLED_1, MESSAGE_GARBLED_2, HERE_IS_A_NEW_LANDER, THIS_MAY_SEEM_SILLY, OK_THE_NAFS, OK_THE_CAN, OK_THE_UFW, OK_THE_NAME_IS_EMPIRE0, OK_THE_NAME_IS_EMPIRE1, FUEL_UP0, FUEL_UP1, WHAT_KIND_OF_IDIOT, DONT_KNOW_WHO_YOU_ARE, THATS_IMPOSSIBLE, ASK_AWAY, RADIOS_ON_MERCURY, THANKS_FOR_HELPING, STARBASE_IS, HAPPENED_TO_EARTH, URQUAN_LEFT, BASE_ON_MOON, ACKNOWLEDGE_SECRET, ABOUT_BASE, GOOD_LUCK_WITH_BASE, DEALT_WITH_BASE_YET, HERE_COMES_ILWRATH, VERY_IMPRESSIVE, IT_WAS_ABANDONED, YOU_REALLY_FOUGHT_BASE, IM_GLAD_YOU_WON, IM_SURE_IT_WAS_DIFFICULT, THAT_WAS_PROBE, DEEP_TROUBLE, GOOD_NEWS, SURE_HOPE, ABOUT_BASE_AGAIN, COOK_BUTTS, OVERTHROW_ALIENS, KILL_MONSTERS, GOOD_LUCK_AGAIN, STARBASE_WILL_BE_READY, overthrow_evil_aliens, annihilate_those_monsters, cook_their_butts, where_get_radios, well_go_get_them_now, we_will_transfer_now, what_will_you_give_us, before_radios_we_need_info, no_but_well_help0, no_but_well_help1, yes_this_is_supply_ship, what_slave_planet, i_lied, plumb_out, we_are_vindicator0, we_are_vindicator1, we_are_vindicator2, first_give_info, we_must_go_now, where_can_i_get_radios, ok_i_will_get_radios, whats_this_starbase, what_about_earth, where_are_urquan, our_mission_was_secret, we_are_here_to_help, tell_me_about_base, we_will_take_care_of_base, tell_me_again, base_was_abandoned, we_fought_them, oh_yes_big_fight, i_lied_it_was_abandoned, i_cant_talk_about_it, name_1, name_2, name_3, name_40, name_41, i_lost_my_lander, i_lost_another_lander, need_fuel_mercury, need_fuel_luna, need_fuel_again, what_was_red_thing, it_went_away, we_destroyed_it, what_probe, take_care_of_base_again, goodbye_commander, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/comandr/igfxres.h0000600000175000017500000000005210543202022017770 0ustar joeyjoey#define COMMANDER_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/comandr/istrtab.h0000600000175000017500000000021710543202022017774 0ustar joeyjoey#define COMMANDER_COLOR_MAP 0x00200004L #define COMMANDER_CONVERSATION_PHRASES 0x00400104L #define STARBASE_CONVERSATION_PHRASES 0x00600204L uqm-0.6.2/sc2/src/sc2code/comm/comandr/imusicre.h0000600000175000017500000000017010543202021020141 0ustar joeyjoey#define COMMANDER_MUSIC 0x00200006L #define STARBASE_ALT_MUSIC 0x00800106L #define COMMANDER_LOWPOW_MUSIC 0x00a00206L uqm-0.6.2/sc2/src/sc2code/comm/comandr/comandr.c0000600000175000017500000004154710543202021017754 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "setup.h" #include "comm/commall.h" #include "comm/comandr/resinst.h" #include "comm/comandr/strings.h" #include "libs/graphics/gfx_common.h" static LOCDATA commander_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)COMMANDER_PMAP_ANIM, /* AlienFrame */ (FONT)COMMANDER_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_MIDDLE, /* AlienTextValign */ COMMANDER_COLOR_MAP, /* AlienColorMap */ COMMANDER_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ COMMANDER_CONVERSATION_PHRASES, /* PlayerPhrases */ 3, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { /* Blink */ 1, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ 0, ONE_SECOND * 8, /* RestartRate */ 0, /* BlockMask */ }, { /* Running light */ 10, /* StartIndex */ 30, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ ONE_SECOND * 2, 0, /* RestartRate */ 0, /* BlockMask */ }, { 1, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM | COLORXFORM_ANIM,/* AnimFlags */ 0, ONE_SECOND / 30, /* FrameRate */ 0, ONE_SECOND / 15, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 4, /* StartIndex */ 6, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 7 / 60, ONE_SECOND / 12, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void ByeBye (RESPONSE_REF R) { if (PLAYER_SAID (R, ok_i_will_get_radios)) NPCPhrase (THANKS_FOR_HELPING); else if (PLAYER_SAID (R, well_go_get_them_now)) NPCPhrase (GLAD_WHEN_YOU_COME_BACK); else if (PLAYER_SAID (R, we_will_take_care_of_base)) { NPCPhrase (GOOD_LUCK_WITH_BASE); SET_GAME_STATE (WILL_DESTROY_BASE, 1); } else if (PLAYER_SAID (R, take_care_of_base_again)) NPCPhrase (GOOD_LUCK_AGAIN); else if (PLAYER_SAID (R, base_was_abandoned) || PLAYER_SAID (R, i_lied_it_was_abandoned)) { NPCPhrase (IT_WAS_ABANDONED); NPCPhrase (HERE_COMES_ILWRATH); SET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER, 1); } else if (PLAYER_SAID (R, oh_yes_big_fight)) { NPCPhrase (IM_GLAD_YOU_WON); NPCPhrase (HERE_COMES_ILWRATH); SET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER, 1); } else if (PLAYER_SAID (R, i_cant_talk_about_it)) { NPCPhrase (IM_SURE_IT_WAS_DIFFICULT); NPCPhrase (HERE_COMES_ILWRATH); SET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER, 1); } else if (PLAYER_SAID (R, cook_their_butts) || PLAYER_SAID (R, overthrow_evil_aliens) || PLAYER_SAID (R, annihilate_those_monsters)) { SET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER, 0); if (PLAYER_SAID (R, cook_their_butts)) NPCPhrase (COOK_BUTTS); else if (PLAYER_SAID (R, overthrow_evil_aliens)) NPCPhrase (OVERTHROW_ALIENS); else /* if (R == annihilate_those_monsters) */ NPCPhrase (KILL_MONSTERS); construct_response (shared_phrase_buf, name_40, GLOBAL_SIS (CommanderName), name_41, NULL_PTR); NPCPhrase (THIS_MAY_SEEM_SILLY); Response (name_1, ByeBye); Response (name_2, ByeBye); Response (name_3, ByeBye); DoResponsePhrase (name_40, ByeBye, shared_phrase_buf); SET_GAME_STATE (STARBASE_AVAILABLE, 1); } else { if (PLAYER_SAID (R, name_1)) { NPCPhrase (OK_THE_NAFS); SET_GAME_STATE (NEW_ALLIANCE_NAME, 0); } else if (PLAYER_SAID (R, name_2)) { NPCPhrase (OK_THE_CAN); SET_GAME_STATE (NEW_ALLIANCE_NAME, 1); } else if (PLAYER_SAID (R, name_3)) { NPCPhrase (OK_THE_UFW); SET_GAME_STATE (NEW_ALLIANCE_NAME, 2); } else /* if (PLAYER_SAID (R, name_4)) */ { NPCPhrase (OK_THE_NAME_IS_EMPIRE0); NPCPhrase (GLOBAL_PLAYER_NAME); NPCPhrase (OK_THE_NAME_IS_EMPIRE1); SET_GAME_STATE (NEW_ALLIANCE_NAME, 3); } NPCPhrase (STARBASE_WILL_BE_READY); } } static void GiveRadios (RESPONSE_REF R); static void NoRadioactives (RESPONSE_REF R) { if (PLAYER_SAID (R, yes_this_is_supply_ship)) { NPCPhrase (ABOUT_TIME); if (GLOBAL_SIS (ElementAmounts[RADIOACTIVE])) GiveRadios (NULL_PTR); else { Response (i_lied, NoRadioactives); Response (plumb_out, NoRadioactives); } } else { if (PLAYER_SAID (R, where_can_i_get_radios)) { NPCPhrase (RADIOS_ON_MERCURY); DISABLE_PHRASE (where_can_i_get_radios); } else if (PLAYER_SAID (R, no_but_well_help0)) NPCPhrase (THE_WHAT_FROM_WHERE); else if (PLAYER_SAID (R, what_slave_planet) || PLAYER_SAID (R, i_lied)) NPCPhrase (DONT_KNOW_WHO_YOU_ARE); else if (PLAYER_SAID (R, plumb_out)) NPCPhrase (WHAT_KIND_OF_IDIOT); else if (PLAYER_SAID (R, i_lost_my_lander)) { NPCPhrase (HERE_IS_A_NEW_LANDER); ++GLOBAL_SIS (NumLanders); LockMutex (GraphicsLock); DrawLanders (); DeltaSISGauges (4, 0, 0); UnlockMutex (GraphicsLock); SET_GAME_STATE (LANDERS_LOST, 1); } else if (PLAYER_SAID (R, i_lost_another_lander)) { NPCPhrase (HERE_IS_ANOTHER_LANDER); ++GLOBAL_SIS (NumLanders); LockMutex (GraphicsLock); DrawLanders (); DeltaSISGauges (4, 0, 0); UnlockMutex (GraphicsLock); } else if (PLAYER_SAID (R, need_fuel_mercury) || PLAYER_SAID (R, need_fuel_luna)) { NPCPhrase (GIVE_FUEL); LockMutex (GraphicsLock); DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); UnlockMutex (GraphicsLock); SET_GAME_STATE (GIVEN_FUEL_BEFORE, 1); } else if (PLAYER_SAID (R, need_fuel_again)) { NPCPhrase (GIVE_FUEL_AGAIN); LockMutex (GraphicsLock); DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); UnlockMutex (GraphicsLock); } if (GLOBAL_SIS (ElementAmounts[RADIOACTIVE])) GiveRadios (NULL_PTR); else { if (GLOBAL_SIS (NumLanders) == 0 && GET_GAME_STATE (CHMMR_BOMB_STATE) < 2) { if (GET_GAME_STATE (LANDERS_LOST)) Response (i_lost_another_lander, NoRadioactives); else Response (i_lost_my_lander, NoRadioactives); } if (GLOBAL_SIS (FuelOnBoard) < 2 * FUEL_TANK_SCALE) { if (GET_GAME_STATE (GIVEN_FUEL_BEFORE)) Response (need_fuel_again, NoRadioactives); else Response (need_fuel_mercury, NoRadioactives); } Response (ok_i_will_get_radios, ByeBye); if (PHRASE_ENABLED (where_can_i_get_radios)) { Response (where_can_i_get_radios, NoRadioactives); } } } } static void AskAfterRadios (RESPONSE_REF R) { if (PLAYER_SAID (R, i_lost_my_lander)) { NPCPhrase (HERE_IS_A_NEW_LANDER); ++GLOBAL_SIS (NumLanders); LockMutex (GraphicsLock); DrawLanders (); DeltaSISGauges (4, 0, 0); UnlockMutex (GraphicsLock); SET_GAME_STATE (LANDERS_LOST, 1); } else if (PLAYER_SAID (R, i_lost_another_lander)) { NPCPhrase (HERE_IS_ANOTHER_LANDER); ++GLOBAL_SIS (NumLanders); LockMutex (GraphicsLock); DrawLanders (); DeltaSISGauges (4, 0, 0); UnlockMutex (GraphicsLock); } else if (PLAYER_SAID (R, need_fuel_mercury) || PLAYER_SAID (R, need_fuel_luna)) { NPCPhrase (GIVE_FUEL); LockMutex (GraphicsLock); DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); UnlockMutex (GraphicsLock); SET_GAME_STATE (GIVEN_FUEL_BEFORE, 1); } else if (PLAYER_SAID (R, need_fuel_again)) { NPCPhrase (GIVE_FUEL_AGAIN); LockMutex (GraphicsLock); DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); UnlockMutex (GraphicsLock); } else if (PLAYER_SAID (R, where_get_radios)) { NPCPhrase (RADIOS_ON_MERCURY); DISABLE_PHRASE (where_get_radios); } { if (GLOBAL_SIS (NumLanders) == 0 && GET_GAME_STATE (CHMMR_BOMB_STATE) < 2) { if (GET_GAME_STATE (LANDERS_LOST)) Response (i_lost_another_lander, AskAfterRadios); else Response (i_lost_my_lander, AskAfterRadios); } if (GLOBAL_SIS (FuelOnBoard) < 2 * FUEL_TANK_SCALE) { if (GET_GAME_STATE (GIVEN_FUEL_BEFORE)) Response (need_fuel_again, AskAfterRadios); else Response (need_fuel_mercury, AskAfterRadios); } Response (well_go_get_them_now, ByeBye); if (PHRASE_ENABLED (where_get_radios)) { Response (where_get_radios, AskAfterRadios); } } } static void BaseDestroyed (RESPONSE_REF R) { if (PLAYER_SAID (R, we_fought_them)) { NPCPhrase (YOU_REALLY_FOUGHT_BASE); Response (oh_yes_big_fight, ByeBye); Response (i_lied_it_was_abandoned, ByeBye); Response (i_cant_talk_about_it, ByeBye); } else { if (PLAYER_SAID (R, we_are_here_to_help)) { NPCPhrase (BASE_ON_MOON); } else { NPCPhrase (DEALT_WITH_BASE_YET); } Response (base_was_abandoned, ByeBye); Response (we_fought_them, BaseDestroyed); } } static void TellMoonBase (RESPONSE_REF R) { if (R == 0) { NPCPhrase (DEALT_WITH_BASE_YET); } else if (PLAYER_SAID (R, i_lost_my_lander)) { NPCPhrase (HERE_IS_A_NEW_LANDER); ++GLOBAL_SIS (NumLanders); LockMutex (GraphicsLock); DrawLanders (); DeltaSISGauges (4, 0, 0); UnlockMutex (GraphicsLock); SET_GAME_STATE (LANDERS_LOST, 1); } else if (PLAYER_SAID (R, i_lost_another_lander)) { NPCPhrase (HERE_IS_ANOTHER_LANDER); ++GLOBAL_SIS (NumLanders); LockMutex (GraphicsLock); DrawLanders (); DeltaSISGauges (4, 0, 0); UnlockMutex (GraphicsLock); } else if (PLAYER_SAID (R, need_fuel_mercury) || PLAYER_SAID (R, need_fuel_luna)) { NPCPhrase (GIVE_FUEL); LockMutex (GraphicsLock); DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); UnlockMutex (GraphicsLock); SET_GAME_STATE (GIVEN_FUEL_BEFORE, 1); } else if (PLAYER_SAID (R, need_fuel_again)) { NPCPhrase (GIVE_FUEL_AGAIN); LockMutex (GraphicsLock); DeltaSISGauges (0, 5 * FUEL_TANK_SCALE, 0); UnlockMutex (GraphicsLock); } else if (PLAYER_SAID (R, we_are_here_to_help)) { NPCPhrase (BASE_ON_MOON); } else if (GET_GAME_STATE (STARBASE_YACK_STACK1) == 0) { NPCPhrase (ABOUT_BASE); SET_GAME_STATE (STARBASE_YACK_STACK1, 1); } else { NPCPhrase (ABOUT_BASE_AGAIN); } if (GLOBAL_SIS (NumLanders) == 0 && GET_GAME_STATE (CHMMR_BOMB_STATE) < 2) { if (GET_GAME_STATE (LANDERS_LOST)) Response (i_lost_another_lander, TellMoonBase); else Response (i_lost_my_lander, TellMoonBase); } if (GLOBAL_SIS (FuelOnBoard) < 2 * FUEL_TANK_SCALE) { if (GET_GAME_STATE (GIVEN_FUEL_BEFORE)) Response (need_fuel_again, TellMoonBase); else Response (need_fuel_luna, TellMoonBase); } if (GET_GAME_STATE (WILL_DESTROY_BASE) == 0) Response (we_will_take_care_of_base, ByeBye); else Response (take_care_of_base_again, ByeBye); if (GET_GAME_STATE (STARBASE_YACK_STACK1) == 0) Response (tell_me_about_base, TellMoonBase); else Response (tell_me_again, TellMoonBase); } static void RevealSelf (RESPONSE_REF R); static void TellProbe (RESPONSE_REF R) { (void) R; // ignored NPCPhrase (THAT_WAS_PROBE); DISABLE_PHRASE (what_was_red_thing); Response (it_went_away, RevealSelf); Response (we_destroyed_it, RevealSelf); Response (what_probe, RevealSelf); } static void RevealSelf (RESPONSE_REF R) { BYTE i, stack; stack = 0; if (PLAYER_SAID (R, we_are_vindicator0)) { NPCPhrase (THATS_IMPOSSIBLE); DISABLE_PHRASE (we_are_vindicator0); } else if (PLAYER_SAID (R, our_mission_was_secret)) { NPCPhrase (ACKNOWLEDGE_SECRET); DISABLE_PHRASE (our_mission_was_secret); } else if (PLAYER_SAID (R, first_give_info)) { NPCPhrase (ASK_AWAY); stack = 1; DISABLE_PHRASE (first_give_info); } else if (PLAYER_SAID (R, whats_this_starbase)) { NPCPhrase (STARBASE_IS); stack = 1; DISABLE_PHRASE (whats_this_starbase); } else if (PLAYER_SAID (R, what_about_earth)) { NPCPhrase (HAPPENED_TO_EARTH); stack = 1; DISABLE_PHRASE (what_about_earth); } else if (PLAYER_SAID (R, where_are_urquan)) { NPCPhrase (URQUAN_LEFT); stack = 1; DISABLE_PHRASE (where_are_urquan); } else if (PLAYER_SAID (R, it_went_away)) NPCPhrase (DEEP_TROUBLE); else if (PLAYER_SAID (R, we_destroyed_it)) NPCPhrase (GOOD_NEWS); else if (PLAYER_SAID (R, what_probe)) NPCPhrase (SURE_HOPE); for (i = 0; i < 2; ++i, stack ^= 1) { if (stack == 1) { if (PHRASE_ENABLED (first_give_info)) Response (first_give_info, RevealSelf); else if (PHRASE_ENABLED (whats_this_starbase)) Response (whats_this_starbase, RevealSelf); else if (PHRASE_ENABLED (what_about_earth)) Response (what_about_earth, RevealSelf); else if (PHRASE_ENABLED (where_are_urquan)) Response (where_are_urquan, RevealSelf); else if (PHRASE_ENABLED (what_was_red_thing)) { Response (what_was_red_thing, TellProbe); } } else { if (PHRASE_ENABLED (we_are_vindicator0)) { construct_response (shared_phrase_buf, we_are_vindicator0, GLOBAL_SIS (CommanderName), we_are_vindicator1, GLOBAL_SIS (ShipName), we_are_vindicator2, NULL_PTR); DoResponsePhrase (we_are_vindicator0, RevealSelf, shared_phrase_buf); } else if (PHRASE_ENABLED (our_mission_was_secret)) Response (our_mission_was_secret, RevealSelf); else { if (GET_GAME_STATE (MOONBASE_DESTROYED) == 0) Response (we_are_here_to_help, TellMoonBase); else Response (we_are_here_to_help, BaseDestroyed); } } } } static void GiveRadios (RESPONSE_REF R) { if (PLAYER_SAID (R, we_will_transfer_now)) { SET_GAME_STATE (RADIOACTIVES_PROVIDED, 1); NPCPhrase (FUEL_UP0); NPCPhrase (FUEL_UP1); AlienTalkSegue (1); LockMutex (GraphicsLock); CommData.AlienAmbientArray[2].AnimFlags |= ANIM_DISABLED; UnlockMutex (GraphicsLock); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 0) ), ONE_SECOND / 2); AlienTalkSegue ((COUNT)~0); RevealSelf (NULL_PTR); } else { if (PLAYER_SAID (R, what_will_you_give_us)) NPCPhrase (MESSAGE_GARBLED_1); else if (PLAYER_SAID (R, before_radios_we_need_info)) NPCPhrase (MESSAGE_GARBLED_2); Response (we_will_transfer_now, GiveRadios); Response (what_will_you_give_us, GiveRadios); Response (before_radios_we_need_info, GiveRadios); } } static void Intro (void) { if (GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER)) { NPCPhrase (VERY_IMPRESSIVE); Response (cook_their_butts, ByeBye); Response (overthrow_evil_aliens, ByeBye); Response (annihilate_those_monsters, ByeBye); } else if (GET_GAME_STATE (STARBASE_VISITED)) { if (GET_GAME_STATE (RADIOACTIVES_PROVIDED)) { if (GET_GAME_STATE (MOONBASE_DESTROYED) == 0) { TellMoonBase (NULL_PTR); } else { BaseDestroyed (NULL_PTR); } } else { CommData.AlienColorMap = SetAbsColorMapIndex (CommData.AlienColorMap, 1); NPCPhrase (DO_YOU_HAVE_RADIO_THIS_TIME); if (GLOBAL_SIS (ElementAmounts[RADIOACTIVE])) GiveRadios (NULL_PTR); else AskAfterRadios (NULL_PTR); } } else /* first visit */ { CommData.AlienColorMap = SetAbsColorMapIndex (CommData.AlienColorMap, 1); SET_GAME_STATE (STARBASE_VISITED, 1); NPCPhrase (ARE_YOU_SUPPLY_SHIP); construct_response ( shared_phrase_buf, no_but_well_help0, GLOBAL_SIS (ShipName), no_but_well_help1, NULL_PTR ); DoResponsePhrase (no_but_well_help0, NoRadioactives, shared_phrase_buf); Response (yes_this_is_supply_ship, NoRadioactives); Response (what_slave_planet, NoRadioactives); } } static COUNT uninit_commander (void) { return (0); } static void post_commander_enc (void) { // nothing defined so far } LOCDATAPTR init_commander_comm () { LOCDATAPTR retval; commander_desc.init_encounter_func = Intro; commander_desc.post_encounter_func = post_commander_enc; commander_desc.uninit_encounter_func = uninit_commander; if (GET_GAME_STATE (RADIOACTIVES_PROVIDED)) { commander_desc.AlienAmbientArray[2].AnimFlags |= ANIM_DISABLED; // regular track -- let's make sure commander_desc.AlienSongFlags &= ~LDASF_USE_ALTERNATE; } else { commander_desc.AlienAmbientArray[2].AnimFlags &= ~ANIM_DISABLED; // use alternate 'low-power' track if available commander_desc.AlienAltSong = COMMANDER_LOWPOW_MUSIC; commander_desc.AlienSongFlags |= LDASF_USE_ALTERNATE; } commander_desc.AlienTextWidth = 143; commander_desc.AlienTextBaseline.x = 164; commander_desc.AlienTextBaseline.y = 20; SET_GAME_STATE (BATTLE_SEGUE, 0); retval = &commander_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/comandr/Makeinfo0000600000175000017500000000002710543202021017625 0ustar joeyjoeyuqm_CFILES="comandr.c" uqm-0.6.2/sc2/src/sc2code/comm/comandr/respkg.h0000600000175000017500000000021410543202021017613 0ustar joeyjoeyenum { COMMANDER_PACKAGE = 1, COMMANDER_PHRASE_PACKAGE, STARBASE_PHRASE_PACKAGE, STARBASE_MUSIC_PACKAGE, COMMANDER_LOWPOW_PACKAGE, }; uqm-0.6.2/sc2/src/sc2code/comm/comandr/comandr.res0000600000175000017500000000072110543202022020311 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/comandr PACKAGE COMMANDER_PACKAGE comandr.con GFXRES COMMANDER_PMAP_ANIM comandr.ani FONTRES COMMANDER_FONT comandr.fon MUSICRES COMMANDER_MUSIC comandr.mod STRTAB COMMANDER_COLOR_MAP comandr.ct PACKAGE COMMANDER_PHRASE_PACKAGE comandr.con STRTAB COMMANDER_CONVERSATION_PHRASES comandr.txt PATH comm/starbas PACKAGE STARBASE_PHRASE_PACKAGE comandr.con STRTAB STARBASE_CONVERSATION_PHRASES starbas.txt uqm-0.6.2/sc2/src/sc2code/comm/comandr/resinst.h0000600000175000017500000000012610543202022020012 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/spahome/0000755000175000017500000000000010552600275016210 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/spahome/spahome.c0000600000175000017500000005467310543202025020006 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/spathi/resinst.h" #include "comm/spahome/strings.h" #include "build.h" #include "gameev.h" static LOCDATA spahome_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)SPATHI_HOME_PMAP_ANIM, /* AlienFrame */ (FONT)SPATHI_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)SPATHI_HOME_COLOR_MAP, /* AlienColorMap */ SPATHI_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ SPATHI_HOME_CONVERSATION_PHRASES, /* PlayerPhrases */ 14, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 1, /* StartIndex */ 3, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 4, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 9, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 10) | (1 << 11), /* BlockMask */ }, { 13, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND / 20, 0, /* RestartRate */ (1 << 4) | (1 << 5) /* BlockMask */ }, { 19, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 3) | (1 << 5), /* BlockMask */ }, { 22, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 10, ONE_SECOND / 30, /* RestartRate */ (1 << 3) | (1 << 4) | (1 << 10), /* BlockMask */ }, { 26, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ (1 << 10), /* BlockMask */ }, { 29, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 32, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND / 20, 0, /* RestartRate */ (1 << 9) | (1 << 10), /* BlockMask */ }, { 39, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 8) | (1 << 10), /* BlockMask */ }, { 42, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, 0, /* RestartRate */ (1 << 8) | (1 << 9) | (1 << 6) | (1 << 2) | (1 << 11) | (1 << 5), /* BlockMask */ }, { 46, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 10, ONE_SECOND / 30, /* RestartRate */ (1 << 2) | (1 << 10), /* BlockMask */ }, { 50, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND / 20, 0, /* RestartRate */ (1 << 13), /* BlockMask */ }, { 56, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 12), /* BlockMask */ }, }, { /* AlienTransitionDesc - empty */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc - empty */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (PLAYER_SAID (R, we_attack_again)) { NPCPhrase (WE_FIGHT_AGAIN); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, surrender_or_die)) { NPCPhrase (DEFEND_OURSELVES); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, we_are_vindicator0)) { NPCPhrase (NO_PASSWORD); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, gort_merenga) || PLAYER_SAID (R, guph_florp) || PLAYER_SAID (R, wagngl_fthagn) || PLAYER_SAID (R, pleeese)) { NPCPhrase (WRONG_PASSWORD); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, screw_password)) { NPCPhrase (NO_PASSWORD); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, bye_no_ally_offer)) NPCPhrase (GOODBYE_NO_ALLY_OFFER); else if (PLAYER_SAID (R, bye_angry_spathi)) NPCPhrase (GOODBYE_ANGRY_SPATHI); else if (PLAYER_SAID (R, bye_ally)) NPCPhrase (GOODBYE_ALLY); else if (PLAYER_SAID (R, already_got_them)) { NPCPhrase (EARLY_BIRD_CHECK); SET_GAME_STATE (SPATHI_HOME_VISITS, 0); SET_GAME_STATE (SPATHI_VISITS, 0); SET_GAME_STATE (SPATHI_PARTY, 1); SET_GAME_STATE (SPATHI_MANNER, 3); } else if (PLAYER_SAID (R, too_dangerous)) NPCPhrase (WE_AGREE); else if (PLAYER_SAID (R, think_more)) NPCPhrase (COWARD); else if (PLAYER_SAID (R, i_accept)) { NPCPhrase (AWAIT_RETURN); SET_GAME_STATE (SPATHI_QUEST, 1); SET_GAME_STATE (SPATHI_MANNER, 3); SET_GAME_STATE (SPATHI_VISITS, 0); } else if (PLAYER_SAID (R, do_as_we_say)) { NPCPhrase (DEPART_FOR_EARTH); ActivateStarShip (SPATHI_SHIP, 0); AddEvent (RELATIVE_EVENT, 6, 0, 0, SPATHI_SHIELD_EVENT); SET_GAME_STATE (SPATHI_HOME_VISITS, 0); SET_GAME_STATE (SPATHI_VISITS, 0); } else if (PLAYER_SAID (R, killed_them_all_1)) { NPCPhrase (WILL_CHECK_1); if (!GET_GAME_STATE (SPATHI_CREATURES_ELIMINATED)) { SET_GAME_STATE (LIED_ABOUT_CREATURES, 1); } else { SET_GAME_STATE (SPATHI_HOME_VISITS, 0); SET_GAME_STATE (SPATHI_VISITS, 0); SET_GAME_STATE (SPATHI_PARTY, 1); SET_GAME_STATE (SPATHI_MANNER, 3); } } else if (PLAYER_SAID (R, killed_them_all_2)) { NPCPhrase (WILL_CHECK_2); if (!GET_GAME_STATE (SPATHI_CREATURES_ELIMINATED)) { SET_GAME_STATE (LIED_ABOUT_CREATURES, 2); } else { SET_GAME_STATE (SPATHI_HOME_VISITS, 0); SET_GAME_STATE (SPATHI_VISITS, 0); SET_GAME_STATE (SPATHI_PARTY, 1); SET_GAME_STATE (SPATHI_MANNER, 3); } } else if (PLAYER_SAID (R, bye_before_party)) { NPCPhrase (GOODBYE_BEFORE_PARTY); } else if (PLAYER_SAID (R, bye_from_party_1) || PLAYER_SAID (R, bye_from_party_2) || PLAYER_SAID (R, bye_from_party_3)) { NPCPhrase (GOODBYE_FROM_PARTY); } } static void SpathiAllies (RESPONSE_REF R); static void SpathiInfo (RESPONSE_REF R) { BYTE InfoLeft; InfoLeft = FALSE; if (PLAYER_SAID (R, like_some_info)) NPCPhrase (WHAT_ABOUT); else if (PLAYER_SAID (R, what_about_hierarchy)) { NPCPhrase (ABOUT_HIERARCHY); DISABLE_PHRASE (what_about_hierarchy); } else if (PLAYER_SAID (R, what_about_history)) { NPCPhrase (ABOUT_HISTORY); DISABLE_PHRASE (what_about_history); } else if (PLAYER_SAID (R, what_about_alliance)) { NPCPhrase (ABOUT_ALLIANCE); DISABLE_PHRASE (what_about_alliance); } else if (PLAYER_SAID (R, what_about_other)) { NPCPhrase (ABOUT_OTHER); DISABLE_PHRASE (what_about_other); } else if (PLAYER_SAID (R, what_about_precursors)) { NPCPhrase (ABOUT_PRECURSORS); DISABLE_PHRASE (what_about_precursors); } if (PHRASE_ENABLED (what_about_hierarchy)) { InfoLeft = TRUE; Response (what_about_hierarchy, SpathiInfo); } if (PHRASE_ENABLED (what_about_history)) { InfoLeft = TRUE; Response (what_about_history, SpathiInfo); } if (PHRASE_ENABLED (what_about_alliance)) { InfoLeft = TRUE; Response (what_about_alliance, SpathiInfo); } if (PHRASE_ENABLED (what_about_other)) { InfoLeft = TRUE; Response (what_about_other, SpathiInfo); } if (PHRASE_ENABLED (what_about_precursors)) { InfoLeft = TRUE; Response (what_about_precursors, SpathiInfo); } Response (enough_info, SpathiAllies); if (!InfoLeft) { DISABLE_PHRASE (like_some_info); } } static void SpathiAllies (RESPONSE_REF R) { BYTE NumVisits; if (R == 0) { NumVisits = GET_GAME_STATE (SPATHI_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_ALLIES_1); break; case 1: NPCPhrase (HELLO_ALLIES_2); break; case 2: NPCPhrase (HELLO_ALLIES_3); --NumVisits; break; } SET_GAME_STATE (SPATHI_HOME_VISITS, NumVisits); } else if (PLAYER_SAID (R, whats_up)) { NumVisits = GET_GAME_STATE (SPATHI_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_1); break; case 1: NPCPhrase (GENERAL_INFO_2); break; case 2: NPCPhrase (GENERAL_INFO_3); SET_GAME_STATE (KNOW_URQUAN_STORY, 1); SET_GAME_STATE (KNOW_KOHR_AH_STORY, 1); break; case 3: NPCPhrase (GENERAL_INFO_4); break; case 4: NPCPhrase (GENERAL_INFO_5); --NumVisits; break; case 5: NPCPhrase (GENERAL_INFO_5); --NumVisits; break; } SET_GAME_STATE (SPATHI_INFO, NumVisits); DISABLE_PHRASE (whats_up); } else if (PLAYER_SAID (R, resources_please)) { NPCPhrase (SORRY_NO_RESOURCES); DISABLE_PHRASE (resources_please); } else if (PLAYER_SAID (R, something_fishy)) { NPCPhrase (NOTHING_FISHY); SET_GAME_STATE (SPATHI_INFO, 5); } else if (PLAYER_SAID (R, enough_info)) NPCPhrase (OK_ENOUGH_INFO); if (GET_GAME_STATE (SPATHI_INFO) == 4) Response (something_fishy, SpathiAllies); if (PHRASE_ENABLED (whats_up)) Response (whats_up, SpathiAllies); if (PHRASE_ENABLED (resources_please)) Response (resources_please, SpathiAllies); if (PHRASE_ENABLED (like_some_info)) Response (like_some_info, SpathiInfo); Response (bye_ally, ExitConversation); } static void SpathiQuest (RESPONSE_REF R) { if (R == 0) { if (!GET_GAME_STATE (LIED_ABOUT_CREATURES)) NPCPhrase (HOW_GO_EFFORTS); else NPCPhrase (YOU_LIED_1); } else if (PLAYER_SAID (R, little_mistake)) { NPCPhrase (BIG_MISTAKE); DISABLE_PHRASE (little_mistake); } else if (PLAYER_SAID (R, talk_test)) { NPCPhrase (TEST_AGAIN); DISABLE_PHRASE (talk_test); } else if (PLAYER_SAID (R, zapped_a_few)) { NPCPhrase (YOU_FORTUNATE); DISABLE_PHRASE (zapped_a_few); } if (!GET_GAME_STATE (LIED_ABOUT_CREATURES)) Response (killed_them_all_1, ExitConversation); else { if (PHRASE_ENABLED (little_mistake)) { Response (little_mistake, SpathiQuest); } Response (killed_them_all_2, ExitConversation); } if (!GET_GAME_STATE (SPATHI_CREATURES_ELIMINATED)) { if (PHRASE_ENABLED (talk_test)) { Response (talk_test, SpathiQuest); } if (PHRASE_ENABLED (zapped_a_few) && GET_GAME_STATE (SPATHI_CREATURES_EXAMINED)) { Response (zapped_a_few, SpathiQuest); } Response (bye_before_party, ExitConversation); } } static void LearnQuest (RESPONSE_REF R) { if (R == 0) { NPCPhrase (QUEST_AGAIN); DISABLE_PHRASE (what_test); if (GET_GAME_STATE (KNOW_SPATHI_EVIL)) { DISABLE_PHRASE (tell_evil); } } else if (PLAYER_SAID (R, how_prove)) NPCPhrase (BETTER_IDEA); else if (PLAYER_SAID (R, what_test)) { NPCPhrase (WIPE_EVIL); SET_GAME_STATE (KNOW_SPATHI_QUEST, 1); DISABLE_PHRASE (what_test); } else if (PLAYER_SAID (R, tell_evil)) { NPCPhrase (BEFORE_ACCEPT); SET_GAME_STATE (KNOW_SPATHI_EVIL, 1); DISABLE_PHRASE (tell_evil); DISABLE_PHRASE (prove_strength); } else if (PLAYER_SAID (R, prove_strength)) { NPCPhrase (YOUR_BEHAVIOR); DISABLE_PHRASE (prove_strength); } else if (PLAYER_SAID (R, why_dont_you_do_it)) { NPCPhrase (WE_WONT_BECAUSE); DISABLE_PHRASE (why_dont_you_do_it); } if (PHRASE_ENABLED (what_test)) Response (what_test, LearnQuest); else if (GET_GAME_STATE (SPATHI_CREATURES_ELIMINATED)) { Response (already_got_them, ExitConversation); } else if (PHRASE_ENABLED (tell_evil)) { Response (too_dangerous, ExitConversation); Response (tell_evil, LearnQuest); } else { Response (too_dangerous, ExitConversation); Response (think_more, ExitConversation); Response (i_accept, ExitConversation); } if (PHRASE_ENABLED (prove_strength) && !GET_GAME_STATE (KNOW_SPATHI_QUEST)) Response (prove_strength, LearnQuest); if (PHRASE_ENABLED (why_dont_you_do_it)) Response (why_dont_you_do_it, LearnQuest); } static void AllianceOffer (RESPONSE_REF R) { if (PLAYER_SAID (R, misunderstanding)) { NPCPhrase (JUST_MISUNDERSTANDING); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 1) ), ONE_SECOND / 4); SET_GAME_STATE (SPATHI_MANNER, 3); SET_GAME_STATE (SPATHI_VISITS, 0); } else if (PLAYER_SAID (R, we_come_in_peace)) NPCPhrase (OF_COURSE); else if (PLAYER_SAID (R, hand_in_friendship)) { NPCPhrase (TOO_AFRAID); DISABLE_PHRASE (hand_in_friendship); } else if (PLAYER_SAID (R, stronger)) { NPCPhrase (YOURE_NOT); DISABLE_PHRASE (stronger); } else if (PLAYER_SAID (R, yes_we_are)) { NPCPhrase (NO_YOURE_NOT); DISABLE_PHRASE (yes_we_are); } else if (PLAYER_SAID (R, share_info)) { NPCPhrase (NO_INFO); DISABLE_PHRASE (share_info); } else if (PLAYER_SAID (R, give_us_resources)) { NPCPhrase (NO_RESOURCES); DISABLE_PHRASE (give_us_resources); } if (PHRASE_ENABLED (hand_in_friendship)) Response (hand_in_friendship, AllianceOffer); else if (PHRASE_ENABLED (stronger)) Response (stronger, AllianceOffer); else if (PHRASE_ENABLED (yes_we_are)) Response (yes_we_are, AllianceOffer); else { Response (how_prove, LearnQuest); } if (PHRASE_ENABLED (share_info)) Response (share_info, AllianceOffer); if (PHRASE_ENABLED (give_us_resources)) Response (give_us_resources, AllianceOffer); } static void SpathiAngry (RESPONSE_REF R) { if (R == 0) { NPCPhrase (MEAN_GUYS_RETURN); Response (we_apologize, SpathiAngry); } else /* if (R == we_apologize) */ { NPCPhrase (DONT_BELIEVE); Response (misunderstanding, AllianceOffer); } Response (we_attack_again, ExitConversation); Response (bye_angry_spathi, ExitConversation); } static void SpathiParty (RESPONSE_REF R) { if (R == 0) { BYTE NumVisits; NumVisits = GET_GAME_STATE (SPATHI_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (MUST_PARTY_1); break; case 1: NPCPhrase (MUST_PARTY_2); break; case 2: NPCPhrase (MUST_PARTY_3); --NumVisits; break; } SET_GAME_STATE (SPATHI_HOME_VISITS, NumVisits); } else if (PLAYER_SAID (R, deals_a_deal)) { NPCPhrase (WAIT_A_WHILE); DISABLE_PHRASE (deals_a_deal); } else if (PLAYER_SAID (R, how_long)) { NPCPhrase (TEN_YEARS); DISABLE_PHRASE (how_long); } else if (PLAYER_SAID (R, reneging)) { NPCPhrase (ADULT_VIEW); DISABLE_PHRASE (reneging); } else if (PLAYER_SAID (R, return_beasts)) { NPCPhrase (WHAT_RELATIONSHIP); DISABLE_PHRASE (return_beasts); } else if (PLAYER_SAID (R, minds_and_might)) { NPCPhrase (HUH); DISABLE_PHRASE (minds_and_might); } else if (PLAYER_SAID (R, fellowship)) { NPCPhrase (WHAT); DISABLE_PHRASE (fellowship); } if (PHRASE_ENABLED (deals_a_deal)) Response (deals_a_deal, SpathiParty); else if (PHRASE_ENABLED (how_long)) Response (how_long, SpathiParty); else if (PHRASE_ENABLED (reneging)) Response (reneging, SpathiParty); else if (PHRASE_ENABLED (return_beasts)) Response (return_beasts, SpathiParty); else { if (PHRASE_ENABLED (minds_and_might)) Response (minds_and_might, SpathiParty); if (PHRASE_ENABLED (fellowship)) Response (fellowship, SpathiParty); Response (do_as_we_say, ExitConversation); return; } switch (GET_GAME_STATE (SPATHI_HOME_VISITS) - 1) { case 0: Response (bye_from_party_1, ExitConversation); break; case 1: Response (bye_from_party_2, ExitConversation); break; default: Response (bye_from_party_3, ExitConversation); break; } } static void SpathiCouncil (RESPONSE_REF R) { if (R == 0) NPCPhrase (HELLO_AGAIN); else if (PLAYER_SAID (R, good_password)) { NPCPhrase (YES_GOOD_PASSWORD); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 1) ), ONE_SECOND / 4); SET_GAME_STATE (KNOW_SPATHI_PASSWORD, 1); SET_GAME_STATE (SPATHI_HOME_VISITS, 0); } else if (PLAYER_SAID (R, we_come_in_peace)) { NPCPhrase (KILLED_SPATHI); DISABLE_PHRASE (we_come_in_peace); } else if (PLAYER_SAID (R, spathi_on_pluto)) { NPCPhrase (WHERE_SPATHI); DISABLE_PHRASE (spathi_on_pluto); } else if (PLAYER_SAID (R, hostage)) { NPCPhrase (GUN_TO_HEAD); SET_GAME_STATE (FOUND_PLUTO_SPATHI, 3); DISABLE_PHRASE (hostage); } else if (PLAYER_SAID (R, killed_fwiffo)) { NPCPhrase (POOR_FWIFFO); SET_GAME_STATE (FOUND_PLUTO_SPATHI, 3); DISABLE_PHRASE (killed_fwiffo); } else if (PLAYER_SAID (R, fwiffo_fine)) { NPCPhrase (NOT_LIKELY); R = killed_fwiffo; DISABLE_PHRASE (fwiffo_fine); } else if (PLAYER_SAID (R, surrender)) { NPCPhrase (NO_SURRENDER); DISABLE_PHRASE (surrender); } if (GET_GAME_STATE (SPATHI_MANNER) == 0) { Response (we_come_in_peace, AllianceOffer); } else if (PHRASE_ENABLED (we_come_in_peace)) { Response (we_come_in_peace, SpathiCouncil); } else { Response (misunderstanding, AllianceOffer); } if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) && GET_GAME_STATE (FOUND_PLUTO_SPATHI) < 3) { if (PHRASE_ENABLED (spathi_on_pluto)) Response (spathi_on_pluto, SpathiCouncil); else if (ActivateStarShip (SPATHI_SHIP, ESCORTING_FLAGSHIP)) { if (PHRASE_ENABLED (hostage)) Response (hostage, SpathiCouncil); } else if (PHRASE_ENABLED (killed_fwiffo)) { Response (killed_fwiffo, SpathiCouncil); if (PHRASE_ENABLED (fwiffo_fine)) Response (fwiffo_fine, SpathiCouncil); } } if (PHRASE_ENABLED (surrender)) Response (surrender, SpathiCouncil); else { Response (surrender_or_die, ExitConversation); } Response (bye_no_ally_offer, ExitConversation); } static void SpathiPassword (RESPONSE_REF R) { if (R == 0) { BYTE NumVisits; NumVisits = GET_GAME_STATE (SPATHI_HOME_VISITS); switch (NumVisits++) { default: NPCPhrase (WHAT_IS_PASSWORD); NumVisits = 1; break; case 1: NPCPhrase (WHAT_IS_PASSWORD_AGAIN); --NumVisits; break; } SET_GAME_STATE (SPATHI_HOME_VISITS, NumVisits); } else if (PLAYER_SAID (R, what_do_i_get)) { NPCPhrase (YOU_GET_TO_LIVE); DISABLE_PHRASE (what_do_i_get); } if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) || GET_GAME_STATE (KNOW_SPATHI_PASSWORD)) { Response (good_password, SpathiCouncil); if (PHRASE_ENABLED (what_do_i_get)) { Response (what_do_i_get, SpathiPassword); } } else { construct_response (shared_phrase_buf, we_are_vindicator0, GLOBAL_SIS (CommanderName), we_are_vindicator1, GLOBAL_SIS (ShipName), we_are_vindicator2, NULL_PTR); DoResponsePhrase (we_are_vindicator0, ExitConversation, shared_phrase_buf); Response (gort_merenga, ExitConversation); Response (guph_florp, ExitConversation); Response (wagngl_fthagn, ExitConversation); Response (pleeese, ExitConversation); Response (screw_password, ExitConversation); } } static void Intro (void) { BYTE Manner; Manner = GET_GAME_STATE (SPATHI_MANNER); if (Manner == 2) { NPCPhrase (HATE_YOU_FOREVER); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (Manner == 1 && GET_GAME_STATE (KNOW_SPATHI_PASSWORD) && (GET_GAME_STATE (FOUND_PLUTO_SPATHI) || GET_GAME_STATE (SPATHI_HOME_VISITS) != 7)) { SpathiAngry ((RESPONSE_REF)0); } else if (ActivateStarShip (SPATHI_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { CommData.AlienColorMap = SetAbsColorMapIndex (CommData.AlienColorMap, 1); SpathiAllies ((RESPONSE_REF)0); } else if (GET_GAME_STATE (SPATHI_PARTY)) { CommData.AlienColorMap = SetAbsColorMapIndex (CommData.AlienColorMap, 1); SpathiParty ((RESPONSE_REF)0); } else if (GET_GAME_STATE (SPATHI_QUEST)) { if (GET_GAME_STATE (LIED_ABOUT_CREATURES) < 2) { CommData.AlienColorMap = SetAbsColorMapIndex (CommData.AlienColorMap, 1); SpathiQuest ((RESPONSE_REF)0); } else { NPCPhrase (YOU_LIED_2); SET_GAME_STATE (SPATHI_MANNER, 2); SET_GAME_STATE (BATTLE_SEGUE, 1); } } else if (GET_GAME_STATE (KNOW_SPATHI_QUEST)) { CommData.AlienColorMap = SetAbsColorMapIndex (CommData.AlienColorMap, 1); LearnQuest ((RESPONSE_REF)0); } else if (GET_GAME_STATE (KNOW_SPATHI_PASSWORD) && (GET_GAME_STATE (FOUND_PLUTO_SPATHI) || GET_GAME_STATE (SPATHI_HOME_VISITS) != 7)) { CommData.AlienColorMap = SetAbsColorMapIndex (CommData.AlienColorMap, 1); SpathiCouncil ((RESPONSE_REF)0); } else { SpathiPassword ((RESPONSE_REF)0); } } static COUNT uninit_spahome (void) { return (0); } static void post_spahome_enc (void) { BYTE Manner; if (GET_GAME_STATE (BATTLE_SEGUE) == 1 && (Manner = GET_GAME_STATE (SPATHI_MANNER)) != 2) { SET_GAME_STATE (SPATHI_MANNER, 1); if (Manner != 1) { SET_GAME_STATE (SPATHI_VISITS, 0); SET_GAME_STATE (SPATHI_HOME_VISITS, 0); } } } LOCDATAPTR init_spahome_comm () { LOCDATAPTR retval; spahome_desc.init_encounter_func = Intro; spahome_desc.post_encounter_func = post_spahome_enc; spahome_desc.uninit_encounter_func = uninit_spahome; spahome_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); spahome_desc.AlienTextBaseline.y = 0; spahome_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; // use alternate "Safe Ones" track if available spahome_desc.AlienAltSong = SPAHOME_MUSIC; spahome_desc.AlienSongFlags |= LDASF_USE_ALTERNATE; if (GET_GAME_STATE (SPATHI_MANNER) == 3) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &spahome_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/spahome/strings.h0000600000175000017500000000627410543202025020042 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, killed_fwiffo, POOR_FWIFFO, fwiffo_fine, NOT_LIKELY, we_attack_again, WE_FIGHT_AGAIN, bye_no_ally_offer, GOODBYE_NO_ALLY_OFFER, bye_angry_spathi, GOODBYE_ANGRY_SPATHI, why_dont_you_do_it, WE_WONT_BECAUSE, MEAN_GUYS_RETURN, we_apologize, DONT_BELIEVE, HELLO_AGAIN, HATE_YOU_FOREVER, WHAT_IS_PASSWORD, WHAT_IS_PASSWORD_AGAIN, we_are_vindicator0, we_are_vindicator1, we_are_vindicator2, gort_merenga, guph_florp, pleeese, wagngl_fthagn, screw_password, good_password, WRONG_PASSWORD, NO_PASSWORD, what_do_i_get, YOU_GET_TO_LIVE, YES_GOOD_PASSWORD, spathi_on_pluto, WHERE_SPATHI, hostage, GUN_TO_HEAD, we_come_in_peace, OF_COURSE, KILLED_SPATHI, misunderstanding, JUST_MISUNDERSTANDING, // JUST_MISUNDERSTANDING0, // JUST_MISUNDERSTANDING1, give_us_resources, NO_RESOURCES, resources_please, SORRY_NO_RESOURCES, bye_ally, GOODBYE_ALLY, what_about_hierarchy, what_about_history, what_about_alliance, what_about_other, what_about_precursors, enough_info, OK_ENOUGH_INFO, ABOUT_HIERARCHY, ABOUT_HISTORY, ABOUT_ALLIANCE, ABOUT_OTHER, ABOUT_PRECURSORS, little_mistake, BIG_MISTAKE, bye_before_party, QUEST_AGAIN, GOODBYE_BEFORE_PARTY, GOOD_START, something_fishy, NOTHING_FISHY, surrender, NO_SURRENDER, surrender_or_die, DEFEND_OURSELVES, hand_in_friendship, TOO_AFRAID, stronger, YOURE_NOT, yes_we_are, NO_YOURE_NOT, how_prove, BETTER_IDEA, share_info, NO_INFO, WE_UNDERSTAND, prove_strength, YOUR_BEHAVIOR, what_test, BEFORE_ACCEPT, WIPE_EVIL, think_more, COWARD, tell_evil, i_accept, AWAIT_RETURN, talk_test, already_got_them, EARLY_BIRD_CHECK, NOT_SURPRISED, TEST_AGAIN, too_dangerous, WE_AGREE, HOW_GO_EFFORTS, killed_them_all_1, killed_them_all_2, WILL_CHECK_1, WILL_CHECK_2, zapped_a_few, RETURN_COMPLETE, MUST_DESTROY_ALL, no_landing, saw_creatures, YOU_FORTUNATE, YOU_LIED_1, YOU_LIED_2, bye_from_party_1, bye_from_party_2, bye_from_party_3, GOODBYE_FROM_PARTY, MUST_PARTY_1, MUST_PARTY_2, MUST_PARTY_3, deals_a_deal, WAIT_A_WHILE, how_long, TEN_YEARS, reneging, ADULT_VIEW, return_beasts, WHAT_RELATIONSHIP, minds_and_might, HUH, fellowship, WHAT, do_as_we_say, DEPART_FOR_EARTH, HELLO_ALLIES_1, HELLO_ALLIES_2, HELLO_ALLIES_3, whats_up, GENERAL_INFO_1, GENERAL_INFO_2, GENERAL_INFO_3, GENERAL_INFO_4, GENERAL_INFO_5, like_some_info, WHAT_ABOUT }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/spahome/Makeinfo0000600000175000017500000000002710543202025017642 0ustar joeyjoeyuqm_CFILES="spahome.c" uqm-0.6.2/sc2/src/sc2code/comm/starbas/0000755000175000017500000000000010552600275016213 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/starbas/starbas.c0000600000175000017500000012462110543202025020003 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/comandr/resinst.h" #include "comm/starbas/strings.h" #include "build.h" #include "setup.h" #include "shipcont.h" #include "libs/graphics/gfx_common.h" #include "libs/inplib.h" #include "libs/mathlib.h" #include "libs/inplib.h" #include "libs/sound/sound.h" static void TellMission (RESPONSE_REF R); static void SellMinerals (RESPONSE_REF R); static LOCDATA commander_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)COMMANDER_PMAP_ANIM, /* AlienFrame */ (FONT)COMMANDER_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_MIDDLE, /* AlienTextValign */ (COLORMAP)COMMANDER_COLOR_MAP, /* AlienColorMap */ COMMANDER_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ STARBASE_CONVERSATION_PHRASES, /* PlayerPhrases */ 10, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { /* Blink */ 1, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ 0, ONE_SECOND * 8, /* RestartRate */ 0, /* BlockMask */ }, { /* Running light */ 10, /* StartIndex */ 30, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ ONE_SECOND * 2, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* Arc welder 0 */ 40, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 8, /* RestartRate */ 0, /* BlockMask */ }, { /* Arc welder 1 */ 47, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 8, /* RestartRate */ 0, /* BlockMask */ }, { /* Arc welder 2 */ 55, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 8, /* RestartRate */ 0, /* BlockMask */ }, { /* Arc welder 3 */ 61, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 8, /* RestartRate */ 0, /* BlockMask */ }, { /* Arc welder 4 */ 67, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 8, /* RestartRate */ 0, /* BlockMask */ }, { /* Arc welder 5 */ 74, /* StartIndex */ 11, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 8, /* RestartRate */ 0, /* BlockMask */ }, { /* Arc welder 6 */ 85, /* StartIndex */ 10, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 40, 0, /* FrameRate */ 0, ONE_SECOND * 8, /* RestartRate */ 0, /* BlockMask */ }, { /* Flagship picture */ 95, /* StartIndex */ 1, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 4, /* StartIndex */ 6, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 7 / 60, ONE_SECOND / 12, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static DWORD CurBulletinMask; static void ByeBye (RESPONSE_REF R) { (void) R; // ignored CurBulletinMask |= GET_GAME_STATE_32 (STARBASE_BULLETS0); SET_GAME_STATE_32 (STARBASE_BULLETS0, CurBulletinMask); /* if (R == goodbye_starbase_commander) */ if (GET_GAME_STATE (CHMMR_BOMB_STATE) >= 2) NPCPhrase (GOOD_LUCK_AGAIN); else { RESPONSE_REF pStr0, pStr1; switch ((BYTE)TFB_Random () & 7) { case 0: pStr0 = NORMAL_GOODBYE_A0; pStr1 = NORMAL_GOODBYE_A1; break; case 1: pStr0 = NORMAL_GOODBYE_B0; pStr1 = NORMAL_GOODBYE_B1; break; case 2: pStr0 = NORMAL_GOODBYE_C0; pStr1 = NORMAL_GOODBYE_C1; break; case 3: pStr0 = NORMAL_GOODBYE_D0; pStr1 = NORMAL_GOODBYE_D1; break; case 4: pStr0 = NORMAL_GOODBYE_E0; pStr1 = NORMAL_GOODBYE_E1; break; case 5: pStr0 = NORMAL_GOODBYE_F0; pStr1 = NORMAL_GOODBYE_F1; break; case 6: pStr0 = NORMAL_GOODBYE_G0; pStr1 = NORMAL_GOODBYE_G1; break; case 7: pStr0 = NORMAL_GOODBYE_H0; pStr1 = NORMAL_GOODBYE_H1; break; } NPCPhrase (pStr0); if (speechVolumeScale == 0.0f) { NPCPhrase (SPACE); NPCPhrase (GLOBAL_PLAYER_NAME); } NPCPhrase (pStr1); } } static void NeedInfo (RESPONSE_REF R); static void TellHistory (RESPONSE_REF R); static void AlienRaces (RESPONSE_REF R); static BYTE stack0, stack1, stack2, stack3; static void AllianceInfo (RESPONSE_REF R) { #define ALLIANCE_SHOFIXTI (1 << 0) #define ALLIANCE_YEHAT (1 << 1) #define ALLIANCE_ARILOU (1 << 2) #define ALLIANCE_CHENJESU (1 << 3) #define ALLIANCE_MMRNMHRM (1 << 4) #define ALLIANCE_SYREEN (1 << 5) static BYTE AllianceMask = 0; if (PLAYER_SAID (R, what_about_alliance)) { NPCPhrase (WHICH_ALLIANCE); AllianceMask = 0; } else if (PLAYER_SAID (R, shofixti)) { NPCPhrase (ABOUT_SHOFIXTI); AllianceMask |= ALLIANCE_SHOFIXTI; } else if (PLAYER_SAID (R, yehat)) { NPCPhrase (ABOUT_YEHAT); AllianceMask |= ALLIANCE_YEHAT; } else if (PLAYER_SAID (R, arilou)) { NPCPhrase (ABOUT_ARILOU); AllianceMask |= ALLIANCE_ARILOU; } else if (PLAYER_SAID (R, chenjesu)) { NPCPhrase (ABOUT_CHENJESU); AllianceMask |= ALLIANCE_CHENJESU; } else if (PLAYER_SAID (R, mmrnmhrm)) { NPCPhrase (ABOUT_MMRNMHRM); AllianceMask |= ALLIANCE_MMRNMHRM; } else if (PLAYER_SAID (R, syreen)) { NPCPhrase (ABOUT_SYREEN); AllianceMask |= ALLIANCE_SYREEN; } if (!(AllianceMask & ALLIANCE_SHOFIXTI)) Response (shofixti, AllianceInfo); if (!(AllianceMask & ALLIANCE_YEHAT)) Response (yehat, AllianceInfo); if (!(AllianceMask & ALLIANCE_ARILOU)) Response (arilou, AllianceInfo); if (!(AllianceMask & ALLIANCE_CHENJESU)) Response (chenjesu, AllianceInfo); if (!(AllianceMask & ALLIANCE_MMRNMHRM)) Response (mmrnmhrm, AllianceInfo); if (!(AllianceMask & ALLIANCE_SYREEN)) Response (syreen, AllianceInfo); Response (enough_alliance, AlienRaces); } static void HierarchyInfo (RESPONSE_REF R) { #define HIERARCHY_MYCON (1 << 0) #define HIERARCHY_SPATHI (1 << 1) #define HIERARCHY_UMGAH (1 << 2) #define HIERARCHY_ANDROSYNTH (1 << 3) #define HIERARCHY_ILWRATH (1 << 4) #define HIERARCHY_VUX (1 << 5) static BYTE HierarchyMask = 0; if (PLAYER_SAID (R, what_about_hierarchy)) { NPCPhrase (WHICH_HIERARCHY); HierarchyMask = 0; } else if (PLAYER_SAID (R, mycon)) { NPCPhrase (ABOUT_MYCON); HierarchyMask |= HIERARCHY_MYCON; } else if (PLAYER_SAID (R, spathi)) { NPCPhrase (ABOUT_SPATHI); HierarchyMask |= HIERARCHY_SPATHI; } else if (PLAYER_SAID (R, umgah)) { NPCPhrase (ABOUT_UMGAH); HierarchyMask |= HIERARCHY_UMGAH; } else if (PLAYER_SAID (R, androsynth)) { NPCPhrase (ABOUT_ANDROSYNTH); HierarchyMask |= HIERARCHY_ANDROSYNTH; } else if (PLAYER_SAID (R, ilwrath)) { NPCPhrase (ABOUT_ILWRATH); HierarchyMask |= HIERARCHY_ILWRATH; } else if (PLAYER_SAID (R, vux)) { NPCPhrase (ABOUT_VUX); HierarchyMask |= HIERARCHY_VUX; } if (!(HierarchyMask & HIERARCHY_MYCON)) Response (mycon, HierarchyInfo); if (!(HierarchyMask & HIERARCHY_SPATHI)) Response (spathi, HierarchyInfo); if (!(HierarchyMask & HIERARCHY_UMGAH)) Response (umgah, HierarchyInfo); if (!(HierarchyMask & HIERARCHY_ANDROSYNTH)) Response (androsynth, HierarchyInfo); if (!(HierarchyMask & HIERARCHY_ILWRATH)) Response (ilwrath, HierarchyInfo); if (!(HierarchyMask & HIERARCHY_VUX)) Response (vux, HierarchyInfo); Response (enough_hierarchy, AlienRaces); } static void AlienRaces (RESPONSE_REF R) { #define RACES_ALLIANCE (1 << 0) #define RACES_HIERARCHY (1 << 1) #define RACES_OTHER (1 << 2) static BYTE RacesMask = 0; if (PLAYER_SAID (R, alien_races)) { NPCPhrase (WHICH_ALIEN); RacesMask = 0; } else if (PLAYER_SAID (R, enough_alliance)) { NPCPhrase (OK_ENOUGH_ALLIANCE); RacesMask |= RACES_ALLIANCE; } else if (PLAYER_SAID (R, enough_hierarchy)) { NPCPhrase (OK_ENOUGH_HIERARCHY); RacesMask |= RACES_HIERARCHY; } else if (PLAYER_SAID (R, what_about_other)) { NPCPhrase (ABOUT_OTHER); RacesMask |= RACES_OTHER; } if (!(RacesMask & RACES_ALLIANCE)) { Response (what_about_alliance, AllianceInfo); } if (!(RacesMask & RACES_HIERARCHY)) { Response (what_about_hierarchy, HierarchyInfo); } if (!(RacesMask & RACES_OTHER)) { Response (what_about_other, AlienRaces); } Response (enough_aliens, TellHistory); } static void WarInfo (RESPONSE_REF R) { #define WAR_STARTED (1 << 0) #define WAR_WAS_LIKE (1 << 1) #define WAR_LOST (1 << 2) #define WAR_AFTERMATH (1 << 3) static BYTE WarMask = 0; if (PLAYER_SAID (R, the_war)) { NPCPhrase (WHICH_WAR); WarMask = 0; } else if (PLAYER_SAID (R, what_started_war)) { NPCPhrase (URQUAN_STARTED_WAR); WarMask |= WAR_STARTED; } else if (PLAYER_SAID (R, what_was_war_like)) { NPCPhrase (WAR_WAS_LIKE_SO); WarMask |= WAR_WAS_LIKE; } else if (PLAYER_SAID (R, why_lose_war)) { NPCPhrase (LOST_WAR_BECAUSE); WarMask |= WAR_LOST; } else if (PLAYER_SAID (R, what_after_war)) { NPCPhrase (AFTER_WAR); WarMask |= WAR_AFTERMATH; } if (!(WarMask & WAR_STARTED)) Response (what_started_war, WarInfo); if (!(WarMask & WAR_WAS_LIKE)) Response (what_was_war_like, WarInfo); if (!(WarMask & WAR_LOST)) Response (why_lose_war, WarInfo); if (!(WarMask & WAR_AFTERMATH)) Response (what_after_war, WarInfo); Response (enough_war, TellHistory); } static void AncientHistory (RESPONSE_REF R) { #define ANCIENT_PRECURSORS (1 << 0) #define ANCIENT_RACES (1 << 1) #define ANCIENT_EARTH (1 << 2) static BYTE AncientMask = 0; if (PLAYER_SAID (R, ancient_history)) { NPCPhrase (WHICH_ANCIENT); AncientMask = 0; } else if (PLAYER_SAID (R, precursors)) { NPCPhrase (ABOUT_PRECURSORS); AncientMask |= ANCIENT_PRECURSORS; } else if (PLAYER_SAID (R, old_races)) { NPCPhrase (ABOUT_OLD_RACES); AncientMask |= ANCIENT_RACES; } else if (PLAYER_SAID (R, aliens_on_earth)) { NPCPhrase (ABOUT_ALIENS_ON_EARTH); AncientMask |= ANCIENT_EARTH; } if (!(AncientMask & ANCIENT_PRECURSORS)) Response (precursors, AncientHistory); if (!(AncientMask & ANCIENT_RACES)) Response (old_races, AncientHistory); if (!(AncientMask & ANCIENT_EARTH)) Response (aliens_on_earth, AncientHistory); Response (enough_ancient, TellHistory); } static void TellHistory (RESPONSE_REF R) { RESPONSE_REF pstack[3]; if (PLAYER_SAID (R, history)) { NPCPhrase (WHICH_HISTORY); stack0 = stack1 = stack2 = 0; } else if (PLAYER_SAID (R, enough_aliens)) { NPCPhrase (OK_ENOUGH_ALIENS); stack0 = 1; } else if (PLAYER_SAID (R, enough_war)) { NPCPhrase (OK_ENOUGH_WAR); stack1 = 1; } else if (PLAYER_SAID (R, enough_ancient)) { NPCPhrase (OK_ENOUGH_ANCIENT); stack2 = 1; } switch (stack0) { case 0: pstack[0] = alien_races; break; case 1: pstack[0] = 0; break; } switch (stack1) { case 0: pstack[1] = the_war; break; case 1: pstack[1] = 0; break; } switch (stack2) { case 0: pstack[2] = ancient_history; break; case 1: pstack[2] = 0; break; } if (pstack[0]) { Response (pstack[0], AlienRaces); } if (pstack[1]) { Response (pstack[1], WarInfo); } if (pstack[2]) { Response (pstack[2], AncientHistory); } Response (enough_history, NeedInfo); } static void DefeatUrquan (RESPONSE_REF R) { #define HOW_FIND_URQUAN (1 << 0) #define HOW_FIGHT_URQUAN (1 << 1) #define HOW_ALLY_AGAINST_URQUAN (1 << 2) #define HOW_STRONG_AGAINST_URQUAN (1 << 3) static BYTE DefeatMask = 0; if (PLAYER_SAID (R, how_defeat)) { NPCPhrase (DEFEAT_LIKE_SO); DefeatMask = 0; } else if (PLAYER_SAID (R, how_find_urquan)) { NPCPhrase (FIND_URQUAN); DefeatMask |= HOW_FIND_URQUAN; } else if (PLAYER_SAID (R, how_fight_urquan)) { NPCPhrase (FIGHT_URQUAN); DefeatMask |= HOW_FIGHT_URQUAN; } else if (PLAYER_SAID (R, how_ally)) { NPCPhrase (ALLY_LIKE_SO); DefeatMask |= HOW_ALLY_AGAINST_URQUAN; } else if (PLAYER_SAID (R, how_get_strong)) { NPCPhrase (STRONG_LIKE_SO); DefeatMask |= HOW_STRONG_AGAINST_URQUAN; } if (!(DefeatMask & HOW_FIND_URQUAN)) Response (how_find_urquan, DefeatUrquan); if (!(DefeatMask & HOW_FIGHT_URQUAN)) Response (how_fight_urquan, DefeatUrquan); if (!(DefeatMask & HOW_ALLY_AGAINST_URQUAN)) Response (how_ally, DefeatUrquan); if (!(DefeatMask & HOW_STRONG_AGAINST_URQUAN)) Response (how_get_strong, DefeatUrquan); Response (enough_defeat, TellMission); } static void AnalyzeCondition (void) { BYTE i; BYTE num_thrusters = 0, num_jets = 0, num_guns = 0, num_bays = 0, num_batts = 0, num_track = 0, num_defense = 0; BOOLEAN HasMinimum; for (i = 0; i < NUM_DRIVE_SLOTS; ++i) { if (GLOBAL_SIS (DriveSlots[i]) < EMPTY_SLOT) ++num_thrusters; } for (i = 0; i < NUM_JET_SLOTS; ++i) { if (GLOBAL_SIS (JetSlots[i]) < EMPTY_SLOT) ++num_jets; } for (i = 0; i < NUM_MODULE_SLOTS; ++i) { BYTE which_piece; switch (which_piece = GLOBAL_SIS (ModuleSlots[i])) { case STORAGE_BAY: ++num_bays; break; case DYNAMO_UNIT: case SHIVA_FURNACE: num_batts += 1 + (which_piece - DYNAMO_UNIT); break; case GUN_WEAPON: case BLASTER_WEAPON: case CANNON_WEAPON: num_guns += 1 + (which_piece - GUN_WEAPON); break; case TRACKING_SYSTEM: ++num_track; break; case ANTIMISSILE_DEFENSE: ++num_defense; break; } } if (num_track && num_guns) num_guns += 2; HasMinimum = (num_thrusters >= 7 && num_jets >= 5 && GLOBAL_SIS (CrewEnlisted) >= CREW_POD_CAPACITY && GLOBAL_SIS (FuelOnBoard) >= FUEL_TANK_CAPACITY && num_bays >= 1 && GLOBAL_SIS (NumLanders) && num_batts >= 1 && num_guns >= 2); NPCPhrase (LETS_SEE); if (!HasMinimum && GET_GAME_STATE (CHMMR_BOMB_STATE) < 2) { NPCPhrase (IMPROVE_1); if (num_thrusters < 7) NPCPhrase (NEED_THRUSTERS_1); if (num_jets < 5) NPCPhrase (NEED_TURN_1); if (num_guns < 2) NPCPhrase (NEED_GUNS_1); if (GLOBAL_SIS (CrewEnlisted) < CREW_POD_CAPACITY) NPCPhrase (NEED_CREW_1); if (GLOBAL_SIS (FuelOnBoard) < FUEL_TANK_CAPACITY) NPCPhrase (NEED_FUEL_1); if (num_bays < 1) NPCPhrase (NEED_STORAGE_1); if (GLOBAL_SIS (NumLanders) == 0) NPCPhrase (NEED_LANDERS_1); if (num_batts < 1) NPCPhrase (NEED_DYNAMOS_1); if (GLOBAL_SIS (ResUnits) >= 3000) NPCPhrase (IMPROVE_FLAGSHIP_WITH_RU); else NPCPhrase (GO_GET_MINERALS); } else { BYTE num_aliens = 0; COUNT FleetStrength; BOOLEAN HasMaximum; FleetStrength = ActivateStarShip (0, ESCORT_WORTH); for (i = 0; i < NUM_AVAILABLE_RACES; ++i) { if (i != HUMAN_SHIP && (ActivateStarShip (i, CHECK_ALLIANCE) & GOOD_GUY)) ++num_aliens; } HasMaximum = (num_thrusters == NUM_DRIVE_SLOTS && num_jets == NUM_JET_SLOTS && GLOBAL_SIS (CrewEnlisted) >= CREW_POD_CAPACITY * 3 && GLOBAL_SIS (FuelOnBoard) >= FUEL_TANK_CAPACITY * 3 && GLOBAL_SIS (NumLanders) >= 3 && num_batts >= 4 && num_guns >= 7 && num_defense >= 2); if (!HasMaximum && GET_GAME_STATE (CHMMR_BOMB_STATE) < 2) NPCPhrase (GOT_OK_FLAGSHIP); else NPCPhrase (GOT_AWESOME_FLAGSHIP); if (GET_GAME_STATE (CHMMR_BOMB_STATE) >= 2) { NPCPhrase (CHMMR_IMPROVED_BOMB); if (FleetStrength < 20000) NPCPhrase (MUST_ACQUIRE_AWESOME_FLEET); else { NPCPhrase (GOT_AWESOME_FLEET); if (!GET_GAME_STATE (TALKING_PET_ON_SHIP)) NPCPhrase (MUST_ELIMINATE_URQUAN_GUARDS); else NPCPhrase (GO_DESTROY_SAMATRA); } } else if (num_aliens < 2) NPCPhrase (GO_ALLY_WITH_ALIENS); else { NPCPhrase (MADE_SOME_ALLIES); if (FleetStrength < 6000) { if (GLOBAL_SIS (ResUnits) >= 3000) NPCPhrase (BUY_COMBAT_SHIPS); else NPCPhrase (GET_SHIPS_BY_MINING_OR_ALLIANCE); } else { NPCPhrase (GOT_OK_FLEET); if (!HasMaximum) { NPCPhrase (IMPROVE_2); if (num_thrusters < NUM_DRIVE_SLOTS) NPCPhrase (NEED_THRUSTERS_2); if (num_jets < NUM_JET_SLOTS) NPCPhrase (NEED_TURN_2); if (num_guns < 7) NPCPhrase (NEED_GUNS_2); if (GLOBAL_SIS (CrewEnlisted) < CREW_POD_CAPACITY * 3) NPCPhrase (NEED_CREW_2); if (GLOBAL_SIS (FuelOnBoard) < FUEL_TANK_CAPACITY * 3) NPCPhrase (NEED_FUEL_2); if (GLOBAL_SIS (NumLanders) < 3) NPCPhrase (NEED_LANDERS_2); if (num_batts < 4) NPCPhrase (NEED_DYNAMOS_2); if (num_defense < 2) NPCPhrase (NEED_POINT); } else if (!GET_GAME_STATE (AWARE_OF_SAMATRA)) NPCPhrase (GO_LEARN_ABOUT_URQUAN); else { NPCPhrase (KNOW_ABOUT_SAMATRA); if (!GET_GAME_STATE (UTWIG_BOMB)) NPCPhrase (FIND_WAY_TO_DESTROY_SAMATRA); else if (GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) NPCPhrase (MUST_INCREASE_BOMB_STRENGTH); } } } } } static void TellMission (RESPONSE_REF R) { RESPONSE_REF pstack[4]; if (PLAYER_SAID (R, our_mission)) { NPCPhrase (WHICH_MISSION); stack0 = stack1 = stack2 = stack3 = 0; } else if (PLAYER_SAID (R, where_get_minerals)) { NPCPhrase (GET_MINERALS); stack0 = 1; } else if (PLAYER_SAID (R, what_about_aliens)) { NPCPhrase (ABOUT_ALIENS); stack1 = 1; } else if (PLAYER_SAID (R, what_do_now)) { AnalyzeCondition (); stack2 = 1; } else if (PLAYER_SAID (R, what_about_urquan)) { NPCPhrase (MUST_DEFEAT); stack3 = 1; } else if (PLAYER_SAID (R, enough_defeat)) { NPCPhrase (OK_ENOUGH_DEFEAT); stack3 = 2; } switch (stack0) { case 0: pstack[0] = where_get_minerals; break; default: pstack[0] = 0; break; } switch (stack1) { case 0: pstack[1] = what_about_aliens; break; default: pstack[1] = 0; break; } switch (stack2) { case 0: pstack[2] = what_do_now; break; default: pstack[2] = 0; break; } switch (stack3) { case 0: pstack[3] = what_about_urquan; break; case 1: pstack[3] = how_defeat; break; default: pstack[3] = 0; break; } if (pstack[0]) Response (pstack[0], TellMission); if (pstack[1]) Response (pstack[1], TellMission); if (pstack[2]) Response (pstack[2], TellMission); if (pstack[3]) { if (stack3 == 1) Response (pstack[3], DefeatUrquan); else Response (pstack[3], TellMission); } Response (enough_mission, NeedInfo); } static void TellStarBase (RESPONSE_REF R) { RESPONSE_REF pstack[4]; static UNICODE buf0[80]; if (PLAYER_SAID (R, starbase_functions)) { NPCPhrase (WHICH_FUNCTION); stack0 = stack1 = stack2 = stack3 = 0; } else if (PLAYER_SAID (R, tell_me_about_fuel0)) { NPCPhrase (ABOUT_FUEL); stack1 = 1; } else if (PLAYER_SAID (R, tell_me_about_crew)) { NPCPhrase (ABOUT_CREW0); if (speechVolumeScale > 0.0f) NPCPhrase (YOUR_FLAGSHIP_3DO2); else { NPCPhrase (YOUR_FLAGSHIP_PC); NPCPhrase (GLOBAL_SHIP_NAME); } NPCPhrase (ABOUT_CREW1); stack2 = 2; } else if (PLAYER_SAID (R, tell_me_about_modules0)) { NPCPhrase (ABOUT_MODULES); stack0 = 1; } else if (PLAYER_SAID (R, tell_me_about_ships)) { NPCPhrase (ABOUT_SHIPS); stack2 = 1; } else if (PLAYER_SAID (R, tell_me_about_ru)) { NPCPhrase (ABOUT_RU); stack3 = 1; } else if (PLAYER_SAID (R, tell_me_about_minerals)) { NPCPhrase (ABOUT_MINERALS); stack3 = 2; } else if (PLAYER_SAID (R, tell_me_about_life)) { NPCPhrase (ABOUT_LIFE); stack3 = 3; } switch (stack0) { case 0: construct_response ( buf0, tell_me_about_modules0, GLOBAL_SIS (ShipName), tell_me_about_modules1, NULL_PTR ); pstack[0] = tell_me_about_modules0; break; default: pstack[0] = 0; break; } switch (stack1) { case 0: construct_response ( shared_phrase_buf, tell_me_about_fuel0, GLOBAL_SIS (ShipName), tell_me_about_fuel1, NULL_PTR ); pstack[1] = tell_me_about_fuel0; break; default: pstack[1] = 0; break; } switch (stack2) { case 0: pstack[2] = tell_me_about_ships; break; case 1: pstack[2] = tell_me_about_crew; break; default: pstack[2] = 0; break; } switch (stack3) { case 0: pstack[3] = tell_me_about_ru; break; case 1: pstack[3] = tell_me_about_minerals; break; case 2: pstack[3] = tell_me_about_life; break; default: pstack[3] = 0; break; } if (pstack[0]) DoResponsePhrase (pstack[0], TellStarBase, buf0); if (pstack[1]) DoResponsePhrase (pstack[1], TellStarBase, shared_phrase_buf); if (pstack[2]) Response (pstack[2], TellStarBase); if (pstack[3]) Response (pstack[3], TellStarBase); Response (enough_starbase, NeedInfo); } static void NormalStarbase (RESPONSE_REF R); static void NeedInfo (RESPONSE_REF R) { if (PLAYER_SAID (R, need_info)) NPCPhrase (WHAT_KIND_OF_INFO); else if (PLAYER_SAID (R, enough_starbase)) NPCPhrase (OK_ENOUGH_STARBASE); else if (PLAYER_SAID (R, enough_history)) NPCPhrase (OK_ENOUGH_HISTORY); else if (PLAYER_SAID (R, enough_mission)) NPCPhrase (OK_ENOUGH_MISSION); Response (starbase_functions, TellStarBase); Response (history, TellHistory); Response (our_mission, TellMission); Response (no_need_info, NormalStarbase); } static BOOLEAN DiscussDevices (BOOLEAN TalkAbout) { COUNT i, VuxBeastIndex, PhraseIndex; BOOLEAN Undiscussed; if (TalkAbout) NPCPhrase (DEVICE_HEAD); PhraseIndex = 2; VuxBeastIndex = 0; Undiscussed = FALSE; for (i = 0; i < NUM_DEVICES; ++i) { RESPONSE_REF pStr; pStr = 0; switch (i) { case ROSY_SPHERE_DEVICE: if (GET_GAME_STATE (ROSY_SPHERE_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_ROSY_SPHERE)) { pStr = ABOUT_SPHERE; SET_GAME_STATE (DISCUSSED_ROSY_SPHERE, TalkAbout); } break; case ARTIFACT_2_DEVICE: if (GET_GAME_STATE (ARTIFACT_2_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_ARTIFACT_2)) { pStr = ABOUT_ARTIFACT_2; SET_GAME_STATE (DISCUSSED_ARTIFACT_2, TalkAbout); } break; case ARTIFACT_3_DEVICE: if (GET_GAME_STATE (ARTIFACT_3_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_ARTIFACT_3)) { pStr = ABOUT_ARTIFACT_3; SET_GAME_STATE (DISCUSSED_ARTIFACT_3, TalkAbout); } break; case SUN_EFFICIENCY_DEVICE: if (GET_GAME_STATE (SUN_DEVICE_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_SUN_EFFICIENCY)) { pStr = ABOUT_SUN; SET_GAME_STATE (DISCUSSED_SUN_EFFICIENCY, TalkAbout); } break; case UTWIG_BOMB_DEVICE: if (GET_GAME_STATE (UTWIG_BOMB_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_UTWIG_BOMB)) { pStr = ABOUT_BOMB; SET_GAME_STATE (DISCUSSED_UTWIG_BOMB, TalkAbout); } break; case ULTRON_0_DEVICE: if (GET_GAME_STATE (ULTRON_CONDITION) == 1 && !GET_GAME_STATE (DISCUSSED_ULTRON)) { pStr = ABOUT_ULTRON_0; SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout); } break; case ULTRON_1_DEVICE: if (GET_GAME_STATE (ULTRON_CONDITION) == 2 && !GET_GAME_STATE (DISCUSSED_ULTRON)) { pStr = ABOUT_ULTRON_1; SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout); } break; case ULTRON_2_DEVICE: if (GET_GAME_STATE (ULTRON_CONDITION) == 3 && !GET_GAME_STATE (DISCUSSED_ULTRON)) { pStr = ABOUT_ULTRON_2; SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout); } break; case ULTRON_3_DEVICE: if (GET_GAME_STATE (ULTRON_CONDITION) == 4 && !GET_GAME_STATE (DISCUSSED_ULTRON)) { pStr = ABOUT_ULTRON_3; SET_GAME_STATE (DISCUSSED_ULTRON, TalkAbout); } break; case MAIDENS_DEVICE: if (GET_GAME_STATE (MAIDENS_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_MAIDENS)) { pStr = ABOUT_MAIDENS; SET_GAME_STATE (DISCUSSED_MAIDENS, TalkAbout); } break; case TALKING_PET_DEVICE: if (GET_GAME_STATE (TALKING_PET_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_TALKING_PET)) { pStr = ABOUT_TALKPET; SET_GAME_STATE (DISCUSSED_TALKING_PET, TalkAbout); } break; case AQUA_HELIX_DEVICE: if (GET_GAME_STATE (AQUA_HELIX_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_AQUA_HELIX)) { pStr = ABOUT_HELIX; SET_GAME_STATE (DISCUSSED_AQUA_HELIX, TalkAbout); } break; case CLEAR_SPINDLE_DEVICE: if (GET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_CLEAR_SPINDLE)) { pStr = ABOUT_SPINDLE; SET_GAME_STATE (DISCUSSED_CLEAR_SPINDLE, TalkAbout); } break; case UMGAH_HYPERWAVE_DEVICE: if (GET_GAME_STATE (UMGAH_BROADCASTERS_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_UMGAH_HYPERWAVE)) { pStr = ABOUT_UCASTER; SET_GAME_STATE (DISCUSSED_UMGAH_HYPERWAVE, TalkAbout); } break; #ifdef NEVER case DATA_PLATE_1_DEVICE: if (GET_GAME_STATE (DATA_PLATE_1_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_DATA_PLATE_1)) { pStr = (PSTR)ABOUT_DATAPLATE_1; SET_GAME_STATE (DISCUSSED_DATA_PLATE_1, TalkAbout); } break; case DATA_PLATE_2_DEVICE: if (GET_GAME_STATE (DATA_PLATE_2_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_DATA_PLATE_2)) { pStr = (PSTR)ABOUT_DATAPLATE_2; SET_GAME_STATE (DISCUSSED_DATA_PLATE_2, TalkAbout); } break; case DATA_PLATE_3_DEVICE: if (GET_GAME_STATE (DATA_PLATE_3_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_DATA_PLATE_3)) { pStr = (PSTR)ABOUT_DATAPLATE_3; SET_GAME_STATE (DISCUSSED_DATA_PLATE_3, TalkAbout); } break; #endif /* NEVER */ case TAALO_PROTECTOR_DEVICE: if (GET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_TAALO_PROTECTOR)) { pStr = ABOUT_SHIELD; SET_GAME_STATE (DISCUSSED_TAALO_PROTECTOR, TalkAbout); } break; case EGG_CASING0_DEVICE: if (GET_GAME_STATE (EGG_CASE0_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_EGG_CASING0)) { pStr = ABOUT_EGGCASE_0; SET_GAME_STATE (DISCUSSED_EGG_CASING0, TalkAbout); SET_GAME_STATE (DISCUSSED_EGG_CASING1, TalkAbout); SET_GAME_STATE (DISCUSSED_EGG_CASING2, TalkAbout); } break; case EGG_CASING1_DEVICE: if (GET_GAME_STATE (EGG_CASE1_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_EGG_CASING1)) { pStr = ABOUT_EGGCASE_0; SET_GAME_STATE (DISCUSSED_EGG_CASING0, TalkAbout); SET_GAME_STATE (DISCUSSED_EGG_CASING1, TalkAbout); SET_GAME_STATE (DISCUSSED_EGG_CASING2, TalkAbout); } break; case EGG_CASING2_DEVICE: if (GET_GAME_STATE (EGG_CASE2_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_EGG_CASING2)) { pStr = ABOUT_EGGCASE_0; SET_GAME_STATE (DISCUSSED_EGG_CASING0, TalkAbout); SET_GAME_STATE (DISCUSSED_EGG_CASING1, TalkAbout); SET_GAME_STATE (DISCUSSED_EGG_CASING2, TalkAbout); } break; case SYREEN_SHUTTLE_DEVICE: if (GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_SYREEN_SHUTTLE)) { pStr = ABOUT_SHUTTLE; SET_GAME_STATE (DISCUSSED_SYREEN_SHUTTLE, TalkAbout); } break; case VUX_BEAST_DEVICE: if (GET_GAME_STATE (VUX_BEAST_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_VUX_BEAST)) { pStr = ABOUT_VUXBEAST0; SET_GAME_STATE (DISCUSSED_VUX_BEAST, TalkAbout); } break; case DESTRUCT_CODE_DEVICE: if (GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_DESTRUCT_CODE)) { pStr = ABOUT_DESTRUCT; SET_GAME_STATE (DISCUSSED_DESTRUCT_CODE, TalkAbout); } break; case PORTAL_SPAWNER_DEVICE: if (GET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_PORTAL_SPAWNER)) { pStr = ABOUT_PORTAL; SET_GAME_STATE (DISCUSSED_PORTAL_SPAWNER, TalkAbout); } break; case URQUAN_WARP_DEVICE: if (GET_GAME_STATE (PORTAL_KEY_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_URQUAN_WARP)) { pStr = ABOUT_WARPPOD; SET_GAME_STATE (DISCUSSED_URQUAN_WARP, TalkAbout); } break; case BURVIX_HYPERWAVE_DEVICE: if (GET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP) && !GET_GAME_STATE (DISCUSSED_BURVIX_HYPERWAVE)) { pStr = ABOUT_BCASTER; SET_GAME_STATE (DISCUSSED_BURVIX_HYPERWAVE, TalkAbout); } break; } if (pStr) { if (TalkAbout) { if (PhraseIndex > 2) NPCPhrase (BETWEEN_DEVICES); NPCPhrase (pStr); if (pStr == ABOUT_VUXBEAST0) { VuxBeastIndex = ++PhraseIndex; NPCPhrase (ABOUT_VUXBEAST1); } } PhraseIndex += 2; } } if (TalkAbout) { NPCPhrase (DEVICE_TAIL); if (VuxBeastIndex) { for (i = 1; i < VuxBeastIndex; ++i) AlienTalkSegue (i); i = CommData.AlienTalkDesc.NumFrames; CommData.AlienTalkDesc.NumFrames = 0; AlienTalkSegue (VuxBeastIndex); CommData.AlienTalkDesc.NumFrames = i; AlienTalkSegue ((COUNT)~0); } } return (PhraseIndex > 2); } static BOOLEAN CheckTiming (COUNT month_index, COUNT day_index) { COUNT mi, year_index; BYTE days_in_month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, }; mi = GET_GAME_STATE (STARBASE_MONTH); year_index = START_YEAR; day_index += GET_GAME_STATE (STARBASE_DAY); while (day_index > days_in_month[mi - 1]) { day_index -= days_in_month[mi - 1]; if (++mi > 12) { mi = 1; ++year_index; } } month_index += mi; year_index += (month_index - 1) / 12; month_index = ((month_index - 1) % 12) + 1; return (year_index < GLOBAL (GameClock.year_index) || (year_index == GLOBAL (GameClock.year_index) && (month_index < GLOBAL (GameClock.month_index) || (month_index == GLOBAL (GameClock.month_index) && day_index < GLOBAL (GameClock.day_index))))); } static void CheckBulletins (BOOLEAN Repeat) { RESPONSE_REF pIntro; BYTE b0; DWORD BulletinMask; if (Repeat) BulletinMask = CurBulletinMask ^ 0xFFFFFFFFL; else BulletinMask = GET_GAME_STATE_32 (STARBASE_BULLETS0); pIntro = 0; for (b0 = 0; b0 < 32; ++b0) { if (!(BulletinMask & (1L << b0))) { RESPONSE_REF pStr; pStr = 0; switch (b0) { case 0: if (ActivateStarShip (SPATHI_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { pStr = STARBASE_BULLETIN_1; } break; case 1: if (ActivateStarShip (ZOQFOTPIK_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { pStr = STARBASE_BULLETIN_2; } break; case 2: if (ActivateStarShip (SUPOX_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { pStr = STARBASE_BULLETIN_3; } break; case 3: if (ActivateStarShip (UTWIG_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { pStr = STARBASE_BULLETIN_4; } break; case 4: if (ActivateStarShip (ORZ_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { pStr = STARBASE_BULLETIN_5; } break; case 5: if (GET_GAME_STATE (ARILOU_MANNER) == 2) BulletinMask |= 1L << b0; else if (GET_GAME_STATE (PORTAL_SPAWNER) && (Repeat || ActivateStarShip ( ARILOU_SHIP, FEASIBILITY_STUDY ))) { #define NUM_GIFT_ARILOUS 3 pStr = STARBASE_BULLETIN_6; if (!Repeat) ActivateStarShip (ARILOU_SHIP, NUM_GIFT_ARILOUS); } break; case 6: if (GET_GAME_STATE (ZOQFOT_DISTRESS) == 1) { pStr = STARBASE_BULLETIN_7; } break; case 7: if (GET_GAME_STATE (MET_MELNORME)) BulletinMask |= 1L << b0; else if (CheckTiming (3, 0)) { pStr = STARBASE_BULLETIN_8; } break; case 8: if (GET_GAME_STATE (MET_MELNORME)) BulletinMask |= 1L << b0; else if (CheckTiming (6, 0)) { pStr = STARBASE_BULLETIN_9; } break; case 9: if (GET_GAME_STATE (FOUND_PLUTO_SPATHI)) BulletinMask |= 1L << b0; else if (CheckTiming (0, 7)) { pStr = STARBASE_BULLETIN_10; } break; case 10: if (GET_GAME_STATE (SPATHI_SHIELDED_SELVES)) { pStr = STARBASE_BULLETIN_11; } break; case 11: if (GET_GAME_STATE (ZOQFOT_HOME_VISITS) || GET_GAME_STATE_32 (ZOQFOT_GRPOFFS0)) BulletinMask |= 1L << b0; else if (CheckTiming (0, 42)) { pStr = STARBASE_BULLETIN_12; } break; case 12: if (ActivateStarShip (CHMMR_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { pStr = STARBASE_BULLETIN_13; } break; case 13: if (ActivateStarShip (SHOFIXTI_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { pStr = STARBASE_BULLETIN_14; } break; case 14: if (GET_GAME_STATE (PKUNK_MISSION)) { pStr = STARBASE_BULLETIN_15; } break; case 15: if (GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP)) BulletinMask |= 1L << b0; else if (CheckTiming (7, 0)) { pStr = STARBASE_BULLETIN_16; } break; case 16: break; case 17: if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK)) { pStr = STARBASE_BULLETIN_18; } break; case 18: if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) { pStr = STARBASE_BULLETIN_19; } break; case 19: break; case 20: break; case 21: if (GET_GAME_STATE (ZOQFOT_DISTRESS) == 2) { pStr = STARBASE_BULLETIN_22; } break; case 22: break; case 23: break; case 24: break; case 25: break; case 26: { COUNT crew_sold; crew_sold = MAKE_WORD ( GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0), GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1) ); if (crew_sold > 100) BulletinMask |= 1L << b0; else if (crew_sold) { pStr = STARBASE_BULLETIN_27; } break; } case 27: { COUNT crew_sold; crew_sold = MAKE_WORD ( GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0), GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1) ); if (crew_sold > 250) BulletinMask |= 1L << b0; else if (crew_sold > 100) { pStr = STARBASE_BULLETIN_28; } break; } case 28: { COUNT crew_bought; crew_bought = MAKE_WORD ( GET_GAME_STATE (CREW_PURCHASED0), GET_GAME_STATE (CREW_PURCHASED1) ); if (crew_bought >= CREW_EXPENSE_THRESHOLD) { pStr = STARBASE_BULLETIN_29; } break; } case 29: if (MAKE_WORD ( GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0), GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1) ) > 250) { pStr = STARBASE_BULLETIN_30; } break; case 30: break; case 31: break; } if (pStr) { if (pIntro) NPCPhrase (BETWEEN_BULLETINS); else if (Repeat) pIntro = BEFORE_WE_GO_ON_1; else { switch ((BYTE)TFB_Random () % 7) { case 0: pIntro = BEFORE_WE_GO_ON_1; break; case 1: pIntro = BEFORE_WE_GO_ON_2; break; case 2: pIntro = BEFORE_WE_GO_ON_3; break; case 3: pIntro = BEFORE_WE_GO_ON_4; break; case 4: pIntro = BEFORE_WE_GO_ON_5; break; case 5: pIntro = BEFORE_WE_GO_ON_6; break; default: pIntro = BEFORE_WE_GO_ON_7; break; } NPCPhrase (pIntro); } NPCPhrase (pStr); CurBulletinMask |= 1L << b0; } } } if (pIntro == 0 && GET_GAME_STATE (STARBASE_VISITED)) NPCPhrase (RETURN_HELLO); else if (!Repeat) SET_GAME_STATE_32 (STARBASE_BULLETS0, BulletinMask); } static void NormalStarbase (RESPONSE_REF R) { if (PLAYER_SAID (R, no_need_info)) NPCPhrase (OK_NO_NEED_INFO); else if (PLAYER_SAID (R, new_devices)) DiscussDevices (TRUE); else if (PLAYER_SAID (R, repeat_bulletins)) CheckBulletins (TRUE); else if (R == 0) { if (GET_GAME_STATE (MOONBASE_ON_SHIP)) { NPCPhrase (STARBASE_IS_READY_A); if (speechVolumeScale > 0.0f) NPCPhrase (YOUR_FLAGSHIP_3DO1); else { NPCPhrase (YOUR_FLAGSHIP_PC); NPCPhrase (GLOBAL_SHIP_NAME); } NPCPhrase (STARBASE_IS_READY_B); if (speechVolumeScale > 0.0f) NPCPhrase (YOUR_FLAGSHIP_3DO0); else NPCPhrase (GLOBAL_SHIP_NAME); NPCPhrase (STARBASE_IS_READY_C); LockMutex (GraphicsLock); DeltaSISGauges (0, 0, 2500); UnlockMutex (GraphicsLock); SET_GAME_STATE (STARBASE_MONTH, GLOBAL (GameClock.month_index)); SET_GAME_STATE (STARBASE_DAY, GLOBAL (GameClock.day_index)); } else if (GET_GAME_STATE (STARBASE_VISITED)) { CheckBulletins (FALSE); } else { RESPONSE_REF pStr0, pStr1; switch ((BYTE)TFB_Random () & 7) { case 0: pStr0 = NORMAL_HELLO_A0; pStr1 = NORMAL_HELLO_A1; break; case 1: pStr0 = NORMAL_HELLO_B0; pStr1 = NORMAL_HELLO_B1; break; case 2: pStr0 = NORMAL_HELLO_C0; pStr1 = NORMAL_HELLO_C1; break; case 3: pStr0 = NORMAL_HELLO_D0; pStr1 = NORMAL_HELLO_D1; break; case 4: pStr0 = NORMAL_HELLO_E0; pStr1 = NORMAL_HELLO_E1; break; case 5: pStr0 = NORMAL_HELLO_F0; pStr1 = NORMAL_HELLO_F1; break; case 6: pStr0 = NORMAL_HELLO_G0; pStr1 = NORMAL_HELLO_G1; break; case 7: pStr0 = NORMAL_HELLO_H0; pStr1 = NORMAL_HELLO_H1; break; } NPCPhrase (pStr0); if (speechVolumeScale == 0.0f) { NPCPhrase (SPACE); NPCPhrase (GLOBAL_PLAYER_NAME); } NPCPhrase (pStr1); CheckBulletins (FALSE); } SET_GAME_STATE (STARBASE_VISITED, 1); } if (GLOBAL_SIS (TotalElementMass)) Response (have_minerals, SellMinerals); if (DiscussDevices (FALSE)) Response (new_devices, NormalStarbase); if (CurBulletinMask) Response (repeat_bulletins, NormalStarbase); Response (need_info, NeedInfo); Response (goodbye_commander, ByeBye); } static void SellMinerals (RESPONSE_REF R) { COUNT i, total; BOOLEAN Sleepy; RESPONSE_REF pStr1, pStr2; total = 0; Sleepy = TRUE; for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) { COUNT amount; DWORD TimeIn; if (i == 0) { DrawCargoStrings ((BYTE)~0, (BYTE)~0); SleepThread (ONE_SECOND / 2); TimeIn = GetTimeCounter (); DrawCargoStrings ((BYTE)0, (BYTE)0); } else if (Sleepy) { DrawCargoStrings ((BYTE)(i - 1), (BYTE)i); TimeIn = GetTimeCounter (); } if ((amount = GLOBAL_SIS (ElementAmounts[i])) != 0) { total += amount * GLOBAL (ElementWorth[i]); do { if (!Sleepy || AnyButtonPress (TRUE)) { Sleepy = FALSE; GLOBAL_SIS (ElementAmounts[i]) = 0; GLOBAL_SIS (TotalElementMass) -= amount; LockMutex (GraphicsLock); DeltaSISGauges (0, 0, amount * GLOBAL (ElementWorth[i])); UnlockMutex (GraphicsLock); break; } --GLOBAL_SIS (ElementAmounts[i]); --GLOBAL_SIS (TotalElementMass); TaskSwitch (); TimeIn = GetTimeCounter (); DrawCargoStrings ((BYTE)i, (BYTE)i); LockMutex (GraphicsLock); ShowRemainingCapacity (); DeltaSISGauges (0, 0, GLOBAL (ElementWorth[i])); UnlockMutex (GraphicsLock); } while (--amount); } if (Sleepy) { SleepThreadUntil (TimeIn + (ONE_SECOND / 4)); TimeIn = GetTimeCounter (); } } SleepThread (ONE_SECOND / 2); LockMutex (GraphicsLock); ClearSISRect (DRAW_SIS_DISPLAY); UnlockMutex (GraphicsLock); // DrawStorageBays (FALSE); if (total < 1000) { total = GET_GAME_STATE (LIGHT_MINERAL_LOAD); switch (total++) { case 0: pStr1 = LIGHT_LOAD_A0; pStr2 = LIGHT_LOAD_A1; break; case 1: pStr1 = LIGHT_LOAD_B0; pStr2 = LIGHT_LOAD_B1; break; case 2: pStr1 = LIGHT_LOAD_C0; pStr2 = LIGHT_LOAD_C1; break; case 3: pStr1 = LIGHT_LOAD_D0; pStr2 = LIGHT_LOAD_D1; break; case 4: pStr1 = LIGHT_LOAD_E0; pStr2 = LIGHT_LOAD_E1; break; case 5: pStr1 = LIGHT_LOAD_F0; pStr2 = LIGHT_LOAD_F1; break; case 6: --total; pStr1 = LIGHT_LOAD_G0; pStr2 = LIGHT_LOAD_G1; break; } SET_GAME_STATE (LIGHT_MINERAL_LOAD, total); } else if (total < 2500) { total = GET_GAME_STATE (MEDIUM_MINERAL_LOAD); switch (total++) { case 0: pStr1 = MEDIUM_LOAD_A0; pStr2 = MEDIUM_LOAD_A1; break; case 1: pStr1 = MEDIUM_LOAD_B0; pStr2 = MEDIUM_LOAD_B1; break; case 2: pStr1 = MEDIUM_LOAD_C0; pStr2 = MEDIUM_LOAD_C1; break; case 3: pStr1 = MEDIUM_LOAD_D0; pStr2 = MEDIUM_LOAD_D1; break; case 4: pStr1 = MEDIUM_LOAD_E0; pStr2 = MEDIUM_LOAD_E1; break; case 5: pStr1 = MEDIUM_LOAD_F0; pStr2 = MEDIUM_LOAD_F1; break; case 6: --total; pStr1 = MEDIUM_LOAD_G0; pStr2 = MEDIUM_LOAD_G1; break; } SET_GAME_STATE (MEDIUM_MINERAL_LOAD, total); } else { total = GET_GAME_STATE (HEAVY_MINERAL_LOAD); switch (total++) { case 0: pStr1 = HEAVY_LOAD_A0; pStr2 = HEAVY_LOAD_A1; break; case 1: pStr1 = HEAVY_LOAD_B0; pStr2 = HEAVY_LOAD_B1; break; case 2: pStr1 = HEAVY_LOAD_C0; pStr2 = HEAVY_LOAD_C1; break; case 3: pStr1 = HEAVY_LOAD_D0; pStr2 = HEAVY_LOAD_D1; break; case 4: pStr1 = HEAVY_LOAD_E0; pStr2 = HEAVY_LOAD_E1; break; case 5: pStr1 = HEAVY_LOAD_F0; pStr2 = HEAVY_LOAD_F1; break; case 6: --total; pStr1 = HEAVY_LOAD_G0; pStr2 = HEAVY_LOAD_G1; break; } SET_GAME_STATE (HEAVY_MINERAL_LOAD, total); } NPCPhrase (pStr1); if (speechVolumeScale == 0.0f) { NPCPhrase (SPACE); NPCPhrase (GLOBAL_PLAYER_NAME); } NPCPhrase (pStr2); NormalStarbase (R); } static void Intro (void) { NormalStarbase (NULL_PTR); } static COUNT uninit_starbase (void) { return (0); } static void post_starbase_enc (void) { SET_GAME_STATE (MOONBASE_ON_SHIP, 0); if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) { SET_GAME_STATE (CHMMR_BOMB_STATE, 3); } } LOCDATAPTR init_starbase_comm () { LOCDATAPTR retval; commander_desc.init_encounter_func = Intro; commander_desc.post_encounter_func = post_starbase_enc; commander_desc.uninit_encounter_func = uninit_starbase; commander_desc.AlienTextWidth = 143; commander_desc.AlienTextBaseline.x = 164; commander_desc.AlienTextBaseline.y = 20; // use alternate Starbase track if available commander_desc.AlienAltSong = STARBASE_ALT_MUSIC; commander_desc.AlienSongFlags |= LDASF_USE_ALTERNATE; CurBulletinMask = 0; SET_GAME_STATE (BATTLE_SEGUE, 0); retval = &commander_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/starbas/strings.h0000600000175000017500000001400310543202025020032 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, BEFORE_WE_GO_ON_1, BEFORE_WE_GO_ON_2, BEFORE_WE_GO_ON_3, BEFORE_WE_GO_ON_4, BEFORE_WE_GO_ON_5, BEFORE_WE_GO_ON_6, BEFORE_WE_GO_ON_7, NORMAL_HELLO_A0, NORMAL_HELLO_A1, NORMAL_HELLO_B0, NORMAL_HELLO_B1, NORMAL_HELLO_C0, NORMAL_HELLO_C1, NORMAL_HELLO_D0, NORMAL_HELLO_D1, NORMAL_HELLO_E0, NORMAL_HELLO_E1, NORMAL_HELLO_F0, NORMAL_HELLO_F1, NORMAL_HELLO_G0, NORMAL_HELLO_G1, NORMAL_HELLO_H0, NORMAL_HELLO_H1, RETURN_HELLO, NORMAL_HELLO_TAIL, NORMAL_GOODBYE_A0, NORMAL_GOODBYE_A1, NORMAL_GOODBYE_B0, NORMAL_GOODBYE_B1, NORMAL_GOODBYE_C0, NORMAL_GOODBYE_C1, NORMAL_GOODBYE_D0, NORMAL_GOODBYE_D1, NORMAL_GOODBYE_E0, NORMAL_GOODBYE_E1, NORMAL_GOODBYE_F0, NORMAL_GOODBYE_F1, NORMAL_GOODBYE_G0, NORMAL_GOODBYE_G1, NORMAL_GOODBYE_H0, NORMAL_GOODBYE_H1, LIGHT_LOAD_A0, LIGHT_LOAD_A1, LIGHT_LOAD_B0, LIGHT_LOAD_B1, LIGHT_LOAD_C0, LIGHT_LOAD_C1, LIGHT_LOAD_D0, LIGHT_LOAD_D1, LIGHT_LOAD_E0, LIGHT_LOAD_E1, LIGHT_LOAD_F0, LIGHT_LOAD_F1, LIGHT_LOAD_G0, LIGHT_LOAD_G1, MEDIUM_LOAD_A0, MEDIUM_LOAD_A1, MEDIUM_LOAD_B0, MEDIUM_LOAD_B1, MEDIUM_LOAD_C0, MEDIUM_LOAD_C1, MEDIUM_LOAD_D0, MEDIUM_LOAD_D1, MEDIUM_LOAD_E0, MEDIUM_LOAD_E1, MEDIUM_LOAD_F0, MEDIUM_LOAD_F1, MEDIUM_LOAD_G0, MEDIUM_LOAD_G1, HEAVY_LOAD_A0, HEAVY_LOAD_A1, HEAVY_LOAD_B0, HEAVY_LOAD_B1, HEAVY_LOAD_C0, HEAVY_LOAD_C1, HEAVY_LOAD_D0, HEAVY_LOAD_D1, HEAVY_LOAD_E0, HEAVY_LOAD_E1, HEAVY_LOAD_F0, HEAVY_LOAD_F1, HEAVY_LOAD_G0 , HEAVY_LOAD_G1, STARBASE_IS_READY_A, STARBASE_IS_READY_B, STARBASE_IS_READY_C, WHAT_KIND_OF_INFO, WHICH_FUNCTION, WHICH_HISTORY, WHICH_MISSION, OK_NO_NEED_INFO, ABOUT_FUEL, ABOUT_MODULES, ABOUT_CREW0, ABOUT_CREW1, ABOUT_SHIPS, ABOUT_RU, ABOUT_MINERALS, ABOUT_LIFE, OK_ENOUGH_STARBASE, OK_ENOUGH_MISSION, GET_MINERALS, ABOUT_ALIENS, MUST_DEFEAT, DEFEAT_LIKE_SO, FIND_URQUAN, FIGHT_URQUAN, ALLY_LIKE_SO, STRONG_LIKE_SO, OK_ENOUGH_DEFEAT, WHICH_ALIEN, WHICH_WAR, WHICH_ANCIENT, OK_ENOUGH_HISTORY, WHICH_ALLIANCE, WHICH_HIERARCHY, ABOUT_OTHER, OK_ENOUGH_ALIENS, ABOUT_SHOFIXTI, ABOUT_YEHAT, ABOUT_ARILOU, ABOUT_CHENJESU, ABOUT_MMRNMHRM, ABOUT_SYREEN, OK_ENOUGH_ALLIANCE, ABOUT_URQUAN, ABOUT_MYCON, ABOUT_SPATHI, ABOUT_UMGAH, ABOUT_ANDROSYNTH, ABOUT_VUX, ABOUT_ILWRATH, OK_ENOUGH_HIERARCHY, ABOUT_PRECURSORS, ABOUT_OLD_RACES, ABOUT_ALIENS_ON_EARTH, OK_ENOUGH_ANCIENT, URQUAN_STARTED_WAR, WAR_WAS_LIKE_SO, LOST_WAR_BECAUSE, AFTER_WAR, OK_ENOUGH_WAR, STARBASE_BULLETIN_TAIL, BETWEEN_BULLETINS, STARBASE_BULLETIN_1, STARBASE_BULLETIN_2, STARBASE_BULLETIN_3, STARBASE_BULLETIN_4, STARBASE_BULLETIN_5, STARBASE_BULLETIN_6, STARBASE_BULLETIN_7, STARBASE_BULLETIN_8, STARBASE_BULLETIN_9, STARBASE_BULLETIN_10, STARBASE_BULLETIN_11, STARBASE_BULLETIN_12, STARBASE_BULLETIN_13, STARBASE_BULLETIN_14, STARBASE_BULLETIN_15, STARBASE_BULLETIN_16, STARBASE_BULLETIN_18, STARBASE_BULLETIN_19, STARBASE_BULLETIN_22, STARBASE_BULLETIN_27, STARBASE_BULLETIN_28, STARBASE_BULLETIN_29, STARBASE_BULLETIN_30, DEVICE_HEAD, BETWEEN_DEVICES, DEVICE_TAIL, ABOUT_PORTAL, ABOUT_TALKPET, ABOUT_BOMB, ABOUT_SUN, ABOUT_MAIDENS, ABOUT_SPHERE, ABOUT_HELIX, ABOUT_SPINDLE, ABOUT_ULTRON_0, ABOUT_ULTRON_1, ABOUT_ULTRON_2, ABOUT_ULTRON_3, ABOUT_UCASTER, ABOUT_BCASTER, ABOUT_SHIELD, ABOUT_EGGCASE_0, ABOUT_SHUTTLE, ABOUT_VUXBEAST0, ABOUT_VUXBEAST1, ABOUT_DESTRUCT, ABOUT_WARPPOD, ABOUT_ARTIFACT_2, ABOUT_ARTIFACT_3, LETS_SEE, GO_GET_MINERALS, IMPROVE_FLAGSHIP_WITH_RU, GOT_OK_FLAGSHIP, GO_ALLY_WITH_ALIENS, MADE_SOME_ALLIES, GET_SHIPS_BY_MINING_OR_ALLIANCE, GOT_OK_FLEET, BUY_COMBAT_SHIPS, GO_LEARN_ABOUT_URQUAN, MAKE_FLAGSHIP_AWESOME, KNOW_ABOUT_SAMATRA, GOT_AWESOME_FLAGSHIP, GOT_BOMB, FIND_WAY_TO_DESTROY_SAMATRA, MUST_INCREASE_BOMB_STRENGTH, MUST_ACQUIRE_AWESOME_FLEET, MUST_ELIMINATE_URQUAN_GUARDS, CHMMR_IMPROVED_BOMB, GOT_AWESOME_FLEET, GO_DESTROY_SAMATRA, GOOD_LUCK_AGAIN, IMPROVE_1, IMPROVE_2, NEED_THRUSTERS_1, NEED_THRUSTERS_2, NEED_TURN_1, NEED_TURN_2, NEED_GUNS_1, NEED_GUNS_2, NEED_CREW_1, NEED_CREW_2, NEED_FUEL_1, NEED_FUEL_2, NEED_STORAGE_1, NEED_LANDERS_2, NEED_LANDERS_1, NEED_DYNAMOS_1, NEED_DYNAMOS_2, NEED_POINT, have_minerals, goodbye_commander, repeat_bulletins, need_info, starbase_functions, history, our_mission, no_need_info, enough_starbase, enough_mission, tell_me_about_fuel0, tell_me_about_fuel1, tell_me_about_modules0, tell_me_about_modules1, tell_me_about_crew, tell_me_about_ships, tell_me_about_ru, tell_me_about_minerals, tell_me_about_life, where_get_minerals, what_about_aliens, what_about_urquan, how_defeat, how_find_urquan, how_fight_urquan, how_ally, enough_defeat, alien_races, the_war, ancient_history, enough_history, what_about_alliance, what_about_hierarchy, what_about_other, enough_aliens, shofixti, yehat, arilou, chenjesu, mmrnmhrm, syreen, enough_alliance, urquan, mycon, spathi, umgah, androsynth, vux, ilwrath, enough_hierarchy, precursors, old_races, aliens_on_earth, enough_ancient, what_started_war, what_was_war_like, why_lose_war, what_after_war, enough_war, new_devices, how_get_strong, what_do_now, YOUR_FLAGSHIP_PC, YOUR_FLAGSHIP_3DO0, YOUR_FLAGSHIP_3DO1, YOUR_FLAGSHIP_3DO2, SPACE, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/starbas/Makeinfo0000600000175000017500000000002710543202025017645 0ustar joeyjoeyuqm_CFILES="starbas.c" uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/0000755000175000017500000000000010552600275016226 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/ilwrath/ifontres.h0000600000175000017500000000004310543202032020202 0ustar joeyjoey#define ILWRATH_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/restypes.h0000600000175000017500000000024110543202032020227 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/strings.h0000600000175000017500000000525510543202032020054 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, NEVER_ENOUGH, OK_WARSHIP, OK_DWE, OK_YOUBOO, OK_DILRAT, BIG_FUN, FAST_AS_CAN, GLORIOUS_WORSHIP, ON_WAY, GODS_RETURN_1, GODS_RETURN_2, GODS_RETURN_3, JUST_GRUNTS, GRUNTS_AGAIN, WHAT_ORDERS, WE_WORSHIP_1, WE_WORSHIP_2, WE_WORSHIP_3, SUBSEQUENT_CHMMR_HELLO, INIT_CHMMR_HELLO, OK_ENOUGH_ILWRATH, OK_ENOUGH_GODS, SEND_MESSAGE, CAME_FROM, WHO_BLASTS_WHO, NO_SURRENDER, NOT_REASONABLE, SUBSEQUENT_HOME_HELLO, GENERAL_INFO, GOODBYE_AND_DIE, DECEIVERS, NO_PEACE, NO_ALLIANCE, ILWRATH_BELIEVE, OK_KILL_THRADDASH, GOODBYE_GODS, INIT_HELLO_SPACE, SUBSEQUENT_HELLO_SPACE_1, SUBSEQUENT_HELLO_SPACE_2, SUBSEQUENT_HELLO_SPACE_3, SUBSEQUENT_HELLO_SPACE_4, GENERAL_INFO_SPACE_1, GENERAL_INFO_SPACE_2, GENERAL_INFO_SPACE_3, GENERAL_INFO_SPACE_4, GENERAL_INFO_SPACE_5, STRENGTH_NOT_ALL, NO_SLAY_BY_THOUSANDS, NO_EASE_UP, GOODBYE_AND_DIE_SPACE, INIT_HOME_HELLO, GOODBYE_AND_DIE_HOMEWORLD, SO_MUCH_TO_KNOW, LONG_AGO, KILLED_GOOD_GODS, CHANNEL_44, BECAUSE_44, WHAT_ABOUT_ILWRATH, ABOUT_PHYSIO, ABOUT_HISTORY, ABOUT_CULTURE, ABOUT_URQUAN, URQUAN_TOO_NICE, OF_COURSE_WERE_EVIL, DONT_CONFUSE_US, ON_WAY_TO_THRADDASH, HAPPY_FIGHTING_THRADDASH, say_warship, say_dwe, say_youboo, say_dillrat, enough_orders, other_divine_orders, worship_us, bye_gods, enough_ilwrath, enough_gods, where_you_come_from, it_will_be_a_pleasure, be_reasonable, surrender, whats_up, bye, want_peace, want_alliance, go_kill_thraddash, whats_up_space_1, whats_up_space_2, whats_up_space_3, whats_up_space_4, whats_up_space_5, you_are_weak, slay_by_thousands, ease_up, bye_space, bye_homeworld, want_info_on_gods, when_start_worship, any_good_gods, how_talk_with_gods, why_44, want_info_on_ilwrath, what_about_physio, what_about_history, what_about_culture, what_about_urquan, are_you_evil, but_evil_is_defined, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/igfxres.h0000600000175000017500000000005010543202032020016 0ustar joeyjoey#define ILWRATH_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/istrtab.h0000600000175000017500000000013010543202032020016 0ustar joeyjoey#define ILWRATH_CONVERSATION_PHRASES 0x00200004L #define ILWRATH_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/imusicre.h0000600000175000017500000000004410543202032020172 0ustar joeyjoey#define ILWRATH_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/ilwrath.res0000600000175000017500000000037510543202032020375 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/ilwrath PACKAGE ILWRATH_PACKAGE ilwrath.con GFXRES ILWRATH_PMAP_ANIM ilwrath.ani FONTRES ILWRATH_FONT ilwrath.fon MUSICRES ILWRATH_MUSIC ilwrath.mod STRTAB ILWRATH_CONVERSATION_PHRASES ilwrath.txt uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/Makeinfo0000600000175000017500000000003010543202032017650 0ustar joeyjoeyuqm_CFILES="ilwrathc.c" uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/respkg.h0000600000175000017500000000004010543202032017641 0ustar joeyjoeyenum { ILWRATH_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/resinst.h0000600000175000017500000000012610543202032020042 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/ilwrath/ilwrathc.c0000600000175000017500000003415710543202032020176 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/ilwrath/resinst.h" #include "comm/ilwrath/strings.h" #include "gameev.h" static LOCDATA ilwrath_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)ILWRATH_PMAP_ANIM, /* AlienFrame */ (FONT)ILWRATH_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_MIDDLE, /* AlienTextValign */ (COLORMAP)ILWRATH_COLOR_MAP, /* AlienColorMap */ ILWRATH_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ ILWRATH_CONVERSATION_PHRASES, /* PlayerPhrases */ 4, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 6, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 11, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 16, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 21, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 5, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void CombatIsInevitable (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, you_are_weak)) NPCPhrase (STRENGTH_NOT_ALL); else if (PLAYER_SAID (R, slay_by_thousands)) NPCPhrase (NO_SLAY_BY_THOUSANDS); else if (PLAYER_SAID (R, ease_up)) NPCPhrase (NO_EASE_UP); else if (PLAYER_SAID (R, bye_space)) NPCPhrase (GOODBYE_AND_DIE_SPACE); else if (PLAYER_SAID (R, bye_homeworld)) NPCPhrase (GOODBYE_AND_DIE_HOMEWORLD); else if (PLAYER_SAID (R, want_peace)) NPCPhrase (NO_PEACE); else if (PLAYER_SAID (R, want_alliance)) NPCPhrase (NO_ALLIANCE); else if (PLAYER_SAID (R, but_evil_is_defined)) NPCPhrase (DONT_CONFUSE_US); else if (PLAYER_SAID (R, bye_gods)) { NPCPhrase (GOODBYE_GODS); SET_GAME_STATE (BATTLE_SEGUE, 0); } if (PLAYER_SAID (R, whats_up)) { NPCPhrase (GENERAL_INFO); Response (bye, CombatIsInevitable); } else if (PLAYER_SAID (R, whats_up_space_1) || PLAYER_SAID (R, whats_up_space_2) || PLAYER_SAID (R, whats_up_space_3) || PLAYER_SAID (R, whats_up_space_4) || PLAYER_SAID (R, whats_up_space_5)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (ILWRATH_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_SPACE_1); break; case 1: NPCPhrase (GENERAL_INFO_SPACE_2); break; case 2: NPCPhrase (GENERAL_INFO_SPACE_3); break; case 3: NPCPhrase (GENERAL_INFO_SPACE_4); break; case 4: NPCPhrase (GENERAL_INFO_SPACE_5); --NumVisits; break; } SET_GAME_STATE (ILWRATH_INFO, NumVisits); } else { if (PLAYER_SAID (R, bye)) NPCPhrase (GOODBYE_AND_DIE); else if (PLAYER_SAID (R, where_you_come_from)) NPCPhrase (CAME_FROM); if (PLAYER_SAID (R, it_will_be_a_pleasure)) NPCPhrase (WHO_BLASTS_WHO); if (PLAYER_SAID (R, surrender)) NPCPhrase (NO_SURRENDER); if (PLAYER_SAID (R, be_reasonable)) NPCPhrase (NOT_REASONABLE); } } static void IlwrathHome (RESPONSE_REF R); static void IlwrathGods (RESPONSE_REF R) { BYTE GodsLeft; GodsLeft = FALSE; if (PLAYER_SAID (R, want_info_on_gods)) NPCPhrase (SO_MUCH_TO_KNOW); else if (PLAYER_SAID (R, when_start_worship)) { NPCPhrase (LONG_AGO); DISABLE_PHRASE (when_start_worship); } else if (PLAYER_SAID (R, any_good_gods)) { NPCPhrase (KILLED_GOOD_GODS); DISABLE_PHRASE (any_good_gods); } else if (PLAYER_SAID (R, how_talk_with_gods)) { NPCPhrase (CHANNEL_44); DISABLE_PHRASE (how_talk_with_gods); } else if (PLAYER_SAID (R, why_44)) { NPCPhrase (BECAUSE_44); DISABLE_PHRASE (why_44); } if (PHRASE_ENABLED (when_start_worship)) { Response (when_start_worship, IlwrathGods); GodsLeft = TRUE; } if (PHRASE_ENABLED (any_good_gods)) { Response (any_good_gods, IlwrathGods); GodsLeft = TRUE; } if (PHRASE_ENABLED (how_talk_with_gods)) { Response (how_talk_with_gods, IlwrathGods); GodsLeft = TRUE; } else if (PHRASE_ENABLED (why_44)) { Response (why_44, IlwrathGods); GodsLeft = TRUE; } Response (enough_gods, IlwrathHome); if (!GodsLeft) DISABLE_PHRASE (want_info_on_gods); } static void IlwrathInfo (RESPONSE_REF R) { BYTE InfoLeft; InfoLeft = FALSE; if (PLAYER_SAID (R, want_info_on_ilwrath)) NPCPhrase (WHAT_ABOUT_ILWRATH); else if (PLAYER_SAID (R, what_about_physio)) { NPCPhrase (ABOUT_PHYSIO); DISABLE_PHRASE (what_about_physio); } else if (PLAYER_SAID (R, what_about_history)) { NPCPhrase (ABOUT_HISTORY); DISABLE_PHRASE (what_about_history); } else if (PLAYER_SAID (R, what_about_culture)) { NPCPhrase (ABOUT_CULTURE); DISABLE_PHRASE (what_about_culture); } else if (PLAYER_SAID (R, what_about_urquan)) { NPCPhrase (URQUAN_TOO_NICE); DISABLE_PHRASE (what_about_urquan); } else if (PLAYER_SAID (R, are_you_evil)) { NPCPhrase (OF_COURSE_WERE_EVIL); DISABLE_PHRASE (are_you_evil); } if (PHRASE_ENABLED (what_about_physio)) { Response (what_about_physio, IlwrathInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_history)) { Response (what_about_history, IlwrathInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_culture)) { Response (what_about_culture, IlwrathInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_urquan)) { Response (what_about_urquan, IlwrathInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (are_you_evil)) { Response (are_you_evil, IlwrathInfo); InfoLeft = TRUE; } else { Response (but_evil_is_defined, CombatIsInevitable); InfoLeft = TRUE; } Response (enough_ilwrath, IlwrathHome); if (!InfoLeft) DISABLE_PHRASE (want_info_on_ilwrath); } static void IlwrathHome (RESPONSE_REF R) { if (R == 0) { BYTE NumVisits; NumVisits = GET_GAME_STATE (ILWRATH_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (INIT_HOME_HELLO); break; case 1: NPCPhrase (SUBSEQUENT_HOME_HELLO); --NumVisits; break; } SET_GAME_STATE (ILWRATH_HOME_VISITS, NumVisits); } else if (PLAYER_SAID (R, enough_gods)) NPCPhrase (OK_ENOUGH_GODS); else if (PLAYER_SAID (R, enough_ilwrath)) NPCPhrase (OK_ENOUGH_ILWRATH); if (PHRASE_ENABLED (want_info_on_gods)) { Response (want_info_on_gods, IlwrathGods); } if (PHRASE_ENABLED (want_info_on_ilwrath)) { Response (want_info_on_ilwrath, IlwrathInfo); } Response (want_peace, CombatIsInevitable); Response (want_alliance, CombatIsInevitable); Response (bye_homeworld, CombatIsInevitable); } static void GodsSpeak (RESPONSE_REF R); static void GodsOrder (RESPONSE_REF R) { BYTE OrdersLeft; OrdersLeft = FALSE; if (PLAYER_SAID (R, other_divine_orders)) NPCPhrase (WHAT_ORDERS); else if (PLAYER_SAID (R, say_warship)) { NPCPhrase (OK_WARSHIP); DISABLE_PHRASE (say_warship); } else if (PLAYER_SAID (R, say_dwe)) { NPCPhrase (OK_DWE); DISABLE_PHRASE (say_dwe); } else if (PLAYER_SAID (R, say_youboo)) { NPCPhrase (OK_YOUBOO); DISABLE_PHRASE (say_youboo); } else if (PLAYER_SAID (R, say_dillrat)) { NPCPhrase (OK_DILRAT); DISABLE_PHRASE (say_dillrat); } if (PHRASE_ENABLED (say_warship)) { Response (say_warship, GodsOrder); OrdersLeft = TRUE; } if (PHRASE_ENABLED (say_dwe)) { Response (say_dwe, GodsOrder); OrdersLeft = TRUE; } if (PHRASE_ENABLED (say_youboo)) { Response (say_youboo, GodsOrder); OrdersLeft = TRUE; } if (PHRASE_ENABLED (say_dillrat)) { Response (say_dillrat, GodsOrder); OrdersLeft = TRUE; } Response (enough_orders, GodsSpeak); if (!OrdersLeft) DISABLE_PHRASE (other_divine_orders); } static void GodsSpeak (RESPONSE_REF R) { BYTE NumVisits; if (R == 0) { if (GET_GAME_STATE (ILWRATH_FIGHT_THRADDASH)) NPCPhrase (GLORIOUS_WORSHIP); else if (GET_GAME_STATE (ILWRATH_DECEIVED)) NPCPhrase (ON_WAY); else { NumVisits = GET_GAME_STATE (ILWRATH_GODS_SPOKEN); switch (NumVisits++) { case 0: NPCPhrase (ILWRATH_BELIEVE); break; case 1: NPCPhrase (GODS_RETURN_1); break; case 2: NPCPhrase (GODS_RETURN_2); break; case 3: NPCPhrase (GODS_RETURN_3); --NumVisits; break; } SET_GAME_STATE (ILWRATH_GODS_SPOKEN, NumVisits); } } else if (PLAYER_SAID (R, go_kill_thraddash)) { NPCPhrase (OK_KILL_THRADDASH); SET_GAME_STATE (ILWRATH_DECEIVED, 1); AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_ILWRATH_MISSION); } else if (PLAYER_SAID (R, worship_us)) { NumVisits = GET_GAME_STATE (ILWRATH_WORSHIP); switch (NumVisits++) { case 0: NPCPhrase (WE_WORSHIP_1); break; case 1: NPCPhrase (WE_WORSHIP_2); break; case 2: NPCPhrase (WE_WORSHIP_3); --NumVisits; break; } SET_GAME_STATE (ILWRATH_WORSHIP, NumVisits); DISABLE_PHRASE (worship_us); } else if (PLAYER_SAID (R, enough_orders)) NPCPhrase (NEVER_ENOUGH); if (!GET_GAME_STATE (ILWRATH_DECEIVED)) Response (go_kill_thraddash, GodsSpeak); if (PHRASE_ENABLED (worship_us)) Response (worship_us, GodsSpeak); if (PHRASE_ENABLED (other_divine_orders)) { Response (other_divine_orders, GodsOrder); } Response (bye_gods, CombatIsInevitable); } static void IlwrathSpace (RESPONSE_REF R) { BYTE NumVisits; if (R == 0) { NumVisits = GET_GAME_STATE (ILWRATH_VISITS); switch (NumVisits++) { case 0: NPCPhrase (INIT_HELLO_SPACE); break; case 1: NPCPhrase (SUBSEQUENT_HELLO_SPACE_1); break; case 2: NPCPhrase (SUBSEQUENT_HELLO_SPACE_2); break; case 3: NPCPhrase (SUBSEQUENT_HELLO_SPACE_3); break; case 4: NPCPhrase (SUBSEQUENT_HELLO_SPACE_4); --NumVisits; break; } SET_GAME_STATE (ILWRATH_VISITS, NumVisits); } NumVisits = GET_GAME_STATE (ILWRATH_INFO); switch (NumVisits) { case 0: Response (whats_up_space_1, CombatIsInevitable); break; case 1: Response (whats_up_space_2, CombatIsInevitable); break; case 2: Response (whats_up_space_3, CombatIsInevitable); break; case 3: Response (whats_up_space_4, CombatIsInevitable); break; case 4: Response (whats_up_space_5, CombatIsInevitable); break; } Response (you_are_weak, CombatIsInevitable); Response (slay_by_thousands, CombatIsInevitable); Response (ease_up, CombatIsInevitable); Response (bye_space, CombatIsInevitable); } static void Intro (void) { BYTE NumVisits; if (GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER)) { NPCPhrase (SEND_MESSAGE); Response (where_you_come_from, CombatIsInevitable); Response (it_will_be_a_pleasure, CombatIsInevitable); Response (surrender, CombatIsInevitable); Response (be_reasonable, CombatIsInevitable); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { IlwrathHome ((RESPONSE_REF)0); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { NumVisits = GET_GAME_STATE (ILWRATH_CHMMR_VISITS); switch (NumVisits++) { case 0: NPCPhrase (INIT_CHMMR_HELLO); break; case 1: NPCPhrase (SUBSEQUENT_CHMMR_HELLO); --NumVisits; break; } SET_GAME_STATE (ILWRATH_CHMMR_VISITS, NumVisits); Response (whats_up, CombatIsInevitable); Response (bye, CombatIsInevitable); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 5)) { // Communicating with an Ilwrath ship using a HyperWave Broadcaster. if (GET_GAME_STATE (ILWRATH_FIGHT_THRADDASH)) NPCPhrase (BIG_FUN); else if (GET_GAME_STATE (ILWRATH_DECEIVED)) NPCPhrase (FAST_AS_CAN); else NPCPhrase (JUST_GRUNTS); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 4)) { // Communicating with the Ilwrath homeworld using a // Hyperwave Broadcaster. GodsSpeak ((RESPONSE_REF)0); } else { SET_GAME_STATE (BATTLE_SEGUE, 0); if (GET_GAME_STATE (ILWRATH_FIGHT_THRADDASH)) NPCPhrase (HAPPY_FIGHTING_THRADDASH); else if (GET_GAME_STATE (ILWRATH_DECEIVED)) NPCPhrase (ON_WAY_TO_THRADDASH); else IlwrathSpace ((RESPONSE_REF)0); } } static COUNT uninit_ilwrath (void) { return (0); } static void post_ilwrath_enc (void) { // nothing defined so far } LOCDATAPTR init_ilwrath_comm (void) { LOCDATAPTR retval; ilwrath_desc.init_encounter_func = Intro; ilwrath_desc.post_encounter_func = post_ilwrath_enc; ilwrath_desc.uninit_encounter_func = uninit_ilwrath; ilwrath_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); ilwrath_desc.AlienTextBaseline.y = 70; ilwrath_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if (GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER) || (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & ((1 << 4) | (1 << 5))) || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &ilwrath_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/urquan/0000755000175000017500000000000010552600275016067 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/urquan/urquanc.c0000600000175000017500000003073310543202033017675 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/urquan/resinst.h" #include "comm/urquan/strings.h" static LOCDATA urquan_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)URQUAN_PMAP_ANIM, /* AlienFrame */ (FONT)URQUAN_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)URQUAN_COLOR_MAP, /* AlienColorMap */ URQUAN_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ URQUAN_CONVERSATION_PHRASES, /* PlayerPhrases */ 7, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 7, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND / 10, 0, /* RestartRate */ 0, /* BlockMask */ }, { 13, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 16, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 19, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 22, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 29, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 36, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 1, /* StartIndex */ 2, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 6, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 2, /* StartIndex */ 5, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void CombatIsInevitable (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, you_must_surrender)) NPCPhrase (NOPE); else if (PLAYER_SAID (R, whats_up_1) || PLAYER_SAID (R, whats_up_2) || PLAYER_SAID (R, whats_up_3) || PLAYER_SAID (R, whats_up_4)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (URQUAN_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_1); break; case 1: NPCPhrase (GENERAL_INFO_2); break; case 2: NPCPhrase (GENERAL_INFO_3); break; case 3: NPCPhrase (GENERAL_INFO_4); --NumVisits; break; } SET_GAME_STATE (URQUAN_INFO, NumVisits); } else if (PLAYER_SAID (R, i_wont_surrender)) NPCPhrase (BAD_CHOICE); else if (PLAYER_SAID (R, i_will_surrender)) { NPCPhrase (GOOD_CHOICE); SET_GAME_STATE (BATTLE_SEGUE, 0); GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; GLOBAL (CurrentActivity) |= CHECK_RESTART; } else if (PLAYER_SAID (R, like_to_leave)) NPCPhrase (INDEPENDENCE_IS_BAD); else if (PLAYER_SAID (R, bye_wars_over)) { NPCPhrase (GOODBYE_WARS_OVER); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (PLAYER_SAID (R, bye_sub_hypno)) NPCPhrase (GOODBYE_AND_DIE_SUB_HYPNO); else if (PLAYER_SAID (R, bye_init_hypno)) { NPCPhrase (GOODBYE_AND_DIE_INIT_HYPNO); SET_GAME_STATE (URQUAN_HYPNO_VISITS, 1); } else if (PLAYER_SAID (R, terran_amphibian) || PLAYER_SAID (R, talking_pet_on_steroids)) { NPCPhrase (BAD_NEWS); SET_GAME_STATE (BATTLE_SEGUE, 0); SET_GAME_STATE (URQUAN_HYPNO_VISITS, 1); } else if (PLAYER_SAID (R, falling_asleep) || PLAYER_SAID (R, someone_else_controlled)) { NPCPhrase (SOUNDS_FAMILIAR); SET_GAME_STATE (BATTLE_SEGUE, 0); SET_GAME_STATE (URQUAN_HYPNO_VISITS, 1); } } static void DescribePet (RESPONSE_REF R) { if (PLAYER_SAID (R, wascally_little_guy)) NPCPhrase (WHAT_IT_LOOK_LIKE); else if (PLAYER_SAID (R, turd_and_toad)) { NPCPhrase (WHAT_IS_TURD_AND_TOAD); DISABLE_PHRASE (turd_and_toad); } Response (terran_amphibian, CombatIsInevitable); Response (talking_pet_on_steroids, CombatIsInevitable); if (PHRASE_ENABLED (turd_and_toad)) { Response (turd_and_toad, DescribePet); } } static void DescribeCompulsion (RESPONSE_REF R) { if (PLAYER_SAID (R, alien_mind_control)) NPCPhrase (WHAT_FELT_LIKE); else if (PLAYER_SAID (R, before_coffee)) { NPCPhrase (EXPLAIN); DISABLE_PHRASE (before_coffee); } Response (falling_asleep, CombatIsInevitable); Response (someone_else_controlled, CombatIsInevitable); if (PHRASE_ENABLED (before_coffee)) { Response (before_coffee, DescribeCompulsion); } } static void MentionCompulsion (RESPONSE_REF R) { if (PLAYER_SAID (R, compulsion)) { NPCPhrase (WHAT_COMPULSION); SET_GAME_STATE (MENTIONED_PET_COMPULSION, 1); } else if (PLAYER_SAID (R, possessed_by_devil)) { NPCPhrase (STUPID_DEVIL); DISABLE_PHRASE (possessed_by_devil); } else if (PLAYER_SAID (R, why_explain)) { NPCPhrase (MUST_EXPLAIN); DISABLE_PHRASE (why_explain); } Response (wascally_little_guy, DescribePet); Response (alien_mind_control, DescribeCompulsion); if (PHRASE_ENABLED (possessed_by_devil)) Response (possessed_by_devil, MentionCompulsion); if (PHRASE_ENABLED (why_explain)) Response (why_explain, MentionCompulsion); } static void UrquanHypno (RESPONSE_REF R) { if (GET_GAME_STATE (URQUAN_HYPNO_VISITS) == 0) { if (R == 0) NPCPhrase (INIT_URQUAN_WAKE_UP); else if (PLAYER_SAID (R, where_am_i)) { NPCPhrase (YOU_ARE_HERE); DISABLE_PHRASE (where_am_i); } else if (PLAYER_SAID (R, why_does_my_head_hurt)) { NPCPhrase (HURTS_BECAUSE); DISABLE_PHRASE (why_does_my_head_hurt); } else if (PLAYER_SAID (R, what_about_2_weeks)) { NPCPhrase (ABOUT_2_WEEKS); DISABLE_PHRASE (what_about_2_weeks); } if (PHRASE_ENABLED (where_am_i)) Response (where_am_i, UrquanHypno); if (PHRASE_ENABLED (why_does_my_head_hurt)) Response (why_does_my_head_hurt, UrquanHypno); if (PHRASE_ENABLED (what_about_2_weeks)) Response (what_about_2_weeks, UrquanHypno); Response (compulsion, MentionCompulsion); Response (bye_init_hypno, CombatIsInevitable); } else { if (R == 0) NPCPhrase (SUBSEQUENT_URQUAN_WAKE_UP); else if (PLAYER_SAID (R, uh_oh)) { NPCPhrase (NO_UH_OH); DISABLE_PHRASE (uh_oh); } else if (PLAYER_SAID (R, stop_meeting)) { NPCPhrase (NO_STOP_MEETING); DISABLE_PHRASE (stop_meeting); } if (PHRASE_ENABLED (uh_oh)) Response (uh_oh, UrquanHypno); if (PHRASE_ENABLED (stop_meeting)) Response (stop_meeting, UrquanHypno); if (!GET_GAME_STATE (MENTIONED_PET_COMPULSION)) { Response (compulsion, MentionCompulsion); } Response (bye_sub_hypno, CombatIsInevitable); } } static void NormalUrquan (RESPONSE_REF R) { if (PLAYER_SAID (R, i_surrender)) { NPCPhrase (DISOBEDIENCE_PUNISHED); Response (i_wont_surrender, CombatIsInevitable); Response (i_will_surrender, CombatIsInevitable); } else { if (PLAYER_SAID (R, key_phrase)) { NPCPhrase (URQUAN_STORY); SET_GAME_STATE (KNOW_URQUAN_STORY, 2); } Response (you_must_surrender, CombatIsInevitable); if (GET_GAME_STATE (KNOW_URQUAN_STORY) == 1) { Response (key_phrase, NormalUrquan); } switch (GET_GAME_STATE (URQUAN_INFO)) { case 0: Response (whats_up_1, CombatIsInevitable); break; case 1: Response (whats_up_2, CombatIsInevitable); break; case 2: Response (whats_up_3, CombatIsInevitable); break; case 3: Response (whats_up_4, CombatIsInevitable); break; } Response (i_surrender, NormalUrquan); Response (like_to_leave, CombatIsInevitable); } } static void LoserUrquan (RESPONSE_REF R) { if (PLAYER_SAID (R, why_flee)) { NPCPhrase (FLEE_BECAUSE); DISABLE_PHRASE (why_flee); } else if (PLAYER_SAID (R, what_happens_now)) { NPCPhrase (HAPPENS_NOW); DISABLE_PHRASE (what_happens_now); } else if (PLAYER_SAID (R, what_about_you)) { NPCPhrase (ABOUT_US); DISABLE_PHRASE (what_about_you); } if (PHRASE_ENABLED (why_flee)) Response (why_flee, LoserUrquan); if (PHRASE_ENABLED (what_happens_now)) Response (what_happens_now, LoserUrquan); if (PHRASE_ENABLED (what_about_you)) Response (what_about_you, LoserUrquan); Response (bye_wars_over, CombatIsInevitable); } static void Intro (void) { DWORD GrpOffs; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } GrpOffs = GET_GAME_STATE_32 (URQUAN_PROBE_GRPOFFS0); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && GLOBAL (BattleGroupRef) && GLOBAL (BattleGroupRef) == GrpOffs) { NPCPhrase (SEND_MESSAGE); SET_GAME_STATE (PROBE_MESSAGE_DELIVERED, 1); } else if (GET_GAME_STATE (PLAYER_HYPNOTIZED)) { UrquanHypno ((RESPONSE_REF)0); } else { BYTE NumVisits; if (!GET_GAME_STATE (URQUAN_SENSES_EVIL) && GET_GAME_STATE (TALKING_PET_ON_SHIP)) { NPCPhrase (SENSE_EVIL); SET_GAME_STATE (URQUAN_SENSES_EVIL, 1); } GrpOffs = GET_GAME_STATE_32 (COLONY_GRPOFFS0); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && GLOBAL (BattleGroupRef) && GLOBAL (BattleGroupRef) == GrpOffs) { NPCPhrase (CAUGHT_YA); SET_GAME_STATE (BATTLE_SEGUE, 1); return; } GrpOffs = GET_GAME_STATE_32 (SAMATRA_GRPOFFS0); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && GLOBAL (BattleGroupRef) && GLOBAL (BattleGroupRef) == GrpOffs) { NPCPhrase (HELLO_SAMATRA); SET_GAME_STATE (AWARE_OF_SAMATRA, 1); SET_GAME_STATE (BATTLE_SEGUE, 1); } else { NumVisits = GET_GAME_STATE (URQUAN_VISITS); if (!GET_GAME_STATE (KOHR_AH_FRENZY)) { switch (NumVisits++) { case 0: NPCPhrase (INIT_HELLO); break; case 1: NPCPhrase (SUBSEQUENT_HELLO_1); break; case 2: NPCPhrase (SUBSEQUENT_HELLO_2); break; case 3: NPCPhrase (SUBSEQUENT_HELLO_3); break; case 4: NPCPhrase (SUBSEQUENT_HELLO_4); --NumVisits; break; } NormalUrquan ((RESPONSE_REF)0); } else { switch (NumVisits++) { case 0: NPCPhrase (INIT_FLEE_HUMAN); LoserUrquan ((RESPONSE_REF)0); break; case 1: NPCPhrase (SUBSEQUENT_FLEE_HUMAN); SET_GAME_STATE (BATTLE_SEGUE, 0); --NumVisits; break; } } SET_GAME_STATE (URQUAN_VISITS, NumVisits); } } } static COUNT uninit_urquan (void) { return (0); } static void post_urquan_enc (void) { SET_GAME_STATE (PLAYER_HYPNOTIZED, 0); } LOCDATAPTR init_urquan_comm (void) { LOCDATAPTR retval; DWORD GrpOffs; urquan_desc.init_encounter_func = Intro; urquan_desc.post_encounter_func = post_urquan_enc; urquan_desc.uninit_encounter_func = uninit_urquan; urquan_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); urquan_desc.AlienTextBaseline.y = 0; urquan_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; GrpOffs = GET_GAME_STATE_32 (URQUAN_PROBE_GRPOFFS0); if (GET_GAME_STATE (PLAYER_HYPNOTIZED) || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE || (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && GLOBAL (BattleGroupRef) && GLOBAL (BattleGroupRef) == GrpOffs)) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &urquan_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/urquan/ifontres.h0000600000175000017500000000004210543202033020043 0ustar joeyjoey#define URQUAN_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/urquan/restypes.h0000600000175000017500000000024110543202033020071 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/urquan/strings.h0000600000175000017500000000417110543202033017712 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, HELLO_SAMATRA, SENSE_EVIL, INIT_URQUAN_WAKE_UP, where_am_i, YOU_ARE_HERE, why_does_my_head_hurt, HURTS_BECAUSE, what_about_2_weeks, ABOUT_2_WEEKS, compulsion, WHAT_COMPULSION, wascally_little_guy, WHAT_IT_LOOK_LIKE, terran_amphibian, talking_pet_on_steroids, BAD_NEWS, turd_and_toad, WHAT_IS_TURD_AND_TOAD, alien_mind_control, WHAT_FELT_LIKE, possessed_by_devil, STUPID_DEVIL, falling_asleep, someone_else_controlled, SOUNDS_FAMILIAR, before_coffee, EXPLAIN, why_explain, MUST_EXPLAIN, bye_init_hypno, GOODBYE_AND_DIE_INIT_HYPNO, SUBSEQUENT_URQUAN_WAKE_UP, uh_oh, NO_UH_OH, stop_meeting, NO_STOP_MEETING, bye_sub_hypno, GOODBYE_AND_DIE_SUB_HYPNO, CAUGHT_YA, INIT_FLEE_HUMAN, SUBSEQUENT_FLEE_HUMAN, why_flee, FLEE_BECAUSE, what_happens_now, HAPPENS_NOW, what_about_you, ABOUT_US, bye_wars_over, GOODBYE_WARS_OVER, SEND_MESSAGE, INIT_HELLO, SUBSEQUENT_HELLO_1, SUBSEQUENT_HELLO_2, SUBSEQUENT_HELLO_3, SUBSEQUENT_HELLO_4, you_must_surrender, NOPE, i_surrender, DISOBEDIENCE_PUNISHED, i_wont_surrender, BAD_CHOICE, i_will_surrender, GOOD_CHOICE, key_phrase, URQUAN_STORY, like_to_leave, INDEPENDENCE_IS_BAD, whats_up_1, GENERAL_INFO_1, whats_up_2, GENERAL_INFO_2, whats_up_3, GENERAL_INFO_3, whats_up_4, GENERAL_INFO_4, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/urquan/igfxres.h0000600000175000017500000000004710543202033017666 0ustar joeyjoey#define URQUAN_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/urquan/istrtab.h0000600000175000017500000000012610543202033017665 0ustar joeyjoey#define URQUAN_CONVERSATION_PHRASES 0x00200004L #define URQUAN_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/urquan/imusicre.h0000600000175000017500000000004310543202033020033 0ustar joeyjoey#define URQUAN_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/urquan/icode.h0000600000175000017500000000010210543202033017272 0ustar joeyjoey#define URQUAN_CODE 0x00200006L typedef RESOURCE CODE_INSTANCE; uqm-0.6.2/sc2/src/sc2code/comm/urquan/urquan.res0000600000175000017500000000036210543202033020074 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/urquan PACKAGE URQUAN_PACKAGE urquan.con GFXRES URQUAN_PMAP_ANIM urquan.ani FONTRES URQUAN_FONT urquan.fon MUSICRES URQUAN_MUSIC urquan.mod STRTAB URQUAN_CONVERSATION_PHRASES urquan.txt uqm-0.6.2/sc2/src/sc2code/comm/urquan/Makeinfo0000600000175000017500000000002710543202033017520 0ustar joeyjoeyuqm_CFILES="urquanc.c" uqm-0.6.2/sc2/src/sc2code/comm/urquan/respkg.h0000600000175000017500000000003710543202033017511 0ustar joeyjoeyenum { URQUAN_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/urquan/resinst.h0000600000175000017500000000012610543202033017704 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/arilou/0000755000175000017500000000000010552600275016047 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/arilou/ifontres.h0000600000175000017500000000004210543202025020024 0ustar joeyjoey#define ARILOU_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/arilou/restypes.h0000600000175000017500000000024110543202025020052 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/arilou/strings.h0000600000175000017500000000514410543202025017674 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, INIT_HELLO, confused_by_hello, CONFUSED_RESPONSE, happy_by_hello, HAPPY_RESPONSE, miffed_by_hello, MIFFED_RESPONSE, FRIENDLY_SPACE_HELLO_1, FRIENDLY_SPACE_HELLO_2, FRIENDLY_SPACE_HELLO_3, FRIENDLY_SPACE_HELLO_4, FRDLY_HOMEWORLD_HELLO_1, FRDLY_HOMEWORLD_HELLO_2, FRDLY_HOMEWORLD_HELLO_3, FRDLY_HOMEWORLD_HELLO_4, whats_up_1, whats_up_2, GENERAL_INFO_1, GENERAL_INFO_2, GENERAL_INFO_3, GENERAL_INFO_4, why_you_here, LEARN_THINGS, what_things, THESE_THINGS, why_do_it, DO_IT_BECAUSE, give_me_info_1, ARILOU_HINTS_1, give_me_info_2, ARILOU_HINTS_2, ARILOU_HINTS_3, ARILOU_HINTS_4, bye_friendly_space, GOODBYE_FRIENDLY_SPACE, GOT_PART_YET_1, GOT_PART_YET_2, INIT_ANGRY_HWLD_HELLO, invaders_from_mars, HAD_OUR_REASONS, bug_eyed_fruitcakes, WE_NEVER_FRIENDS, ok_lets_be_friends, NO_ALLY_BUT_MUCH_GIVE, why_should_i_trust, TRUST_BECAUSE, what_about_interference, INTERFERENCE_NECESSARY, i_just_like_to_leave, SORRY_NO_LEAVE, what_about_war, ABOUT_WAR, what_about_urquan, ABOUT_URQUAN, best_if_i_killed_you, WICKED_HUMAN, what_did_on_earth, DID_THIS, why_did_this, IDF_PARASITES, tell_more, NOT_NOW, umgah_acting_weird, learned_about_umgah, WELL_GO_CHECK, NO_NEWS_YET, UMGAH_UNDER_COMPULSION, what_do_now, GO_FIND_OUT, tell_arilou_about_tpet, BAD_NEWS_ABOUT_TPET, what_do_about_tpet, DANGEROUS_BUT_USEFUL, what_give_me, ABOUT_PORTAL, what_about_tpet, ABOUT_TPET, about_portal_again, PORTAL_AGAIN, got_it, CLEVER_HUMAN, GIVE_PORTAL, bye_friendly_homeworld, GOODBYE_FRDLY_HOMEWORLD, HOSTILE_GOODBYE_1, HOSTILE_GOODBYE_2, HOSTILE_GOODBYE_3, HOSTILE_GOODBYE_4, ANGRY_SPACE_HELLO_1, ANGRY_SPACE_HELLO_2, lets_fight, NO_FIGHT, im_sorry, APOLOGIZE_AT_HOMEWORLD, bye_angry_space, GOODBYE_ANGRY_SPACE, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/arilou/igfxres.h0000600000175000017500000000011410543202025017642 0ustar joeyjoey#define ARILOU_PMAP_ANIM 0x00200002L #define ARILOU_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/arilou/istrtab.h0000600000175000017500000000006210543202025017645 0ustar joeyjoey#define ARILOU_CONVERSATION_PHRASES 0x00200004L uqm-0.6.2/sc2/src/sc2code/comm/arilou/imusicre.h0000600000175000017500000000004310543202025020014 0ustar joeyjoey#define ARILOU_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/arilou/arilou.res0000600000175000017500000000036210543202025020035 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/arilou PACKAGE ARILOU_PACKAGE arilou.con GFXRES ARILOU_PMAP_ANIM arilou.ani FONTRES ARILOU_FONT arilou.fon MUSICRES ARILOU_MUSIC arilou.mod STRTAB ARILOU_CONVERSATION_PHRASES arilou.txt uqm-0.6.2/sc2/src/sc2code/comm/arilou/Makeinfo0000600000175000017500000000002710543202025017501 0ustar joeyjoeyuqm_CFILES="arilouc.c" uqm-0.6.2/sc2/src/sc2code/comm/arilou/respkg.h0000600000175000017500000000003710543202025017472 0ustar joeyjoeyenum { ARILOU_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/arilou/arilouc.c0000600000175000017500000004561710543202025017645 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/arilou/resinst.h" #include "comm/arilou/strings.h" #include "gameev.h" static LOCDATA arilou_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)ARILOU_PMAP_ANIM, /* AlienFrame */ (FONT)ARILOU_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)ARILOU_COLOR_MAP, /* AlienColorMap */ ARILOU_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ ARILOU_CONVERSATION_PHRASES, /* PlayerPhrases */ 20, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 4, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 1) | (1L << 16) }, { 13, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 0) | (1L << 16) }, { 22, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1L << 16) }, { 31, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 4) }, { 40, /* StartIndex */ 10, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 3) }, { 50, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 7) }, { 59, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 67, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 5) }, { 76, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 9) }, { 85, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 8) }, { 94, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 103, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 13) }, { 112, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 121, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 11) }, { 129, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1L << 15) }, { 138, /* StartIndex */ 8, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 14) }, { 146, /* StartIndex */ 9, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 0) | (1 << 1) | (1 << 2) }, { 155, /* StartIndex */ 2, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 157, /* StartIndex */ 2, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 159, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM | WAIT_TALKING,/* AnimFlags */ ONE_SECOND / 12, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 3, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (PLAYER_SAID (R, bye_angry_space)) NPCPhrase (GOODBYE_ANGRY_SPACE); else if (PLAYER_SAID (R, bye_friendly_space)) NPCPhrase (GOODBYE_FRIENDLY_SPACE); else if (PLAYER_SAID (R, bye_friendly_homeworld)) NPCPhrase (GOODBYE_FRDLY_HOMEWORLD); else if (PLAYER_SAID (R, lets_fight)) NPCPhrase (NO_FIGHT); else if (PLAYER_SAID (R, bug_eyed_fruitcakes)) { NPCPhrase (WE_NEVER_FRIENDS); SET_GAME_STATE (ARILOU_MANNER, 2); } else if (PLAYER_SAID (R, best_if_i_killed_you)) { NPCPhrase (WICKED_HUMAN); SET_GAME_STATE (ARILOU_MANNER, 2); } } static void ArilouHome (RESPONSE_REF R) { BYTE i, LastStack; RESPONSE_REF pStr[4]; LastStack = 0; pStr[0] = pStr[1] = pStr[2] = pStr[3] = 0; if (PLAYER_SAID (R, confused_by_hello)) NPCPhrase (CONFUSED_RESPONSE); else if (PLAYER_SAID (R, happy_by_hello)) NPCPhrase (HAPPY_RESPONSE); else if (PLAYER_SAID (R, miffed_by_hello)) NPCPhrase (MIFFED_RESPONSE); else if (PLAYER_SAID (R, ok_lets_be_friends)) NPCPhrase (NO_ALLY_BUT_MUCH_GIVE); else if (PLAYER_SAID (R, what_about_war)) { NPCPhrase (ABOUT_WAR); SET_GAME_STATE (ARILOU_STACK_1, 1); } else if (PLAYER_SAID (R, what_about_urquan)) { NPCPhrase (ABOUT_URQUAN); SET_GAME_STATE (ARILOU_STACK_1, 2); } else if (PLAYER_SAID (R, tell_arilou_about_tpet)) { NPCPhrase (BAD_NEWS_ABOUT_TPET); LastStack = 1; SET_GAME_STATE (ARILOU_STACK_2, 1); } else if (PLAYER_SAID (R, what_do_about_tpet)) { NPCPhrase (DANGEROUS_BUT_USEFUL); LastStack = 1; SET_GAME_STATE (ARILOU_STACK_2, 2); } else if (PLAYER_SAID (R, learned_about_umgah)) { if (GET_GAME_STATE (ARILOU_CHECKED_UMGAH) != 2) NPCPhrase (NO_NEWS_YET); else { NPCPhrase (UMGAH_UNDER_COMPULSION); LastStack = 1; } DISABLE_PHRASE (learned_about_umgah); } else if (PLAYER_SAID (R, umgah_acting_weird)) { NPCPhrase (WELL_GO_CHECK); SET_GAME_STATE (ARILOU_CHECKED_UMGAH, 1); AddEvent (RELATIVE_EVENT, 0, 10, 0, ARILOU_UMGAH_CHECK); DISABLE_PHRASE (umgah_acting_weird); } else if (PLAYER_SAID (R, what_do_now)) { NPCPhrase (GO_FIND_OUT); SET_GAME_STATE (ARILOU_CHECKED_UMGAH, 3); } else if (PLAYER_SAID (R, what_did_on_earth)) { NPCPhrase (DID_THIS); LastStack = 2; SET_GAME_STATE (ARILOU_STACK_3, 1); } else if (PLAYER_SAID (R, why_did_this)) { NPCPhrase (IDF_PARASITES); LastStack = 2; SET_GAME_STATE (ARILOU_STACK_3, 2); } else if (PLAYER_SAID (R, tell_more)) { NPCPhrase (NOT_NOW); LastStack = 2; SET_GAME_STATE (ARILOU_STACK_3, 3); } else if (PLAYER_SAID (R, what_give_me)) { NPCPhrase (ABOUT_PORTAL); LastStack = 3; SET_GAME_STATE (KNOW_ARILOU_WANT_WRECK, 1); R = about_portal_again; DISABLE_PHRASE (what_give_me); } else if (PLAYER_SAID (R, what_about_tpet)) { NPCPhrase (ABOUT_TPET); SET_GAME_STATE (ARILOU_STACK_4, 1); } else if (PLAYER_SAID (R, about_portal_again)) { NPCPhrase (PORTAL_AGAIN); DISABLE_PHRASE (about_portal_again); } else if (PLAYER_SAID (R, got_it)) { if (GET_GAME_STATE (ARILOU_HOME_VISITS) == 1) NPCPhrase (CLEVER_HUMAN); NPCPhrase (GIVE_PORTAL); SET_GAME_STATE (PORTAL_KEY_ON_SHIP, 0); SET_GAME_STATE (PORTAL_SPAWNER, 1); SET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP, 1); } #ifdef NEVER else if (PLAYER_SAID (R, got_tpet)) { NPCPhrase (OK_GOT_TPET); SET_GAME_STATE (ARILOU_STACK_2, 1); } #endif /* NEVER */ switch (GET_GAME_STATE (ARILOU_STACK_1)) { case 0: pStr[0] = what_about_war; break; case 1: pStr[0] = what_about_urquan; break; } if (GET_GAME_STATE (TALKING_PET)) { #ifdef NEVER if (GET_GAME_STATE (ARILOU_STACK_2) == 0) pStr[1] = got_tpet; #endif /* NEVER */ } else { if (GET_GAME_STATE (TALKING_PET_VISITS)) { switch (GET_GAME_STATE (ARILOU_STACK_2)) { case 0: pStr[1] = tell_arilou_about_tpet; break; case 1: pStr[1] = what_do_about_tpet; break; } } else if (GET_GAME_STATE (KNOW_UMGAH_ZOMBIES)) { if (!GET_GAME_STATE (ARILOU_CHECKED_UMGAH)) pStr[1] = umgah_acting_weird; else if (PHRASE_ENABLED (learned_about_umgah) && PHRASE_ENABLED (umgah_acting_weird)) pStr[1] = learned_about_umgah; else if (GET_GAME_STATE (ARILOU_CHECKED_UMGAH) == 2) pStr[1] = what_do_now; } } switch (GET_GAME_STATE (ARILOU_STACK_3)) { case 0: pStr[2] = what_did_on_earth; break; case 1: pStr[2] = why_did_this; break; case 2: pStr[2] = tell_more; break; } if (!GET_GAME_STATE (KNOW_ARILOU_WANT_WRECK)) pStr[3] = what_give_me; else if (!GET_GAME_STATE (ARILOU_STACK_4)) pStr[3] = what_about_tpet; if (pStr[LastStack]) Response (pStr[LastStack], ArilouHome); for (i = 0; i < 4; ++i) { if (i != LastStack && pStr[i]) Response (pStr[i], ArilouHome); } if (GET_GAME_STATE (KNOW_ARILOU_WANT_WRECK)) { if (GET_GAME_STATE (PORTAL_KEY_ON_SHIP)) Response (got_it, ArilouHome); else if (PHRASE_ENABLED (about_portal_again) && !GET_GAME_STATE (PORTAL_SPAWNER)) Response (about_portal_again, ArilouHome); } if (GET_GAME_STATE (ARILOU_MANNER) != 3) Response (best_if_i_killed_you, ExitConversation); Response (bye_friendly_homeworld, ExitConversation); } static void AngryHomeArilou (RESPONSE_REF R) { if (PLAYER_SAID (R, invaders_from_mars)) { NPCPhrase (HAD_OUR_REASONS); DISABLE_PHRASE (invaders_from_mars); } else if (PLAYER_SAID (R, why_should_i_trust)) { NPCPhrase (TRUST_BECAUSE); DISABLE_PHRASE (why_should_i_trust); } else if (PLAYER_SAID (R, what_about_interference)) { NPCPhrase (INTERFERENCE_NECESSARY); DISABLE_PHRASE (what_about_interference); } else if (PLAYER_SAID (R, i_just_like_to_leave)) { NPCPhrase (SORRY_NO_LEAVE); DISABLE_PHRASE (i_just_like_to_leave); } if (PHRASE_ENABLED (invaders_from_mars)) Response (invaders_from_mars, AngryHomeArilou); else { Response (bug_eyed_fruitcakes, ExitConversation); } if (PHRASE_ENABLED (why_should_i_trust)) Response (why_should_i_trust, AngryHomeArilou); else if (PHRASE_ENABLED (what_about_interference)) Response (what_about_interference, AngryHomeArilou); Response (ok_lets_be_friends, ArilouHome); Response (i_just_like_to_leave, AngryHomeArilou); } static void AngrySpaceArilou (RESPONSE_REF R) { if (PLAYER_SAID (R, im_sorry)) { NPCPhrase (APOLOGIZE_AT_HOMEWORLD); DISABLE_PHRASE (im_sorry); } Response (lets_fight, ExitConversation); if (PHRASE_ENABLED (im_sorry)) { Response (im_sorry, AngrySpaceArilou); } Response (bye_angry_space, ExitConversation); } static void FriendlySpaceArilou (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, confused_by_hello)) NPCPhrase (CONFUSED_RESPONSE); else if (PLAYER_SAID (R, happy_by_hello)) NPCPhrase (HAPPY_RESPONSE); else if (PLAYER_SAID (R, miffed_by_hello)) NPCPhrase (MIFFED_RESPONSE); else if (PLAYER_SAID (R, whats_up_1) || PLAYER_SAID (R, whats_up_2)) { NumVisits = GET_GAME_STATE (ARILOU_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_1); break; case 1: NPCPhrase (GENERAL_INFO_2); break; case 2: NPCPhrase (GENERAL_INFO_3); break; case 3: NPCPhrase (GENERAL_INFO_4); --NumVisits; break; } SET_GAME_STATE (ARILOU_INFO, NumVisits); DISABLE_PHRASE (whats_up_2); } else if (PLAYER_SAID (R, why_you_here)) { NPCPhrase (LEARN_THINGS); SET_GAME_STATE (ARILOU_STACK_5, 1); } else if (PLAYER_SAID (R, what_things)) { NPCPhrase (THESE_THINGS); SET_GAME_STATE (ARILOU_STACK_5, 2); } else if (PLAYER_SAID (R, why_do_it)) { NPCPhrase (DO_IT_BECAUSE); SET_GAME_STATE (ARILOU_STACK_5, 3); } else if (PLAYER_SAID (R, give_me_info_1) || PLAYER_SAID (R, give_me_info_2)) { NumVisits = GET_GAME_STATE (ARILOU_HINTS); switch (NumVisits++) { case 0: NPCPhrase (ARILOU_HINTS_1); break; case 1: NPCPhrase (ARILOU_HINTS_2); if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) < 2) { SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 2); } break; case 2: NPCPhrase (ARILOU_HINTS_3); SET_GAME_STATE (KNOW_URQUAN_STORY, 1); SET_GAME_STATE (KNOW_KOHR_AH_STORY, 1); break; case 3: NPCPhrase (ARILOU_HINTS_4); --NumVisits; break; } SET_GAME_STATE (ARILOU_HINTS, NumVisits); DISABLE_PHRASE (give_me_info_2); } switch (GET_GAME_STATE (ARILOU_STACK_5)) { case 0: Response (why_you_here, FriendlySpaceArilou); break; case 1: Response (what_things, FriendlySpaceArilou); break; case 2: Response (why_do_it, FriendlySpaceArilou); break; } if (PHRASE_ENABLED (whats_up_2)) { if (GET_GAME_STATE (ARILOU_INFO) == 0) Response (whats_up_1, FriendlySpaceArilou); else Response (whats_up_2, FriendlySpaceArilou); } if (PHRASE_ENABLED (give_me_info_2)) { if (GET_GAME_STATE (ARILOU_HINTS) == 0) Response (give_me_info_1, FriendlySpaceArilou); else Response (give_me_info_2, FriendlySpaceArilou); } Response (bye_friendly_space, ExitConversation); } static void Intro (void) { BYTE NumVisits, Manner; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } else if (!GET_GAME_STATE (MET_ARILOU)) { RESPONSE_FUNC RespFunc; if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { NPCPhrase (INIT_HELLO); RespFunc = (RESPONSE_FUNC)FriendlySpaceArilou; } else { NPCPhrase (FRDLY_HOMEWORLD_HELLO_1); RespFunc = (RESPONSE_FUNC)ArilouHome; SET_GAME_STATE (ARILOU_HOME_VISITS, 1); } Response (confused_by_hello, RespFunc); Response (happy_by_hello, RespFunc); Response (miffed_by_hello, RespFunc); SET_GAME_STATE (MET_ARILOU, 1); return; } Manner = GET_GAME_STATE (ARILOU_MANNER); if (Manner == 2) { NumVisits = GET_GAME_STATE (ARILOU_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_GOODBYE_1); break; case 1: NPCPhrase (HOSTILE_GOODBYE_2); break; case 2: NPCPhrase (HOSTILE_GOODBYE_3); break; case 3: NPCPhrase (HOSTILE_GOODBYE_4); --NumVisits; break; } SET_GAME_STATE (ARILOU_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (Manner == 1) { if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1) { NPCPhrase (INIT_ANGRY_HWLD_HELLO); SET_GAME_STATE (ARILOU_HOME_VISITS, 1); AngryHomeArilou ((RESPONSE_REF)0); } else { NumVisits = GET_GAME_STATE (ARILOU_VISITS); switch (NumVisits++) { case 0: NPCPhrase (ANGRY_SPACE_HELLO_1); break; case 1: NPCPhrase (ANGRY_SPACE_HELLO_2); --NumVisits; break; } SET_GAME_STATE (ARILOU_VISITS, NumVisits); AngrySpaceArilou ((RESPONSE_REF)0); } } else { if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { NumVisits = GET_GAME_STATE (ARILOU_VISITS); switch (NumVisits++) { case 0: NPCPhrase (FRIENDLY_SPACE_HELLO_1); break; case 1: NPCPhrase (FRIENDLY_SPACE_HELLO_2); break; case 2: NPCPhrase (FRIENDLY_SPACE_HELLO_3); break; case 3: NPCPhrase (FRIENDLY_SPACE_HELLO_4); --NumVisits; break; } SET_GAME_STATE (ARILOU_VISITS, NumVisits); FriendlySpaceArilou ((RESPONSE_REF)0); } else { if (!GET_GAME_STATE (PORTAL_SPAWNER) && GET_GAME_STATE (KNOW_ARILOU_WANT_WRECK)) { NumVisits = GET_GAME_STATE (NO_PORTAL_VISITS); switch (NumVisits++) { case 0: NPCPhrase (GOT_PART_YET_1); break; case 1: NPCPhrase (GOT_PART_YET_1); --NumVisits; break; } SET_GAME_STATE (NO_PORTAL_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (ARILOU_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (FRDLY_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (FRDLY_HOMEWORLD_HELLO_2); break; case 2: NPCPhrase (FRDLY_HOMEWORLD_HELLO_3); break; case 3: NPCPhrase (FRDLY_HOMEWORLD_HELLO_4); --NumVisits; break; } SET_GAME_STATE (ARILOU_HOME_VISITS, NumVisits); } ArilouHome ((RESPONSE_REF)0); } } } static COUNT uninit_arilou (void) { return (0); } static void post_arilou_enc (void) { BYTE Manner; if (GET_GAME_STATE (BATTLE_SEGUE) == 1 && (Manner = GET_GAME_STATE (ARILOU_MANNER)) != 2) { SET_GAME_STATE (ARILOU_MANNER, 1); if (Manner != 1) { SET_GAME_STATE (ARILOU_VISITS, 0); SET_GAME_STATE (ARILOU_HOME_VISITS, 0); } } if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1 && GET_GAME_STATE (ARILOU_HOME_VISITS) <= 1) { SET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES, 1); SET_GAME_STATE (UMGAH_VISITS, 0); SET_GAME_STATE (UMGAH_HOME_VISITS, 0); if (GET_GAME_STATE (ARILOU_MANNER) < 2) { SET_GAME_STATE (ARILOU_MANNER, 3); } } } LOCDATAPTR init_arilou_comm (void) { LOCDATAPTR retval; arilou_desc.init_encounter_func = Intro; arilou_desc.post_encounter_func = post_arilou_enc; arilou_desc.uninit_encounter_func = uninit_arilou; arilou_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); arilou_desc.AlienTextBaseline.y = 0; arilou_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1 || GET_GAME_STATE (ARILOU_MANNER) == 3 || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &arilou_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/arilou/resinst.h0000600000175000017500000000012610543202025017665 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/mycon/0000755000175000017500000000000010552600275015701 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/mycon/ifontres.h0000600000175000017500000000004110543202023017653 0ustar joeyjoey#define MYCON_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/mycon/restypes.h0000600000175000017500000000024110543202023017702 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/mycon/strings.h0000600000175000017500000000466110543202023017527 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, TELL_US_ABOUT_WORLD, BYE_AND_DIE_HOMEWORLD, RAMBLE_1, RAMBLE_2, RAMBLE_3, RAMBLE_4, RAMBLE_5, RAMBLE_6, RAMBLE_7, RAMBLE_8, RAMBLE_9, RAMBLE_10, RAMBLE_11, RAMBLE_12, RAMBLE_13, RAMBLE_14, RAMBLE_15, RAMBLE_16, RAMBLE_17, RAMBLE_18, RAMBLE_19, RAMBLE_20, RAMBLE_21, RAMBLE_22, RAMBLE_23, RAMBLE_24, RAMBLE_25, RAMBLE_26, RAMBLE_27, RAMBLE_28, RAMBLE_29, RAMBLE_30, RAMBLE_31, RAMBLE_32, question_1, question_2, question_3, question_4, question_5, question_6, question_7, question_8, question_9, question_10, question_11, question_12, question_13, question_14, question_15, question_16, bye_space, BYE_AND_DIE_SPACE, gonna_die, insult_1, insult_2, insult_3, insult_4, insult_5, insult_6, insult_7, insult_8, come_in_peace, HELLO_HOMEWORLD_1, HELLO_HOMEWORLD_2, HELLO_HOMEWORLD_3, HELLO_HOMEWORLD_4, HELLO_HOMEWORLD_5, HELLO_HOMEWORLD_6, HELLO_HOMEWORLD_7, HELLO_HOMEWORLD_8, HELLO_SPACE_1, HELLO_SPACE_2, HELLO_SPACE_3, HELLO_SPACE_4, HELLO_SPACE_5, HELLO_SPACE_6, HELLO_SPACE_7, HELLO_SPACE_8, lets_be_friends, came_to_homeworld, submit_to_us, bye_sun_device, GOODBYE_SUN_DEVICE, RESPONSE_1, RESPONSE_2, RESPONSE_3, clue_1, clue_2, clue_3, what_about_shattered, ABOUT_SHATTERED, HELLO_SUN_DEVICE_WORLD_1, HELLO_SUN_DEVICE_WORLD_2, whats_up_sun_device, GENERAL_INFO_SUN_DEVICE, like_to_land, NEVER_LET_LAND, bye_homeworld, i_have_a_cunning_plan, DIE_LIAR, how_goes_implanting, UNFORSEEN_DELAYS, DIE_THIEF, DIE_THIEF_AGAIN, GOODBYE_AND_DIE, AMBUSH_TAIL, RAMBLE_TAIL, WE_GO_TO_IMPLANT, WONT_FALL_FOR_TRICK, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/mycon/igfxres.h0000600000175000017500000000004610543202023017476 0ustar joeyjoey#define MYCON_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/mycon/istrtab.h0000600000175000017500000000012410543202023017474 0ustar joeyjoey#define MYCON_CONVERSATION_PHRASES 0x00200004L #define MYCON_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/mycon/imusicre.h0000600000175000017500000000004210543202023017643 0ustar joeyjoey#define MYCON_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/mycon/myconc.c0000600000175000017500000003225010543202023017314 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/mycon/resinst.h" #include "comm/mycon/strings.h" #include "gameev.h" #include "libs/mathlib.h" static LOCDATA mycon_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)MYCON_PMAP_ANIM, /* AlienFrame */ (FONT)MYCON_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)MYCON_COLOR_MAP, /* AlienColorMap */ MYCON_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ MYCON_CONVERSATION_PHRASES, /* PlayerPhrases */ 5, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 12, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 3 / 40, 0, /* FrameRate */ ONE_SECOND * 3 / 40, 0, /* RestartRate */ (1 << 1), /* BlockMask */ }, { 18, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 3 / 40, 0, /* FrameRate */ ONE_SECOND * 3 / 40, 0, /* RestartRate */ (1 << 0), /* BlockMask */ }, { 22, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 3 / 40, 0, /* FrameRate */ ONE_SECOND * 3 / 40, 0, /* RestartRate */ 0, /* BlockMask */ }, { 28, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 3 / 40, 0, /* FrameRate */ ONE_SECOND * 3 / 40, 0, /* RestartRate */ 0, /* BlockMask */ }, { 33, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND * 3 / 40, 0, /* FrameRate */ ONE_SECOND * 3 / 40, 0, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 11, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static BYTE MadeChoice; static void DoRamble (RESPONSE_REF R) { BYTE Counter; Counter = GET_GAME_STATE (MYCON_RAMBLE); switch (Counter++) { case 0: NPCPhrase (RAMBLE_1); break; case 1: NPCPhrase (RAMBLE_2); break; case 2: NPCPhrase (RAMBLE_3); break; case 3: NPCPhrase (RAMBLE_4); break; case 4: NPCPhrase (RAMBLE_5); break; case 5: NPCPhrase (RAMBLE_6); break; case 6: NPCPhrase (RAMBLE_7); break; case 7: NPCPhrase (RAMBLE_8); break; case 8: NPCPhrase (RAMBLE_9); break; case 9: NPCPhrase (RAMBLE_10); break; case 10: NPCPhrase (RAMBLE_11); break; case 11: NPCPhrase (RAMBLE_12); break; case 12: NPCPhrase (RAMBLE_13); break; case 13: NPCPhrase (RAMBLE_14); break; case 14: NPCPhrase (RAMBLE_15); break; case 15: NPCPhrase (RAMBLE_16); break; case 16: NPCPhrase (RAMBLE_17); break; case 17: NPCPhrase (RAMBLE_18); break; case 18: NPCPhrase (RAMBLE_19); break; case 19: NPCPhrase (RAMBLE_20); break; case 20: NPCPhrase (RAMBLE_21); break; case 21: NPCPhrase (RAMBLE_22); break; case 22: NPCPhrase (RAMBLE_23); break; case 23: NPCPhrase (RAMBLE_24); break; case 24: NPCPhrase (RAMBLE_25); if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) < 2) { SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 2); } break; case 25: NPCPhrase (RAMBLE_26); break; case 26: NPCPhrase (RAMBLE_27); break; case 27: NPCPhrase (RAMBLE_28); break; case 28: NPCPhrase (RAMBLE_29); break; case 29: NPCPhrase (RAMBLE_30); break; case 30: NPCPhrase (RAMBLE_31); break; case 31: NPCPhrase (RAMBLE_32); Counter = 0; break; } SET_GAME_STATE (MYCON_RAMBLE, Counter); if (!(GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) { if (!PLAYER_SAID (R, come_in_peace) && !PLAYER_SAID (R, gonna_die)) { Counter = (GET_GAME_STATE (MYCON_INSULTS) + 1) & 7; SET_GAME_STATE (MYCON_INSULTS, Counter); MadeChoice = 1; } } else if (!PLAYER_SAID (R, lets_be_friends) && !PLAYER_SAID (R, came_to_homeworld) && !PLAYER_SAID (R, submit_to_us)) { Counter = (GET_GAME_STATE (MYCON_INFO) + 1) & 15; SET_GAME_STATE (MYCON_INFO, Counter); MadeChoice = 1; } } static void CombatIsInevitable (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, bye_space)) NPCPhrase (BYE_AND_DIE_SPACE); else if (PLAYER_SAID (R, bye_homeworld)) NPCPhrase (BYE_AND_DIE_HOMEWORLD); else if (PLAYER_SAID (R, like_to_land)) NPCPhrase (NEVER_LET_LAND); else if (PLAYER_SAID (R, bye_sun_device)) { NPCPhrase (GOODBYE_SUN_DEVICE); SET_GAME_STATE (BATTLE_SEGUE, 0); } else { DoRamble (R); if (!(GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) NPCPhrase (BYE_AND_DIE_SPACE); else NPCPhrase (BYE_AND_DIE_HOMEWORLD); } MadeChoice = 0; } static void SunDevice (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_up_sun_device)) { NPCPhrase (GENERAL_INFO_SUN_DEVICE); DISABLE_PHRASE (whats_up_sun_device); } else if (PLAYER_SAID (R, how_goes_implanting)) { NPCPhrase (UNFORSEEN_DELAYS); DISABLE_PHRASE (how_goes_implanting); } else if (PLAYER_SAID (R, i_have_a_cunning_plan)) { NPCPhrase (WONT_FALL_FOR_TRICK); SET_GAME_STATE (NO_TRICK_AT_SUN, 1); } if (PHRASE_ENABLED (whats_up_sun_device)) Response (whats_up_sun_device, SunDevice); if (GET_GAME_STATE (MYCON_FELL_FOR_AMBUSH)) { if (PHRASE_ENABLED (how_goes_implanting) && GET_GAME_STATE (MYCON_FELL_FOR_AMBUSH)) Response (how_goes_implanting, SunDevice); Response (like_to_land, CombatIsInevitable); } else if (GET_GAME_STATE (MYCON_AMBUSH) && !GET_GAME_STATE (NO_TRICK_AT_SUN)) Response (i_have_a_cunning_plan, SunDevice); Response (bye_sun_device, CombatIsInevitable); } static void TrickMycon (RESPONSE_REF R) { if (PLAYER_SAID (R, i_have_a_cunning_plan)) { NPCPhrase (TELL_US_ABOUT_WORLD); DISABLE_PHRASE (i_have_a_cunning_plan); } else if (PLAYER_SAID (R, clue_1)) { NPCPhrase (RESPONSE_1); DISABLE_PHRASE (clue_1); } else if (PLAYER_SAID (R, clue_2)) { NPCPhrase (RESPONSE_2); DISABLE_PHRASE (clue_2); } else if (PLAYER_SAID (R, clue_3)) { NPCPhrase (RESPONSE_3); DISABLE_PHRASE (clue_3); } if (PHRASE_ENABLED (clue_1) == 0 && PHRASE_ENABLED (clue_2) == 0 && PHRASE_ENABLED (clue_3) == 0) { NPCPhrase (WE_GO_TO_IMPLANT); SET_GAME_STATE (BATTLE_SEGUE, 0); SET_GAME_STATE (MYCON_FELL_FOR_AMBUSH, 1); AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_MYCON_MISSION); } else NPCPhrase (AMBUSH_TAIL); if (PHRASE_ENABLED (clue_1)) Response (clue_1, TrickMycon); if (PHRASE_ENABLED (clue_2)) Response (clue_2, TrickMycon); if (PHRASE_ENABLED (clue_3)) Response (clue_3, TrickMycon); } static void NormalMycon (RESPONSE_REF R) { RESPONSE_FUNC RespFunc; if (PLAYER_SAID (R, what_about_shattered)) { NPCPhrase (ABOUT_SHATTERED); SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 2); } else if (R) { DoRamble (R); NPCPhrase (RAMBLE_TAIL); DISABLE_PHRASE (RESPONSE_TO_REF (R)); } if ((BYTE)TFB_Random () < 256 * 30 / 100) RespFunc = (RESPONSE_FUNC)CombatIsInevitable; else RespFunc = (RESPONSE_FUNC)NormalMycon; if (!(GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) { if (PHRASE_ENABLED (come_in_peace)) Response (come_in_peace, RespFunc); if (PHRASE_ENABLED (gonna_die)) Response (gonna_die, RespFunc); if (!MadeChoice) switch (GET_GAME_STATE (MYCON_INSULTS)) { case 0: Response (insult_1, RespFunc); break; case 1: Response (insult_2, RespFunc); break; case 2: Response (insult_3, RespFunc); break; case 3: Response (insult_4, RespFunc); break; case 4: Response (insult_5, RespFunc); break; case 5: Response (insult_6, RespFunc); break; case 6: Response (insult_7, RespFunc); break; case 7: Response (insult_8, RespFunc); break; } Response (bye_space, CombatIsInevitable); } else { if (!MadeChoice) switch (GET_GAME_STATE (MYCON_INFO)) { case 0: Response (question_1, RespFunc); break; case 1: Response (question_2, RespFunc); break; case 2: Response (question_3, RespFunc); break; case 3: Response (question_4, RespFunc); break; case 4: Response (question_5, RespFunc); break; case 5: Response (question_6, RespFunc); break; case 6: Response (question_7, RespFunc); break; case 7: Response (question_8, RespFunc); break; case 8: Response (question_9, RespFunc); break; case 9: Response (question_10, RespFunc); break; case 10: Response (question_11, RespFunc); break; case 11: Response (question_12, RespFunc); break; case 12: Response (question_13, RespFunc); break; case 13: Response (question_14, RespFunc); break; case 14: Response (question_15, RespFunc); break; case 15: Response (question_16, RespFunc); break; } if (PHRASE_ENABLED (lets_be_friends)) Response (lets_be_friends, RespFunc); if (PHRASE_ENABLED (came_to_homeworld)) Response (came_to_homeworld, RespFunc); if (PHRASE_ENABLED (submit_to_us)) Response (submit_to_us, RespFunc); if (!GET_GAME_STATE (MYCON_FELL_FOR_AMBUSH)) { if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) == 1) Response (what_about_shattered, NormalMycon); if (GET_GAME_STATE (MYCON_AMBUSH)) { Response (i_have_a_cunning_plan, TrickMycon); } } Response (bye_homeworld, CombatIsInevitable); } } static void Intro (void) { BYTE NumVisits; if (GET_GAME_STATE (SUN_DEVICE)) { NumVisits = GET_GAME_STATE (MYCON_VISITS); switch (NumVisits++) { case 0: NPCPhrase (DIE_THIEF); break; case 1: NPCPhrase (DIE_THIEF_AGAIN); --NumVisits; break; } SET_GAME_STATE (MYCON_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (GET_GAME_STATE (MYCON_KNOW_AMBUSH)) { NPCPhrase (DIE_LIAR); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { NumVisits = GET_GAME_STATE (MYCON_SUN_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_SUN_DEVICE_WORLD_1); break; case 1: NPCPhrase (HELLO_SUN_DEVICE_WORLD_2); --NumVisits; break; } SET_GAME_STATE (MYCON_SUN_VISITS, NumVisits); SunDevice ((RESPONSE_REF)0); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (MYCON_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_HOMEWORLD_1); break; case 1: NPCPhrase (HELLO_HOMEWORLD_2); break; case 2: NPCPhrase (HELLO_HOMEWORLD_3); break; case 3: NPCPhrase (HELLO_HOMEWORLD_4); break; case 4: NPCPhrase (HELLO_HOMEWORLD_5); break; case 5: NPCPhrase (HELLO_HOMEWORLD_6); break; case 6: NPCPhrase (HELLO_HOMEWORLD_7); break; case 7: NPCPhrase (HELLO_HOMEWORLD_8); --NumVisits; break; } SET_GAME_STATE (MYCON_HOME_VISITS, NumVisits); NormalMycon ((RESPONSE_REF)0); } else { NumVisits = GET_GAME_STATE (MYCON_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_SPACE_1); break; case 1: NPCPhrase (HELLO_SPACE_2); break; case 2: NPCPhrase (HELLO_SPACE_3); break; case 3: NPCPhrase (HELLO_SPACE_4); break; case 4: NPCPhrase (HELLO_SPACE_5); break; case 5: NPCPhrase (HELLO_SPACE_6); break; case 6: NPCPhrase (HELLO_SPACE_7); break; case 7: NPCPhrase (HELLO_SPACE_8); --NumVisits; break; } SET_GAME_STATE (MYCON_VISITS, NumVisits); NormalMycon ((RESPONSE_REF)0); } } static COUNT uninit_mycon (void) { return (0); } static void post_mycon_enc (void) { // nothing defined so far } LOCDATAPTR init_mycon_comm (void) { LOCDATAPTR retval; mycon_desc.init_encounter_func = Intro; mycon_desc.post_encounter_func = post_mycon_enc; mycon_desc.uninit_encounter_func = uninit_mycon; mycon_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); mycon_desc.AlienTextBaseline.y = 0; mycon_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; MadeChoice = 0; if (LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 1); } else { SET_GAME_STATE (BATTLE_SEGUE, 0); } retval = &mycon_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/mycon/mycon.res0000600000175000017500000000035010543202023017514 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/mycon PACKAGE MYCON_PACKAGE mycon.con GFXRES MYCON_PMAP_ANIM mycon.ani FONTRES MYCON_FONT mycon.fon MUSICRES MYCON_MUSIC mycon.mod STRTAB MYCON_CONVERSATION_PHRASES mycon.txt uqm-0.6.2/sc2/src/sc2code/comm/mycon/Makeinfo0000600000175000017500000000002610543202023017330 0ustar joeyjoeyuqm_CFILES="myconc.c" uqm-0.6.2/sc2/src/sc2code/comm/mycon/respkg.h0000600000175000017500000000003610543202023017321 0ustar joeyjoeyenum { MYCON_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/mycon/resinst.h0000600000175000017500000000012610543202023017515 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/druuge/0000755000175000017500000000000010552600275016047 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/druuge/ifontres.h0000600000175000017500000000004210543202024020023 0ustar joeyjoey#define DRUUGE_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/druuge/restypes.h0000600000175000017500000000024110543202024020051 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/druuge/strings.h0000600000175000017500000000541110543202024017670 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, AMBUSH_IS_FIRST_HELLO, INIT_BOMB_WORLD_HELLO, SUBSEQ_BOMB_WORLD_HELLO, whats_up_at_bomb_planet, GEN_INFO_AT_BOMB_PLANET, we_get_bomb, NOT_GET_BOMB, then_we_take_bomb, FIGHT_FOR_BOMB, GOODBYE_FROM_BOMB_PLANET, NOT_ENOUGH_ROOM, TRADE_FOR_SPHERE, no_way, OK_REGULAR_DEAL, way, OK_HERES_SPHERE, whats_the_sphere_again, SPHERE_IS, WE_SELL_FOR_CREW, i_will_never_trade_crew, YOUR_LOSS, isnt_this_slave_trading, NO_SLAVE_TRADE, what_do_with_crew, HAVE_FUN, im_ready_to_buy, THIS_FOR_SALE, HAVE_SPHERE, HAVE_ART_2, HAVE_ART_1, SHIPS_AND_FUEL, BOUGHT_SHIP, BOUGHT_FUEL, BOUGHT_ART_2, BOUGHT_ART_1, BOUGHT_SPHERE, repeat_what_to_sell, INIT_SPACE_HELLO, SUBSEQUENT_SPACE_HELLO, whats_up_in_space, GENERAL_INFO_IN_SPACE_1, GENERAL_INFO_IN_SPACE_2, GENERAL_INFO_IN_SPACE_3, GENERAL_INFO_IN_SPACE_4, GOODBYE_FROM_SPACE, HSTL_TRADE_WORLD_HELLO_1, HSTL_TRADE_WORLD_HELLO_2, HOSTILE_SPACE_HELLO_1, HOSTILE_SPACE_HELLO_2, INITIAL_TRADE_WORLD_HELLO, SSQ_TRADE_WORLD_HELLO_1, SSQ_TRADE_WORLD_HELLO_2, SSQ_TRADE_WORLD_HELLO_3, SSQ_TRADE_WORLD_HELLO_4, whats_up_at_trade_world, GEN_INFO_AT_TRADE_WORLD_1, GEN_INFO_AT_TRADE_WORLD_2, GEN_INFO_AT_TRADE_WORLD_3, GEN_INFO_AT_TRADE_WORLD_4, SCAN_MAIDENS, SCAN_FRAGMENTS, SCAN_DRUUGE_CASTER, SCAN_ARILOU_SPAWNER, ENOUGH_FRAGMENTS, READY_TO_BUY, READY_TO_SELL, BYE_FROM_TRADE_WORLD_1, BYE_FROM_TRADE_WORLD_2, NOT_ENOUGH_CREW, EXCHANGE_MADE, OK_DONE_BUYING, OK_DONE_SELLING, bye, want_to_sell, want_to_buy, buy_druuge_ship, buy_fuel, buy_art_1, buy_art_2, buy_rosy_sphere, done_buying, done_selling, sell_maidens, sell_caster, sell_fragments, sell_spawner, BOUGHT_MAIDENS, BOUGHT_FRAGMENTS, BOUGHT_CASTER, YOU_GET, YOU_ALSO_GET, BOUGHT_SPAWNER, SALVAGE_YOUR_SHIP_1, SALVAGE_YOUR_SHIP_2, DEAL_FOR_STATED_SHIPS, DEAL_FOR_LESS_SHIPS, DEAL_FOR_NO_SHIPS, FUEL0, FUEL1, HIDEOUS_DEAL, BAD_DEAL, FAIR_DEAL, GOOD_DEAL, FINE_DEAL, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/druuge/igfxres.h0000600000175000017500000000004710543202024017646 0ustar joeyjoey#define DRUUGE_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/druuge/istrtab.h0000600000175000017500000000012610543202024017645 0ustar joeyjoey#define DRUUGE_CONVERSATION_PHRASES 0x00200004L #define DRUUGE_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/druuge/imusicre.h0000600000175000017500000000004310543202024020013 0ustar joeyjoey#define DRUUGE_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/druuge/druugec.c0000600000175000017500000005107010543202024017632 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/druuge/resinst.h" #include "comm/druuge/strings.h" #include "build.h" #include "setup.h" static LOCDATA druuge_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)DRUUGE_PMAP_ANIM, /* AlienFrame */ (FONT)DRUUGE_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_MIDDLE, /* AlienTextValign */ (COLORMAP)DRUUGE_COLOR_MAP, /* AlienColorMap */ DRUUGE_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ DRUUGE_CONVERSATION_PHRASES, /* PlayerPhrases */ 11, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 5, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 3 / 40, 0, /* FrameRate */ ONE_SECOND * 3 / 40, 0, /* RestartRate */ 0, /* BlockMask */ }, { 9, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 3 / 40, 0, /* FrameRate */ ONE_SECOND * 3 / 40, 0, /* RestartRate */ 0, /* BlockMask */ }, { 13, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 3 / 40, 0, /* FrameRate */ ONE_SECOND * 3 / 40, 0, /* RestartRate */ 0, /* BlockMask */ }, { 19, /* StartIndex */ 3, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 22, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 12, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 25, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 12, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 28, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 12, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 31, /* StartIndex */ 2, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 12, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 33, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 12, 0, /* FrameRate */ ONE_SECOND * 7, ONE_SECOND * 3,/* RestartRate */ 0, /* BlockMask */ }, { 40, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 3 / 10, 0, /* FrameRate */ ONE_SECOND * 3 / 10, 0, /* RestartRate */ 0, /* BlockMask */ }, { 44, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 5, 0, /* FrameRate */ ONE_SECOND / 5, 0, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 4, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND / 12, ONE_SECOND / 12, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static COUNT SlaveryCount = 0; static void ExitConversation (RESPONSE_REF R) { if (PLAYER_SAID (R, bye)) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { if (SlaveryCount) { UWORD PreviousSlaves; PreviousSlaves = MAKE_WORD ( GET_GAME_STATE (CREW_SOLD_TO_DRUUGE0), GET_GAME_STATE (CREW_SOLD_TO_DRUUGE1) ); SlaveryCount += PreviousSlaves; if (SlaveryCount > 250 && PreviousSlaves <= 250) { if (PreviousSlaves > 100) GLOBAL (CrewCost) += (22 - 7); else GLOBAL (CrewCost) += 22; } else if (SlaveryCount > 100 && PreviousSlaves <= 100) GLOBAL (CrewCost) += 7; SET_GAME_STATE (CREW_SOLD_TO_DRUUGE0, LOBYTE (SlaveryCount)); SET_GAME_STATE (CREW_SOLD_TO_DRUUGE1, HIBYTE (SlaveryCount)); } switch (GET_GAME_STATE (DRUUGE_HOME_VISITS)) { case 1: NPCPhrase (BYE_FROM_TRADE_WORLD_1); break; default: NPCPhrase (BYE_FROM_TRADE_WORLD_2); break; } } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) NPCPhrase (GOODBYE_FROM_BOMB_PLANET); else NPCPhrase (GOODBYE_FROM_SPACE); } else /* if (R == then_we_take_bomb) */ { SET_GAME_STATE (BATTLE_SEGUE, 1); NPCPhrase (FIGHT_FOR_BOMB); } } static void TradeWorld (RESPONSE_REF R); static void Buy (RESPONSE_REF R) { if (PLAYER_SAID (R, want_to_buy) || PLAYER_SAID (R, im_ready_to_buy)) { NPCPhrase (READY_TO_SELL); if (!GET_GAME_STATE (ROSY_SPHERE)) NPCPhrase (HAVE_SPHERE); if (!GET_GAME_STATE (ARTIFACT_2_ON_SHIP)) NPCPhrase (HAVE_ART_1); if (!GET_GAME_STATE (ARTIFACT_3_ON_SHIP)) NPCPhrase (HAVE_ART_2); NPCPhrase (SHIPS_AND_FUEL); SET_GAME_STATE (KNOW_DRUUGE_SLAVERS, 3); } else if (PLAYER_SAID (R, buy_druuge_ship)) { #define SHIP_CREW_COST 100 if (GLOBAL_SIS (CrewEnlisted) < SHIP_CREW_COST) NPCPhrase (NOT_ENOUGH_CREW); else if (ActivateStarShip (DRUUGE_SHIP, FEASIBILITY_STUDY) == 0) NPCPhrase (NOT_ENOUGH_ROOM); else { LockMutex (GraphicsLock); DeltaSISGauges (-SHIP_CREW_COST, 0, 0); UnlockMutex (GraphicsLock); SlaveryCount += SHIP_CREW_COST; ActivateStarShip (DRUUGE_SHIP, 1); NPCPhrase (BOUGHT_SHIP); } } #define ARTIFACT_CREW_COST 100 else if (PLAYER_SAID (R, buy_rosy_sphere)) { if (GLOBAL_SIS (CrewEnlisted) < ARTIFACT_CREW_COST) NPCPhrase (NOT_ENOUGH_CREW); else { LockMutex (GraphicsLock); DeltaSISGauges (-ARTIFACT_CREW_COST, 0, 0); UnlockMutex (GraphicsLock); SlaveryCount += ARTIFACT_CREW_COST; SET_GAME_STATE (ROSY_SPHERE_ON_SHIP, 1); SET_GAME_STATE (ROSY_SPHERE, 1); NPCPhrase (BOUGHT_SPHERE); } } else if (PLAYER_SAID (R, buy_art_1)) { if (GLOBAL_SIS (CrewEnlisted) < ARTIFACT_CREW_COST) NPCPhrase (NOT_ENOUGH_CREW); else { LockMutex (GraphicsLock); DeltaSISGauges (-ARTIFACT_CREW_COST, 0, 0); UnlockMutex (GraphicsLock); SlaveryCount += ARTIFACT_CREW_COST; SET_GAME_STATE (ARTIFACT_2_ON_SHIP, 1); NPCPhrase (BOUGHT_ART_1); } } else if (PLAYER_SAID (R, buy_art_2)) { if (GLOBAL_SIS (CrewEnlisted) < ARTIFACT_CREW_COST) NPCPhrase (NOT_ENOUGH_CREW); else { LockMutex (GraphicsLock); DeltaSISGauges (-ARTIFACT_CREW_COST, 0, 0); UnlockMutex (GraphicsLock); SlaveryCount += ARTIFACT_CREW_COST; SET_GAME_STATE (ARTIFACT_3_ON_SHIP, 1); NPCPhrase (BOUGHT_ART_2); } } else if (PLAYER_SAID (R, buy_fuel)) { #define FUEL_CREW_COST 10 if (GLOBAL_SIS (CrewEnlisted) < FUEL_CREW_COST) NPCPhrase (NOT_ENOUGH_CREW); else { LockMutex (GraphicsLock); DeltaSISGauges (-FUEL_CREW_COST, FUEL_CREW_COST * FUEL_TANK_SCALE, 0); UnlockMutex (GraphicsLock); SlaveryCount += FUEL_CREW_COST; NPCPhrase (BOUGHT_FUEL); } } Response (buy_druuge_ship, Buy); if (!GET_GAME_STATE (ROSY_SPHERE)) Response (buy_rosy_sphere, Buy); if (!GET_GAME_STATE (ARTIFACT_2_ON_SHIP)) Response (buy_art_1, Buy); if (!GET_GAME_STATE (ARTIFACT_3_ON_SHIP)) Response (buy_art_2, Buy); Response (buy_fuel, Buy); Response (done_buying, TradeWorld); } static void Sell (RESPONSE_REF R); static RESPONSE_REF LastResponse = 0; static void Trade (RESPONSE_REF R) { if (!PLAYER_SAID (R, whats_the_sphere_again)) { NPCPhrase (TRADE_FOR_SPHERE); LastResponse = R; } else { NPCPhrase (SPHERE_IS); DISABLE_PHRASE (whats_the_sphere_again); } Response (no_way, Sell); Response (way, Sell); if (PHRASE_ENABLED (whats_the_sphere_again)) { Response (whats_the_sphere_again, Trade); } } static void DoTransaction (RESPONSE_REF R) { if (PLAYER_SAID (R, sell_maidens)) { SET_GAME_STATE (MAIDENS_ON_SHIP, 0); } else if (PLAYER_SAID (R, sell_fragments)) { BYTE num_frags; if (GET_GAME_STATE (EGG_CASE0_ON_SHIP)) { SET_GAME_STATE (EGG_CASE0_ON_SHIP, 0); } else if (GET_GAME_STATE (EGG_CASE1_ON_SHIP)) { SET_GAME_STATE (EGG_CASE1_ON_SHIP, 0); } else if (GET_GAME_STATE (EGG_CASE2_ON_SHIP)) { SET_GAME_STATE (EGG_CASE2_ON_SHIP, 0); } num_frags = GET_GAME_STATE (FRAGMENTS_BOUGHT) + 1; SET_GAME_STATE (FRAGMENTS_BOUGHT, num_frags); } else if (PLAYER_SAID (R, sell_caster)) { SET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP, 0); } else if (PLAYER_SAID (R, sell_spawner)) { SET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP, 0); } if (!GET_GAME_STATE (ROSY_SPHERE) && GET_GAME_STATE (ROSY_SPHERE_ON_SHIP)) { SET_GAME_STATE (ROSY_SPHERE, 1); } else { BYTE trade_gas; BYTE ship_slots, ships_to_trade; trade_gas = 0; ships_to_trade = 0; ship_slots = ActivateStarShip (DRUUGE_SHIP, FEASIBILITY_STUDY); if (PLAYER_SAID (R, sell_maidens)) { NPCPhrase (BOUGHT_MAIDENS); ships_to_trade = 6; } else if (PLAYER_SAID (R, sell_fragments)) { NPCPhrase (BOUGHT_FRAGMENTS); ships_to_trade = 1; } else if (PLAYER_SAID (R, sell_caster)) { NPCPhrase (BOUGHT_CASTER); ships_to_trade = 0; trade_gas = 1; } else if (PLAYER_SAID (R, sell_spawner)) { NPCPhrase (BOUGHT_SPAWNER); ships_to_trade = 3; trade_gas = 1; } NPCPhrase (YOU_GET); if (ships_to_trade) { ActivateStarShip (DRUUGE_SHIP, ships_to_trade); if (ship_slots >= ships_to_trade) NPCPhrase (DEAL_FOR_STATED_SHIPS); else if (ship_slots == 0) NPCPhrase (DEAL_FOR_NO_SHIPS); else NPCPhrase (DEAL_FOR_LESS_SHIPS); if (trade_gas) NPCPhrase (YOU_ALSO_GET); } if (trade_gas) { BYTE slot; COUNT f; DWORD capacity; capacity = FUEL_RESERVE; slot = NUM_MODULE_SLOTS - 1; do { if (GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK || GLOBAL_SIS (ModuleSlots[slot]) == HIGHEFF_FUELSYS) { COUNT volume; volume = GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK ? FUEL_TANK_CAPACITY : HEFUEL_TANK_CAPACITY; capacity += volume; } } while (slot--); capacity -= GLOBAL_SIS (FuelOnBoard); f = (COUNT)((capacity + (FUEL_TANK_SCALE >> 1)) / FUEL_TANK_SCALE); LockMutex (GraphicsLock); while (capacity > 0x3FFFL) { DeltaSISGauges (0, 0x3FFF, 0); capacity -= 0x3FFF; } DeltaSISGauges (0, (SIZE)capacity, 0); UnlockMutex (GraphicsLock); NPCPhrase (FUEL0); NPCPhrase (-(int)f); NPCPhrase (FUEL1); if (f >= 250) NPCPhrase (HIDEOUS_DEAL); else if (f >= 100) NPCPhrase (BAD_DEAL); else if (f >= 50) NPCPhrase (FAIR_DEAL); else if (f >= 10) NPCPhrase (GOOD_DEAL); else NPCPhrase (FINE_DEAL); } } } static void Sell (RESPONSE_REF R) { RESPONSE_FUNC RespFunc; if (PLAYER_SAID (R, want_to_sell)) NPCPhrase (READY_TO_BUY); else if (PLAYER_SAID (R, no_way) || PLAYER_SAID (R, way)) { if (PLAYER_SAID (R, no_way)) NPCPhrase (OK_REGULAR_DEAL); else { NPCPhrase (OK_HERES_SPHERE); SET_GAME_STATE (ROSY_SPHERE_ON_SHIP, 1); } DoTransaction (LastResponse); } else if (PLAYER_SAID (R, sell_maidens) || PLAYER_SAID (R, sell_fragments) || PLAYER_SAID (R, sell_caster) || PLAYER_SAID (R, sell_spawner)) { DoTransaction (R); } if (!GET_GAME_STATE (ROSY_SPHERE)) RespFunc = (RESPONSE_FUNC)Trade; else RespFunc = (RESPONSE_FUNC)Sell; if (GET_GAME_STATE (MAIDENS_ON_SHIP)) Response (sell_maidens, RespFunc); if ((GET_GAME_STATE (EGG_CASE0_ON_SHIP) || GET_GAME_STATE (EGG_CASE1_ON_SHIP) || GET_GAME_STATE (EGG_CASE2_ON_SHIP)) && GET_GAME_STATE (FRAGMENTS_BOUGHT) < 2) Response (sell_fragments, RespFunc); if (GET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP)) Response (sell_caster, RespFunc); if (GET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP)) Response (sell_spawner, RespFunc); Response (done_selling, TradeWorld); } static void ExplainSlaveTrade (RESPONSE_REF R) { if (PLAYER_SAID (R, want_to_buy)) NPCPhrase (WE_SELL_FOR_CREW); else if (PLAYER_SAID (R, isnt_this_slave_trading)) { NPCPhrase (NO_SLAVE_TRADE); SET_GAME_STATE (KNOW_DRUUGE_SLAVERS, 1); } else if (PLAYER_SAID (R, what_do_with_crew)) { NPCPhrase (HAVE_FUN); SET_GAME_STATE (KNOW_DRUUGE_SLAVERS, 2); } switch (GET_GAME_STATE (KNOW_DRUUGE_SLAVERS)) { case 0: Response (isnt_this_slave_trading, ExplainSlaveTrade); break; case 1: Response (what_do_with_crew, ExplainSlaveTrade); break; } Response (i_will_never_trade_crew, TradeWorld); Response (im_ready_to_buy, Buy); } static void TradeWorld (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_up_at_trade_world)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (DRUUGE_HOME_INFO); switch (NumVisits++) { case 0: NPCPhrase (GEN_INFO_AT_TRADE_WORLD_1); break; case 1: NPCPhrase (GEN_INFO_AT_TRADE_WORLD_2); break; case 2: NPCPhrase (GEN_INFO_AT_TRADE_WORLD_3); if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) < 2) { SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 2); } break; case 3: NPCPhrase (GEN_INFO_AT_TRADE_WORLD_4); --NumVisits; break; } SET_GAME_STATE (DRUUGE_HOME_INFO, NumVisits); DISABLE_PHRASE (whats_up_at_trade_world); } else if (PLAYER_SAID (R, done_selling)) NPCPhrase (OK_DONE_SELLING); else if (PLAYER_SAID (R, done_buying)) NPCPhrase (OK_DONE_BUYING); else if (PLAYER_SAID (R, i_will_never_trade_crew)) NPCPhrase (YOUR_LOSS); if (PHRASE_ENABLED (whats_up_at_trade_world)) { Response (whats_up_at_trade_world, TradeWorld); } Response (want_to_sell, Sell); if (GET_GAME_STATE (KNOW_DRUUGE_SLAVERS) == 3) Response (want_to_buy, Buy); else Response (want_to_buy, ExplainSlaveTrade); Response (bye, ExitConversation); } static void BombAmbush (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_up_at_bomb_planet)) { NPCPhrase (GEN_INFO_AT_BOMB_PLANET); SET_GAME_STATE (BOMB_VISITS, 2); } else if (PLAYER_SAID (R, we_get_bomb)) { NPCPhrase (NOT_GET_BOMB); SET_GAME_STATE (BOMB_VISITS, 3); } switch (GET_GAME_STATE (BOMB_VISITS)) { case 1: Response (whats_up_at_bomb_planet, BombAmbush); break; case 2: Response (we_get_bomb, BombAmbush); break; default: Response (then_we_take_bomb, ExitConversation); break; } Response (bye, ExitConversation); } static void Space (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_up_in_space)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (DRUUGE_SPACE_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_IN_SPACE_1); break; case 1: NPCPhrase (GENERAL_INFO_IN_SPACE_2); break; case 2: NPCPhrase (GENERAL_INFO_IN_SPACE_3); break; case 3: NPCPhrase (GENERAL_INFO_IN_SPACE_4); --NumVisits; break; } SET_GAME_STATE (DRUUGE_SPACE_INFO, NumVisits); DISABLE_PHRASE (whats_up_in_space); } if (PHRASE_ENABLED (whats_up_in_space)) { Response (whats_up_in_space, Space); } Response (bye, ExitConversation); } static void Intro (void) { BYTE NumVisits; SlaveryCount = 0; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (GET_GAME_STATE (DRUUGE_MANNER)) { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (DRUUGE_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HSTL_TRADE_WORLD_HELLO_1); break; case 1: NPCPhrase (HSTL_TRADE_WORLD_HELLO_2); --NumVisits; break; } SET_GAME_STATE (DRUUGE_HOME_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (DRUUGE_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_SPACE_HELLO_1); break; case 1: NPCPhrase (HOSTILE_SPACE_HELLO_2); --NumVisits; break; } SET_GAME_STATE (DRUUGE_VISITS, NumVisits); } SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { { NumVisits = GET_GAME_STATE (DRUUGE_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (INITIAL_TRADE_WORLD_HELLO); break; case 1: NPCPhrase (SSQ_TRADE_WORLD_HELLO_1); break; case 2: NPCPhrase (SSQ_TRADE_WORLD_HELLO_2); break; case 3: NPCPhrase (SSQ_TRADE_WORLD_HELLO_3); break; case 4: NPCPhrase (SSQ_TRADE_WORLD_HELLO_4); --NumVisits; break; } SET_GAME_STATE (DRUUGE_HOME_VISITS, NumVisits); } if (GET_GAME_STATE (ATTACKED_DRUUGE) && !GET_GAME_STATE (DRUUGE_DISCLAIMER)) { // NPCPhrase (HOSTILE_TRADE); SET_GAME_STATE (DRUUGE_DISCLAIMER, 1); } if (GET_GAME_STATE (MAIDENS_ON_SHIP) && !GET_GAME_STATE (SCANNED_MAIDENS)) { NPCPhrase (SCAN_MAIDENS); SET_GAME_STATE (SCANNED_MAIDENS, 1); } if ((GET_GAME_STATE (EGG_CASE0_ON_SHIP) || GET_GAME_STATE (EGG_CASE1_ON_SHIP) || GET_GAME_STATE (EGG_CASE2_ON_SHIP)) && !GET_GAME_STATE (SCANNED_FRAGMENTS)) { if (GET_GAME_STATE (FRAGMENTS_BOUGHT) < 2) NPCPhrase (SCAN_FRAGMENTS); else NPCPhrase (ENOUGH_FRAGMENTS); SET_GAME_STATE (SCANNED_FRAGMENTS, 1); } if (GET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP) && !GET_GAME_STATE (SCANNED_CASTER)) { NPCPhrase (SCAN_DRUUGE_CASTER); SET_GAME_STATE (SCANNED_CASTER, 1); } if (GET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP) && !GET_GAME_STATE (SCANNED_SPAWNER)) { NPCPhrase (SCAN_ARILOU_SPAWNER); SET_GAME_STATE (SCANNED_SPAWNER, 1); } TradeWorld ((RESPONSE_REF)0); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { if (GET_GAME_STATE (BOMB_VISITS)) NPCPhrase (SUBSEQ_BOMB_WORLD_HELLO); else { NPCPhrase (INIT_BOMB_WORLD_HELLO); SET_GAME_STATE (BOMB_VISITS, 1); } BombAmbush ((RESPONSE_REF)0); } else if (GET_GAME_STATE (ATTACKED_DRUUGE)) { NumVisits = GET_GAME_STATE (DRUUGE_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_SPACE_HELLO_1); break; case 1: NPCPhrase (HOSTILE_SPACE_HELLO_2); --NumVisits; break; } SET_GAME_STATE (DRUUGE_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 1); } else { NumVisits = 0; if (GetHeadLink (&GLOBAL (built_ship_q)) == 0) { for (NumVisits = 0; NumVisits < NUM_MODULE_SLOTS; ++NumVisits) { BYTE which_module; which_module = GLOBAL_SIS (ModuleSlots[NumVisits]); if (which_module >= GUN_WEAPON && which_module <= CANNON_WEAPON) { NumVisits = 0; break; } } } if (NumVisits) { NumVisits = GET_GAME_STATE (DRUUGE_SALVAGE); switch (NumVisits++) { case 0: NPCPhrase (SALVAGE_YOUR_SHIP_1); break; case 1: NPCPhrase (SALVAGE_YOUR_SHIP_2); --NumVisits; break; } SET_GAME_STATE (DRUUGE_SALVAGE, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 1); } else { NumVisits = GET_GAME_STATE (DRUUGE_VISITS); switch (NumVisits++) { case 0: NPCPhrase (INIT_SPACE_HELLO); break; case 1: NPCPhrase (SUBSEQUENT_SPACE_HELLO); --NumVisits; break; } SET_GAME_STATE (DRUUGE_VISITS, NumVisits); Space ((RESPONSE_REF)0); } } } static COUNT uninit_druuge (void) { return (0); } static void post_druuge_enc (void) { if (GET_GAME_STATE (BATTLE_SEGUE) == 1 && !GET_GAME_STATE (DRUUGE_MANNER)) { if (!GET_GAME_STATE (ATTACKED_DRUUGE)) { SET_GAME_STATE (ATTACKED_DRUUGE, 1); SET_GAME_STATE (DRUUGE_VISITS, 0); } } } LOCDATAPTR init_druuge_comm (void) { LOCDATAPTR retval; druuge_desc.init_encounter_func = Intro; druuge_desc.post_encounter_func = post_druuge_enc; druuge_desc.uninit_encounter_func = uninit_druuge; druuge_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); druuge_desc.AlienTextBaseline.y = 70; druuge_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if ((GET_GAME_STATE (DRUUGE_MANNER) == 0 && (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &druuge_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/druuge/Makeinfo0000600000175000017500000000002710543202024017500 0ustar joeyjoeyuqm_CFILES="druugec.c" uqm-0.6.2/sc2/src/sc2code/comm/druuge/respkg.h0000600000175000017500000000003710543202024017471 0ustar joeyjoeyenum { DRUUGE_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/druuge/druuge.res0000600000175000017500000000036210543202024020034 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/druuge PACKAGE DRUUGE_PACKAGE druuge.con GFXRES DRUUGE_PMAP_ANIM druuge.ani FONTRES DRUUGE_FONT druuge.fon MUSICRES DRUUGE_MUSIC druuge.mod STRTAB DRUUGE_CONVERSATION_PHRASES druuge.txt uqm-0.6.2/sc2/src/sc2code/comm/druuge/resinst.h0000600000175000017500000000012610543202024017664 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/vux/0000755000175000017500000000000010552600275015376 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/vux/ifontres.h0000600000175000017500000000003710543202020017352 0ustar joeyjoey#define VUX_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/vux/restypes.h0000600000175000017500000000024110543202021017375 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/vux/vuxc.c0000600000175000017500000004151410543202021016507 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/vux/resinst.h" #include "comm/vux/strings.h" static LOCDATA vux_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)VUX_PMAP_ANIM, /* AlienFrame */ (FONT)VUX_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* (SIS_TEXT_WIDTH - 16) >> 1, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ VUX_COLOR_MAP, /* AlienColorMap */ VUX_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ VUX_CONVERSATION_PHRASES, /* PlayerPhrases */ 17, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 12, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 15, /* StartIndex */ 5, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 20, /* StartIndex */ 14, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND / 30, 0, /* RestartRate */ 0, /* BlockMask */ }, { 34, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 41, /* StartIndex */ 6, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 47, /* StartIndex */ 11, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 58, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 61, /* StartIndex */ 4, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 65, /* StartIndex */ 4, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 69, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 71, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 74, /* StartIndex */ 6, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND / 15, ONE_SECOND / 15, /* RestartRate */ 0, /* BlockMask */ }, { 80, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND / 15, ONE_SECOND / 15, /* RestartRate */ (1 << 14), /* BlockMask */ }, { 85, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND / 15, ONE_SECOND / 15, /* RestartRate */ 0, /* BlockMask */ }, { 90, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND / 15, ONE_SECOND / 15, /* RestartRate */ (1 << 12), /* BlockMask */ }, { 95, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 5, ONE_SECOND * 5,/* RestartRate */ 0, /* BlockMask */ }, { 99, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 5, ONE_SECOND * 5,/* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 11, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void CombatIsInevitable (RESPONSE_REF R) { BYTE NumVisits; SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, ok_take_beast)) { NPCPhrase (FOOL_AIEE0); NPCPhrase (FOOL_AIEE1); AlienTalkSegue (1); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 1) ), ONE_SECOND / 4); AlienTalkSegue ((COUNT)~0); SET_GAME_STATE (VUX_BEAST_ON_SHIP, 0); SET_GAME_STATE (ZEX_IS_DEAD, 1); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (PLAYER_SAID (R, try_any_way)) { NPCPhrase (NOPE); SET_GAME_STATE (VUX_STACK_1, 4); } else if (PLAYER_SAID (R, kill_you_squids_1) || PLAYER_SAID (R, kill_you_squids_2) || PLAYER_SAID (R, kill_you_squids_3) || PLAYER_SAID (R, kill_you_squids_4)) { NPCPhrase (WE_FIGHT); NumVisits = GET_GAME_STATE (VUX_STACK_2) + 1; if (NumVisits <= 3) { SET_GAME_STATE (VUX_STACK_2, NumVisits); } } else if (PLAYER_SAID (R, cant_we_be_friends_1) || PLAYER_SAID (R, cant_we_be_friends_2) || PLAYER_SAID (R, cant_we_be_friends_3) || PLAYER_SAID (R, cant_we_be_friends_4)) { NumVisits = GET_GAME_STATE (VUX_STACK_3); switch (NumVisits++) { case 0: NPCPhrase (NEVER_UGLY_HUMANS_1); break; case 1: NPCPhrase (NEVER_UGLY_HUMANS_2); break; case 2: NPCPhrase (NEVER_UGLY_HUMANS_3); break; case 3: NPCPhrase (NEVER_UGLY_HUMANS_4); --NumVisits; break; } SET_GAME_STATE (VUX_STACK_3, NumVisits); } else if (PLAYER_SAID (R, bye_hostile_space)) { NumVisits = GET_GAME_STATE (VUX_STACK_4); switch (NumVisits++) { case 0: NPCPhrase (GOODBYE_AND_DIE_HOSTILE_SPACE_1); break; case 1: NPCPhrase (GOODBYE_AND_DIE_HOSTILE_SPACE_2); break; case 2: NPCPhrase (GOODBYE_AND_DIE_HOSTILE_SPACE_3); break; case 3: NPCPhrase (GOODBYE_AND_DIE_HOSTILE_SPACE_4); --NumVisits; break; } SET_GAME_STATE (VUX_STACK_4, NumVisits); } else if (PLAYER_SAID (R, bye_zex)) { NPCPhrase (GOODBYE_ZEX); SET_GAME_STATE (BATTLE_SEGUE, 0); } else { NumVisits = GET_GAME_STATE (VUX_STACK_1); switch (NumVisits++) { case 4: NPCPhrase (NOT_ACCEPTED_1); break; case 5: NPCPhrase (NOT_ACCEPTED_2); break; case 6: NPCPhrase (NOT_ACCEPTED_3); break; case 7: NPCPhrase (NOT_ACCEPTED_4); break; case 8: NPCPhrase (NOT_ACCEPTED_5); break; case 9: NPCPhrase (NOT_ACCEPTED_6); break; case 10: NPCPhrase (NOT_ACCEPTED_7); break; case 11: NPCPhrase (NOT_ACCEPTED_8); break; case 12: NPCPhrase (NOT_ACCEPTED_9); break; case 13: NPCPhrase (TRUTH); break; } SET_GAME_STATE (VUX_STACK_1, NumVisits); } } static void Menagerie (RESPONSE_REF R) { BYTE i, LastStack; RESPONSE_REF pStr[3]; if (PLAYER_SAID (R, i_have_beast) || PLAYER_SAID (R, why_trust_1) || PLAYER_SAID (R, why_trust_2) || PLAYER_SAID (R, why_trust_3)) { if (PLAYER_SAID (R, i_have_beast)) NPCPhrase (GIVE_BEAST); else if (PLAYER_SAID (R, why_trust_1)) { NPCPhrase (TRUST_1); DISABLE_PHRASE (why_trust_1); } else if (PLAYER_SAID (R, why_trust_2)) { NPCPhrase (TRUST_2); DISABLE_PHRASE (why_trust_2); } else if (PLAYER_SAID (R, why_trust_3)) { NPCPhrase (TRUST_3); DISABLE_PHRASE (why_trust_3); } if (PHRASE_ENABLED (why_trust_1)) Response (why_trust_1, Menagerie); else if (PHRASE_ENABLED (why_trust_2)) Response (why_trust_2, Menagerie); else if (PHRASE_ENABLED (why_trust_3)) Response (why_trust_3, Menagerie); Response (ok_take_beast, CombatIsInevitable); } else if (PLAYER_SAID (R, kill_you)) { NPCPhrase (FIGHT_AGAIN); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, regardless)) { NPCPhrase (THEN_FIGHT); SET_GAME_STATE (BATTLE_SEGUE, 1); SET_GAME_STATE (ZEX_STACK_3, 2); SET_GAME_STATE (ZEX_VISITS, 0); } else { LastStack = 0; pStr[0] = pStr[1] = pStr[2] = 0; if (R == 0) { BYTE NumVisits; NumVisits = GET_GAME_STATE (ZEX_VISITS); if (GET_GAME_STATE (ZEX_STACK_3) >= 2) { switch (NumVisits++) { case 0: NPCPhrase (FIGHT_OR_TRADE_1); break; case 1: NPCPhrase (FIGHT_OR_TRADE_2); --NumVisits; break; } } else { switch (NumVisits++) { case 0: NPCPhrase (ZEX_HELLO_1); break; case 1: NPCPhrase (ZEX_HELLO_2); break; case 2: NPCPhrase (ZEX_HELLO_3); break; case 3: NPCPhrase (ZEX_HELLO_4); --NumVisits; break; } } SET_GAME_STATE (ZEX_VISITS, NumVisits); } else if (PLAYER_SAID (R, what_you_do_here)) { NPCPhrase (MY_MENAGERIE); SET_GAME_STATE (ZEX_STACK_1, 1); } else if (PLAYER_SAID (R, what_about_menagerie)) { NPCPhrase (NEED_NEW_CREATURE); SET_GAME_STATE (ZEX_STACK_1, 2); } else if (PLAYER_SAID (R, what_about_creature)) { NPCPhrase (ABOUT_CREATURE); SET_GAME_STATE (KNOW_ZEX_WANTS_MONSTER, 1); SET_GAME_STATE (ZEX_STACK_1, 3); R = about_creature_again; DISABLE_PHRASE (what_about_creature); } else if (PLAYER_SAID (R, about_creature_again)) { NPCPhrase (CREATURE_AGAIN); DISABLE_PHRASE (about_creature_again); } else if (PLAYER_SAID (R, why_dont_you_attack)) { NPCPhrase (LIKE_YOU); LastStack = 1; SET_GAME_STATE (ZEX_STACK_2, 1); } else if (PLAYER_SAID (R, why_like_me)) { NPCPhrase (LIKE_BECAUSE); LastStack = 1; SET_GAME_STATE (ZEX_STACK_2, 2); } else if (PLAYER_SAID (R, are_you_a_pervert)) { NPCPhrase (CALL_ME_WHAT_YOU_WISH); SET_GAME_STATE (ZEX_STACK_2, 3); } else if (PLAYER_SAID (R, take_by_force)) { NPCPhrase (PRECURSOR_DEVICE); LastStack = 2; SET_GAME_STATE (ZEX_STACK_3, 1); } else if (PLAYER_SAID (R, you_lied)) { NPCPhrase (YUP_LIED); LastStack = 2; SET_GAME_STATE (ZEX_STACK_3, 3); } if (GET_GAME_STATE (KNOW_ZEX_WANTS_MONSTER) && GET_GAME_STATE (VUX_BEAST_ON_SHIP)) pStr[0] = i_have_beast; else { switch (GET_GAME_STATE (ZEX_STACK_1)) { case 0: pStr[0] = what_you_do_here; break; case 1: pStr[0] = what_about_menagerie; break; case 2: pStr[0] = what_about_creature; break; case 3: if (PHRASE_ENABLED (about_creature_again)) pStr[0] = about_creature_again; break; } } switch (GET_GAME_STATE (ZEX_STACK_2)) { case 0: pStr[1] = why_dont_you_attack; break; case 1: pStr[1] = why_like_me; break; case 2: pStr[1] = are_you_a_pervert; break; } switch (GET_GAME_STATE (ZEX_STACK_3)) { case 0: pStr[2] = take_by_force; break; case 1: pStr[2] = regardless; break; case 2: pStr[2] = you_lied; break; case 3: pStr[2] = kill_you; break; } if (pStr[LastStack]) Response (pStr[LastStack], Menagerie); for (i = 0; i < 3; ++i) { if (i != LastStack && pStr[i]) Response (pStr[i], Menagerie); } Response (bye_zex, CombatIsInevitable); } } static void NormalVux (RESPONSE_REF R) { if (PLAYER_SAID (R, why_so_mean)) { NPCPhrase (URQUAN_SLAVES); SET_GAME_STATE (VUX_STACK_1, 1); } else if (PLAYER_SAID (R, deeper_reason)) { NPCPhrase (OLD_INSULT); SET_GAME_STATE (VUX_STACK_1, 2); } else if (PLAYER_SAID (R, if_we_apologize)) { NPCPhrase (PROBABLY_NOT); SET_GAME_STATE (VUX_STACK_1, 3); } else if (PLAYER_SAID (R, whats_up_hostile)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (VUX_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_HOSTILE_1); break; case 1: NPCPhrase (GENERAL_INFO_HOSTILE_2); break; case 2: NPCPhrase (GENERAL_INFO_HOSTILE_3); break; case 3: NPCPhrase (GENERAL_INFO_HOSTILE_4); --NumVisits; break; } SET_GAME_STATE (VUX_INFO, NumVisits); DISABLE_PHRASE (whats_up_hostile); } switch (GET_GAME_STATE (VUX_STACK_1)) { case 0: Response (why_so_mean, NormalVux); break; case 1: Response (deeper_reason, NormalVux); break; case 2: Response (if_we_apologize, NormalVux); break; case 3: Response (try_any_way, CombatIsInevitable); break; case 4: Response (apology_1, CombatIsInevitable); break; case 5: Response (apology_2, CombatIsInevitable); break; case 6: Response (apology_3, CombatIsInevitable); break; case 7: Response (apology_4, CombatIsInevitable); break; case 8: Response (apology_5, CombatIsInevitable); break; case 9: Response (apology_6, CombatIsInevitable); break; case 10: Response (apology_7, CombatIsInevitable); break; case 11: Response (apology_8, CombatIsInevitable); break; case 12: Response (apology_9, CombatIsInevitable); break; case 13: Response (apology_10, CombatIsInevitable); break; } switch (GET_GAME_STATE (VUX_STACK_2)) { case 0: Response (kill_you_squids_1, CombatIsInevitable); break; case 1: Response (kill_you_squids_2, CombatIsInevitable); break; case 2: Response (kill_you_squids_3, CombatIsInevitable); break; case 3: Response (kill_you_squids_4, CombatIsInevitable); break; } if (PHRASE_ENABLED (whats_up_hostile)) { Response (whats_up_hostile, NormalVux); } if (GET_GAME_STATE (VUX_STACK_1) > 13) { switch (GET_GAME_STATE (VUX_STACK_3)) { case 0: Response (cant_we_be_friends_1, CombatIsInevitable); break; case 1: Response (cant_we_be_friends_2, CombatIsInevitable); break; case 2: Response (cant_we_be_friends_3, CombatIsInevitable); break; case 3: Response (cant_we_be_friends_4, CombatIsInevitable); break; } } Response (bye_hostile_space, CombatIsInevitable); } static void Intro (void) { if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { Menagerie ((RESPONSE_REF)0); } else { BYTE NumVisits; if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (VUX_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (HOMEWORLD_HELLO_2); break; case 2: NPCPhrase (HOMEWORLD_HELLO_3); break; case 3: NPCPhrase (HOMEWORLD_HELLO_4); --NumVisits; break; } SET_GAME_STATE (VUX_HOME_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (VUX_VISITS); switch (NumVisits++) { case 0: NPCPhrase (SPACE_HELLO_1); break; case 1: NPCPhrase (SPACE_HELLO_2); break; case 2: NPCPhrase (SPACE_HELLO_3); break; case 3: NPCPhrase (SPACE_HELLO_4); --NumVisits; break; } SET_GAME_STATE (VUX_VISITS, NumVisits); } NormalVux ((RESPONSE_REF)0); } } static COUNT uninit_vux (void) { return (0); } static void post_vux_enc (void) { // nothing defined so far } LOCDATAPTR init_vux_comm (void) { LOCDATAPTR retval; vux_desc.init_encounter_func = Intro; vux_desc.post_encounter_func = post_vux_enc; vux_desc.uninit_encounter_func = uninit_vux; vux_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1) + (SIS_TEXT_WIDTH >> 2); vux_desc.AlienTextBaseline.y = 0; vux_desc.AlienTextWidth = (SIS_TEXT_WIDTH - 16) >> 1; if ((GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &vux_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/vux/strings.h0000600000175000017500000000507010543202021017215 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, ZEX_HELLO_1, ZEX_HELLO_2, ZEX_HELLO_3, ZEX_HELLO_4, FIGHT_OR_TRADE_1, FIGHT_OR_TRADE_2, what_you_do_here, MY_MENAGERIE, what_about_menagerie, NEED_NEW_CREATURE, what_about_creature, ABOUT_CREATURE, about_creature_again, CREATURE_AGAIN, i_have_beast, GIVE_BEAST, ok_take_beast, FOOL_AIEE0, FOOL_AIEE1, why_trust_1, TRUST_1, why_trust_2, TRUST_2, why_trust_3, TRUST_3, why_dont_you_attack, LIKE_YOU, why_like_me, LIKE_BECAUSE, are_you_a_pervert, CALL_ME_WHAT_YOU_WISH, take_by_force, PRECURSOR_DEVICE, regardless, THEN_FIGHT, you_lied, YUP_LIED, kill_you, FIGHT_AGAIN, bye_zex, GOODBYE_ZEX, HOMEWORLD_HELLO_1, HOMEWORLD_HELLO_2, HOMEWORLD_HELLO_3, HOMEWORLD_HELLO_4, SPACE_HELLO_1, SPACE_HELLO_2, SPACE_HELLO_3, SPACE_HELLO_4, kill_you_squids_1, kill_you_squids_2, kill_you_squids_3, kill_you_squids_4, WE_FIGHT, why_so_mean, URQUAN_SLAVES, deeper_reason, OLD_INSULT, if_we_apologize, PROBABLY_NOT, try_any_way, NOPE, APOLOGIZE_IN_SPACE, apology_1, NOT_ACCEPTED_1, apology_2, NOT_ACCEPTED_2, apology_3, NOT_ACCEPTED_3, apology_4, NOT_ACCEPTED_4, apology_5, NOT_ACCEPTED_5, apology_6, NOT_ACCEPTED_6, apology_7, NOT_ACCEPTED_7, apology_8, NOT_ACCEPTED_8, apology_9, NOT_ACCEPTED_9, apology_10, TRUTH, whats_up_hostile, GENERAL_INFO_HOSTILE_1, GENERAL_INFO_HOSTILE_2, GENERAL_INFO_HOSTILE_3, GENERAL_INFO_HOSTILE_4, cant_we_be_friends_1, NEVER_UGLY_HUMANS_1, cant_we_be_friends_2, NEVER_UGLY_HUMANS_2, cant_we_be_friends_3, NEVER_UGLY_HUMANS_3, cant_we_be_friends_4, NEVER_UGLY_HUMANS_4, bye_hostile_space, GOODBYE_AND_DIE_HOSTILE_SPACE_1, GOODBYE_AND_DIE_HOSTILE_SPACE_2, GOODBYE_AND_DIE_HOSTILE_SPACE_3, GOODBYE_AND_DIE_HOSTILE_SPACE_4, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/vux/igfxres.h0000600000175000017500000000004410543202021017167 0ustar joeyjoey#define VUX_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/vux/istrtab.h0000600000175000017500000000012110543202021017164 0ustar joeyjoey#define VUX_CONVERSATION_PHRASES 0x00200004L #define VUX_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/vux/imusicre.h0000600000175000017500000000004010543202021017334 0ustar joeyjoey#define VUX_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/vux/Makeinfo0000600000175000017500000000002410543202021017021 0ustar joeyjoeyuqm_CFILES="vuxc.c" uqm-0.6.2/sc2/src/sc2code/comm/vux/respkg.h0000600000175000017500000000003410543202021017012 0ustar joeyjoeyenum { VUX_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/vux/vux.res0000600000175000017500000000036310543202021016710 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/vux PACKAGE VUX_PACKAGE vux.con GFXRES VUX_PMAP_ANIM vux.ani FONTRES VUX_FONT vux.fon MUSICRES VUX_MUSIC vux.mod STRTAB VUX_CONVERSATION_PHRASES vux.txt STRTAB VUX_COLOR_MAP vux.ct uqm-0.6.2/sc2/src/sc2code/comm/vux/resinst.h0000600000175000017500000000012610543202021017210 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/shofixt/0000755000175000017500000000000010552600275016240 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/shofixt/ifontres.h0000600000175000017500000000004410543202022020214 0ustar joeyjoey#define SHOFIXTI_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/shofixt/restypes.h0000600000175000017500000000024110543202022020240 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/shofixt/strings.h0000600000175000017500000000433110543202022020057 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, name_1, name_2, name_3, name_40, name_41, tanaka, katana, HOSTILE_KATANA_1, HOSTILE_KATANA_2, HOSTILE_KATANA_3, HOSTILE_KATANA_4, HOSTILE_TANAKA_1, HOSTILE_TANAKA_2, HOSTILE_TANAKA_3, HOSTILE_TANAKA_4, HOSTILE_TANAKA_5, HOSTILE_TANAKA_6, HOSTILE_TANAKA_7, HOSTILE_TANAKA_8, dont_attack, TYPICAL_PLOY, hey_stop, ONLY_STOP, look_you_are, TOO_BAD, dont_know, NEVER, look0, look1, FOR_YOU, no_bloodshed, YES_BLOODSHED, dont_want_to_fight, MUST_FIGHT_YOU_URQUAN_1, MUST_FIGHT_YOU_URQUAN_2, MUST_FIGHT_YOU_URQUAN_3, MUST_FIGHT_YOU_URQUAN_4, no_one_insults, YOU_LIMP, mighty_words, HANG_YOUR, donkey_breath, DGRUNTI, i_am_captain0, i_am_captain1, i_am_captain2, i_am_captain3, i_am_nice, i_am_guy, SO_SORRY, MUST_UNDERSTAND, NICE_BUT_WHAT_IS_DONKEY, IS_DEFEAT_TRUE, yes_and_no, butt_blasted, clobbered, VERY_SAD_KILL_SELF, important_duty, WHAT_DUTY, need_you_for_duty, OK_WILL_BE_SENTRY, dont_do_it, YES_I_DO_IT, go_ahead, ON_SECOND_THOUGHT, procreating_wildly, replenishing_your_species, hope_you_have, SOUNDS_GREAT_BUT_HOW, females, nubiles, rat_babes, LEAPING_HAPPINESS, bye0, bye1, GOODBYE0, GOODBYE1, why_here0, why_here1, I_GUARD, where_world, BLEW_IT_UP, how_survive, NOT_HERE, what_happened, MET_VUX, glory_device, SWITCH_BROKE, bye, GOODBYE, FRIENDLY_HELLO, report0, report1, NOTHING_NEW, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/shofixt/igfxres.h0000600000175000017500000000005110543202022020030 0ustar joeyjoey#define SHOFIXTI_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/shofixt/shofixt.res0000600000175000017500000000040110543202022020406 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/shofixt PACKAGE SHOFIXTI_PACKAGE shofixt.con GFXRES SHOFIXTI_PMAP_ANIM shofixt.ani FONTRES SHOFIXTI_FONT shofixt.fon MUSICRES SHOFIXTI_MUSIC shofixt.mod STRTAB SHOFIXTI_CONVERSATION_PHRASES shofixt.txt uqm-0.6.2/sc2/src/sc2code/comm/shofixt/istrtab.h0000600000175000017500000000013210543202022020031 0ustar joeyjoey#define SHOFIXTI_CONVERSATION_PHRASES 0x00200004L #define SHOFIXTI_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/shofixt/imusicre.h0000600000175000017500000000004510543202022020204 0ustar joeyjoey#define SHOFIXTI_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/shofixt/Makeinfo0000600000175000017500000000002710543202022017667 0ustar joeyjoeyuqm_CFILES="shofixt.c" uqm-0.6.2/sc2/src/sc2code/comm/shofixt/respkg.h0000600000175000017500000000004110543202022017653 0ustar joeyjoeyenum { SHOFIXTI_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/shofixt/shofixt.c0000600000175000017500000003242210543202022020047 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/shofixt/resinst.h" #include "comm/shofixt/strings.h" #include "gameev.h" static LOCDATA shofixti_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)SHOFIXTI_PMAP_ANIM, /* AlienFrame */ (FONT)SHOFIXTI_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)SHOFIXTI_COLOR_MAP, /* AlienColorMap */ SHOFIXTI_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ SHOFIXTI_CONVERSATION_PHRASES, /* PlayerPhrases */ 11, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 5, /* StartIndex */ 15, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND / 30, 0, /* RestartRate */ 0, /* BlockMask */ }, { 20, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ (ONE_SECOND >> 1), (ONE_SECOND >> 1) * 3, /* RestartRate */ 0, /* BlockMask */ }, { 23, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ (ONE_SECOND >> 1), (ONE_SECOND >> 1) * 3, /* RestartRate */ 0, /* BlockMask */ }, { 26, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 29, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 33, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 20, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 39, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 20, ONE_SECOND / 30, /* RestartRate */ (1 << 7), /* BlockMask */ }, { 46, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 20, ONE_SECOND / 30, /* RestartRate */ (1 << 6), /* BlockMask */ }, { 52, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 20, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 56, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 20, ONE_SECOND / 30, /* RestartRate */ (1 << 10), /* BlockMask */ }, { 63, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 20, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 20, ONE_SECOND / 30, /* RestartRate */ (1 << 9), /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 4, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND / 15, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static RESPONSE_REF shofixti_name; static void GetShofixtiName (void) { if (GET_GAME_STATE (SHOFIXTI_KIA)) shofixti_name = katana; else shofixti_name = tanaka; } static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, bye0)) { NPCPhrase (GOODBYE); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (PLAYER_SAID (R, go_ahead)) { NPCPhrase (ON_SECOND_THOUGHT); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (PLAYER_SAID (R, need_you_for_duty)) { NPCPhrase (OK_WILL_BE_SENTRY); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (PLAYER_SAID (R, females) || PLAYER_SAID (R, nubiles) || PLAYER_SAID (R, rat_babes)) { NPCPhrase (LEAPING_HAPPINESS); SET_GAME_STATE (SHOFIXTI_RECRUITED, 1); SET_GAME_STATE (MAIDENS_ON_SHIP, 0); SET_GAME_STATE (BATTLE_SEGUE, 0); AddEvent (RELATIVE_EVENT, 2, 0, 0, SHOFIXTI_RETURN_EVENT); } else if (PLAYER_SAID (R, dont_attack)) { NPCPhrase (TYPICAL_PLOY); SET_GAME_STATE (SHOFIXTI_STACK1, 1); } else if (PLAYER_SAID (R, hey_stop)) { NPCPhrase (ONLY_STOP); SET_GAME_STATE (SHOFIXTI_STACK1, 2); } else if (PLAYER_SAID (R, look_you_are)) { NPCPhrase (TOO_BAD); SET_GAME_STATE (SHOFIXTI_STACK1, 3); } else if (PLAYER_SAID (R, no_one_insults)) { NPCPhrase (YOU_LIMP); SET_GAME_STATE (SHOFIXTI_STACK2, 1); } else if (PLAYER_SAID (R, mighty_words)) { NPCPhrase (HANG_YOUR); SET_GAME_STATE (SHOFIXTI_STACK2, 2); } else if (PLAYER_SAID (R, dont_know)) { NPCPhrase (NEVER); SET_GAME_STATE (SHOFIXTI_STACK3, 1); } else if (PLAYER_SAID (R, look0)) { NPCPhrase (FOR_YOU); SET_GAME_STATE (SHOFIXTI_STACK3, 2); } else if (PLAYER_SAID (R, no_bloodshed)) { NPCPhrase (YES_BLOODSHED); SET_GAME_STATE (SHOFIXTI_STACK3, 3); } else if (PLAYER_SAID (R, dont_want_to_fight)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (SHOFIXTI_STACK4); switch (NumVisits++) { case 0: NPCPhrase (MUST_FIGHT_YOU_URQUAN_1); break; case 1: NPCPhrase (MUST_FIGHT_YOU_URQUAN_2); break; case 2: NPCPhrase (MUST_FIGHT_YOU_URQUAN_3); break; case 3: NPCPhrase (MUST_FIGHT_YOU_URQUAN_4); --NumVisits; break; } SET_GAME_STATE (SHOFIXTI_STACK4, NumVisits); } } static void GiveMaidens (RESPONSE_REF R) { if (PLAYER_SAID (R, important_duty)) { NPCPhrase (WHAT_DUTY); Response (procreating_wildly, GiveMaidens); Response (replenishing_your_species, GiveMaidens); Response (hope_you_have, GiveMaidens); } else { NPCPhrase (SOUNDS_GREAT_BUT_HOW); Response (females, ExitConversation); Response (nubiles, ExitConversation); Response (rat_babes, ExitConversation); } } static void ConsoleShofixti (RESPONSE_REF R) { if (PLAYER_SAID (R, dont_do_it)) { NPCPhrase (YES_I_DO_IT); DISABLE_PHRASE (dont_do_it); } else NPCPhrase (VERY_SAD_KILL_SELF); if (GET_GAME_STATE (MAIDENS_ON_SHIP)) { Response (important_duty, GiveMaidens); } if (PHRASE_ENABLED (dont_do_it)) { Response (dont_do_it, ConsoleShofixti); } Response (need_you_for_duty, ExitConversation); Response (go_ahead, ExitConversation); } static void ExplainDefeat (RESPONSE_REF R) { if (PLAYER_SAID (R, i_am_nice)) NPCPhrase (MUST_UNDERSTAND); else if (PLAYER_SAID (R, i_am_guy)) NPCPhrase (NICE_BUT_WHAT_IS_DONKEY); else /* if (PLAYER_SAID (R, i_am_captain0)) */ NPCPhrase (SO_SORRY); NPCPhrase (IS_DEFEAT_TRUE); Response (yes_and_no, ConsoleShofixti); Response (clobbered, ConsoleShofixti); Response (butt_blasted, ConsoleShofixti); } static void RealizeMistake (RESPONSE_REF R) { (void) R; // ignored NPCPhrase (DGRUNTI); SET_GAME_STATE (SHOFIXTI_STACK1, 0); SET_GAME_STATE (SHOFIXTI_STACK3, 0); SET_GAME_STATE (SHOFIXTI_STACK2, 3); { UNICODE buf[ALLIANCE_NAME_BUFSIZE]; GetAllianceName (buf, name_1); construct_response ( shared_phrase_buf, i_am_captain0, GLOBAL_SIS (CommanderName), i_am_captain1, buf, i_am_captain2, GLOBAL_SIS (ShipName), i_am_captain3, NULL_PTR ); } DoResponsePhrase (i_am_captain0, ExplainDefeat, shared_phrase_buf); Response (i_am_nice, ExplainDefeat); Response (i_am_guy, ExplainDefeat); } static void Hostile (RESPONSE_REF R) { (void) R; // ignored switch (GET_GAME_STATE (SHOFIXTI_STACK1)) { case 0: Response (dont_attack, ExitConversation); break; case 1: Response (hey_stop, ExitConversation); break; case 2: Response (look_you_are, ExitConversation); break; } switch (GET_GAME_STATE (SHOFIXTI_STACK2)) { case 0: Response (no_one_insults, ExitConversation); break; case 1: Response (mighty_words, ExitConversation); break; case 2: Response (donkey_breath, RealizeMistake); break; } switch (GET_GAME_STATE (SHOFIXTI_STACK3)) { case 0: Response (dont_know, ExitConversation); break; case 1: { construct_response ( shared_phrase_buf, look0, "", shofixti_name, "", look1, NULL_PTR ); DoResponsePhrase (look0, ExitConversation, shared_phrase_buf); break; } case 2: Response (look_you_are, ExitConversation); break; } Response (dont_want_to_fight, ExitConversation); } static void Friendly (RESPONSE_REF R) { BYTE i, LastStack; struct { RESPONSE_REF pStr; UNICODE *c_buf; } Resp[3]; static UNICODE buf0[80], buf1[80]; LastStack = 0; memset (Resp, 0, sizeof (Resp)); if (PLAYER_SAID (R, report0)) { NPCPhrase (NOTHING_NEW); DISABLE_PHRASE (report0); } else if (PLAYER_SAID (R, why_here0)) { NPCPhrase (I_GUARD); LastStack = 1; SET_GAME_STATE (SHOFIXTI_STACK1, 1); } else if (PLAYER_SAID (R, what_happened)) { NPCPhrase (MET_VUX); LastStack = 1; SET_GAME_STATE (SHOFIXTI_STACK1, 2); } else if (PLAYER_SAID (R, glory_device)) { NPCPhrase (SWITCH_BROKE); SET_GAME_STATE (SHOFIXTI_STACK1, 3); } else if (PLAYER_SAID (R, where_world)) { NPCPhrase (BLEW_IT_UP); LastStack = 2; SET_GAME_STATE (SHOFIXTI_STACK3, 1); } else if (PLAYER_SAID (R, how_survive)) { NPCPhrase (NOT_HERE); SET_GAME_STATE (SHOFIXTI_STACK3, 2); } if (PHRASE_ENABLED (report0)) { construct_response ( buf0, report0, "", shofixti_name, "", report1, NULL_PTR ); Resp[0].pStr = report0; Resp[0].c_buf = buf0; } switch (GET_GAME_STATE (SHOFIXTI_STACK1)) { case 0: construct_response ( buf1, why_here0, "", shofixti_name, "", why_here1, NULL_PTR ); Resp[1].pStr = why_here0; Resp[1].c_buf = buf1; break; case 1: Resp[1].pStr = what_happened; break; case 2: Resp[1].pStr = glory_device; break; } switch (GET_GAME_STATE (SHOFIXTI_STACK3)) { case 0: Resp[2].pStr = where_world; break; case 1: Resp[2].pStr = how_survive; break; } if (Resp[LastStack].pStr) DoResponsePhrase (Resp[LastStack].pStr, Friendly, Resp[LastStack].c_buf); for (i = 0; i < 3; ++i) { if (i != LastStack && Resp[i].pStr) DoResponsePhrase (Resp[i].pStr, Friendly, Resp[i].c_buf); } if (GET_GAME_STATE (MAIDENS_ON_SHIP)) { Response (important_duty, GiveMaidens); } construct_response ( shared_phrase_buf, bye0, "", shofixti_name, "", bye1, NULL_PTR ); DoResponsePhrase (bye0, ExitConversation, shared_phrase_buf); } static void Intro (void) { if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } GetShofixtiName (); if (GET_GAME_STATE (SHOFIXTI_STACK2) > 2) { NPCPhrase (FRIENDLY_HELLO); Friendly ((RESPONSE_REF)0); } else { BYTE NumVisits; NumVisits = GET_GAME_STATE (SHOFIXTI_VISITS); if (GET_GAME_STATE (SHOFIXTI_KIA)) { switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_KATANA_1); break; case 1: NPCPhrase (HOSTILE_KATANA_2); break; case 2: NPCPhrase (HOSTILE_KATANA_3); break; case 3: NPCPhrase (HOSTILE_KATANA_4); --NumVisits; break; } } else { switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_TANAKA_1); break; case 1: NPCPhrase (HOSTILE_TANAKA_2); break; case 2: NPCPhrase (HOSTILE_TANAKA_3); break; case 3: NPCPhrase (HOSTILE_TANAKA_4); break; case 4: NPCPhrase (HOSTILE_TANAKA_5); break; case 5: NPCPhrase (HOSTILE_TANAKA_6); break; case 6: NPCPhrase (HOSTILE_TANAKA_7); break; case 7: NPCPhrase (HOSTILE_TANAKA_8); --NumVisits; break; } } SET_GAME_STATE (SHOFIXTI_VISITS, NumVisits); Hostile ((RESPONSE_REF)0); } } static COUNT uninit_shofixti (void) { return(0); } static void post_shofixti_enc (void) { // nothing defined so far } LOCDATAPTR init_shofixti_comm (void) { LOCDATAPTR retval; shofixti_desc.init_encounter_func = Intro; shofixti_desc.post_encounter_func = post_shofixti_enc; shofixti_desc.uninit_encounter_func = uninit_shofixti; shofixti_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); shofixti_desc.AlienTextBaseline.y = 0; shofixti_desc.AlienTextWidth = SIS_TEXT_WIDTH; SET_GAME_STATE (BATTLE_SEGUE, 0); retval = &shofixti_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/shofixt/resinst.h0000600000175000017500000000012610543202022020053 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/talkpet/0000755000175000017500000000000010552600275016220 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/talkpet/ifontres.h0000600000175000017500000000004710543202026020203 0ustar joeyjoey#define TALKING_PET_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/talkpet/restypes.h0000600000175000017500000000024110543202026020224 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/talkpet/strings.h0000600000175000017500000000545510543202026020053 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, HELLO_AT_UMGAH, what_are_you, JUST_TALKING_PET, talking_pets_dumb, OH_NO_YOU_DONT, what_do_to_umgah, DID_NOTHING, umgah_zombies, WORKS_LIKE_THIS, we_are_vindicator0, we_are_vindicator1, GOOD_FOR_YOU, must_explain_presence, EXPLAIN_NOTHING_MONKEY_BOY, bye_at_umgah, GOODBYE_AT_UMGAH, HYPNOTIZE_AGAIN_1, HYPNOTIZE_AGAIN_2, HYPNOTIZE_AGAIN_3, HYPNOTIZE_AGAIN_4, HYPNO_TAIL, CANT_COMPEL, LETS_MAKE_A_DEAL, what_kind_of_deal, HELP_DEFEAT_URQUAN, ok_lets_do_it, COMING_ABOARD, how_trust, TRUST, boneless_dweeb, YOUR_BONELESS_DWEEB, what_are_you_really, POOR_DNYARRI, hard_to_believe, ITS_TRUE, bullshit, WORTH_A_TRY, kill_you, PLEASE_DONT, must_kill, DONT_KILL, want_kill_1, want_kill_2, want_kill_3, GLAD_YOU_WONT_KILL, whats_up_onboard, GENERAL_INFO_ONBOARD_1, GENERAL_INFO_ONBOARD_2, GENERAL_INFO_ONBOARD_3, GENERAL_INFO_ONBOARD_4, GENERAL_INFO_ONBOARD_5, GENERAL_INFO_ONBOARD_6, GENERAL_INFO_ONBOARD_7, GENERAL_INFO_ONBOARD_8, HELLO_AS_DEVICE_1, HELLO_AS_DEVICE_2, HELLO_AS_DEVICE_3, HELLO_AS_DEVICE_4, HELLO_AS_DEVICE_5, HELLO_AS_DEVICE_6, HELLO_AS_DEVICE_7, HELLO_AS_DEVICE_8, CYBORG_PEP_TALK, HUMAN_PEP_TALK, I_SENSE_MY_SLAVES, HAVENT_GOT_EVERYTHING, NEED_BOMB, SOUP_UP_BOMB, SOUP_UP_FLEET, SOUP_UP_FLAGSHIP, COMEBACK_WHEN_READY, what_now, DO_THIS, compel_urquan, HERE_WE_GO, im_scared, STUPID_FOP, compel_that_ship, SAVING_MY_POWER, any_suggestions, SUGGESTION_1, SUGGESTION_2, SUGGESTION_3, SUGGESTION_4, SUGGESTION_5, SUGGESTION_6, SUGGESTION_7, SUGGESTION_8, about_your_race, WHAT_ABOUT_RACE, you_lied, SO_WHAT, bye_onboard, GOODBYE_ONBOARD, what_about_physiology, NO_TALK_ABOUT_SELF, what_about_powers, NOT_POWERS_BUT_FLOWERS, yes_flowers, GOOD_HUMAN, wish_to_go_now, EXCELLENT_IDEA, what_about_your_history, ABOUT_HISTORY, sentient_milieu, ABOUT_SENTIENT_MILIEU, what_about_war, ABOUT_WAR, enough_info, OK_ENOUGH_INFO, UMGAH_ALL_GONE, HELLO_AFTER_COMPEL_URQUAN, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/talkpet/igfxres.h0000600000175000017500000000005410543202026020017 0ustar joeyjoey#define TALKING_PET_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/talkpet/talkpet.res0000600000175000017500000000047510543202026020365 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/talkpet PACKAGE TALKING_PET_PACKAGE talkpet.con GFXRES TALKING_PET_PMAP_ANIM talkpet.ani FONTRES TALKING_PET_FONT talkpet.fon MUSICRES TALKING_PET_MUSIC talkpet.mod STRTAB TALKING_PET_CONVERSATION_PHRASES talkpet.txt STRTAB TALKING_PET_COLOR_MAP talkpet.ct uqm-0.6.2/sc2/src/sc2code/comm/talkpet/istrtab.h0000600000175000017500000000014110543202026020015 0ustar joeyjoey#define TALKING_PET_CONVERSATION_PHRASES 0x00200004L #define TALKING_PET_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/talkpet/imusicre.h0000600000175000017500000000005010543202026020164 0ustar joeyjoey#define TALKING_PET_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/talkpet/talkpet.c0000600000175000017500000004366410543202026020025 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/talkpet/resinst.h" #include "comm/talkpet/strings.h" #include "build.h" static LOCDATA talkpet_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)TALKING_PET_PMAP_ANIM, /* AlienFrame */ (FONT)TALKING_PET_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)TALKING_PET_COLOR_MAP, /* AlienColorMap */ TALKING_PET_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ TALKING_PET_CONVERSATION_PHRASES, /* PlayerPhrases */ 16, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 7, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 10, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 13, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 16, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 18, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 13) /* BlockMask */ }, { 21, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 12) | (1 << 14), /* BlockMask */ }, { 24, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 26, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 28, /* StartIndex */ 4, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 32, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 35, /* StartIndex */ 5, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 40, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 42, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 5), /* BlockMask */ }, { 48, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 4), /* BlockMask */ }, { 50, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 5), /* BlockMask */ }, { 52, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 6, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; #define STROBE_RATE 15 #define STROBE_LENGTH (ONE_SECOND * 3 / 2) #define NUM_STROBES (STROBE_LENGTH * STROBE_RATE / ONE_SECOND) static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 0); SET_GAME_STATE (SHIP_TO_COMPEL, 0); if (PLAYER_SAID (R, compel_urquan)) { NPCPhrase (HERE_WE_GO); SET_GAME_STATE (URQUAN_MESSED_UP, 1); } else if (PLAYER_SAID (R, wish_to_go_now)) NPCPhrase (EXCELLENT_IDEA); else if (PLAYER_SAID (R, bye_onboard)) NPCPhrase (GOODBYE_ONBOARD); else if (PLAYER_SAID (R, compel_that_ship)) NPCPhrase (SAVING_MY_POWER); else if (PLAYER_SAID (R, ok_lets_do_it) || PLAYER_SAID (R, want_kill_1) || PLAYER_SAID (R, want_kill_2) || PLAYER_SAID (R, want_kill_3)) { if (PLAYER_SAID (R, ok_lets_do_it)) NPCPhrase (COMING_ABOARD); else NPCPhrase (GLAD_YOU_WONT_KILL); SET_GAME_STATE (TALKING_PET, 1); SET_GAME_STATE (TALKING_PET_ON_SHIP, 1); SET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES, 0); SET_GAME_STATE (UMGAH_VISITS, 0); SET_GAME_STATE (UMGAH_HOME_VISITS, 0); SET_GAME_STATE (ARILOU_STACK_2, 0); } } static void MindFuckUrquan (RESPONSE_REF R) { if (PLAYER_SAID (R, what_now)) { NPCPhrase (DO_THIS); DISABLE_PHRASE (what_now); } else if (PLAYER_SAID (R, im_scared)) { NPCPhrase (STUPID_FOP); DISABLE_PHRASE (im_scared); } if (PHRASE_ENABLED (what_now)) Response (what_now, MindFuckUrquan); if (PHRASE_ENABLED (im_scared)) Response (im_scared, MindFuckUrquan); Response (compel_urquan, ExitConversation); } static void PetDevice (RESPONSE_REF R); static void MindControlStrobe (void) { BYTE i; for (i = 0; i < NUM_STROBES; ++i) { XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 1) ), 0); SleepThread (ONE_SECOND / (STROBE_RATE * 2)); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 0) ), 0); SleepThread (ONE_SECOND / (STROBE_RATE * 2)); } } static void MindControl (RESPONSE_REF R) { RESPONSE_FUNC RespFunc; if (PLAYER_SAID (R, what_about_powers)) { NPCPhrase (NOT_POWERS_BUT_FLOWERS); RespFunc = (RESPONSE_FUNC)MindControl; R = yes_flowers; } else /* if (R == yes_flowers) */ { NPCPhrase (GOOD_HUMAN); RespFunc = (RESPONSE_FUNC)ExitConversation; R = wish_to_go_now; } AlienTalkSegue ((COUNT)~0); MindControlStrobe (); Response (R, RespFunc); } static void PetInfo (RESPONSE_REF R) { if (PLAYER_SAID (R, about_your_race)) NPCPhrase (WHAT_ABOUT_RACE); else if (PLAYER_SAID (R, what_about_physiology)) { NPCPhrase (NO_TALK_ABOUT_SELF); DISABLE_PHRASE (what_about_physiology); } else if (PLAYER_SAID (R, what_about_your_history)) { NPCPhrase (ABOUT_HISTORY); DISABLE_PHRASE (what_about_your_history); } else if (PLAYER_SAID (R, sentient_milieu)) { NPCPhrase (ABOUT_SENTIENT_MILIEU); DISABLE_PHRASE (sentient_milieu); } else if (PLAYER_SAID (R, what_about_war)) { NPCPhrase (ABOUT_WAR); DISABLE_PHRASE (what_about_war); } if (PHRASE_ENABLED (what_about_physiology)) { Response (what_about_physiology, PetInfo); } else { Response (what_about_powers, MindControl); } if (PHRASE_ENABLED (what_about_your_history)) Response (what_about_your_history, PetInfo); else if (PHRASE_ENABLED (sentient_milieu)) Response (sentient_milieu, PetInfo); else if (PHRASE_ENABLED (what_about_war)) Response (what_about_war, PetInfo); Response (enough_info, PetDevice); } static void PetDevice (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, whats_up_onboard)) { NumVisits = GET_GAME_STATE (TALKING_PET_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_ONBOARD_1); break; case 1: NPCPhrase (GENERAL_INFO_ONBOARD_2); break; case 2: NPCPhrase (GENERAL_INFO_ONBOARD_3); break; case 3: NPCPhrase (GENERAL_INFO_ONBOARD_4); break; case 4: NPCPhrase (GENERAL_INFO_ONBOARD_5); break; case 5: NPCPhrase (GENERAL_INFO_ONBOARD_6); break; case 6: NPCPhrase (GENERAL_INFO_ONBOARD_7); break; case 7: NPCPhrase (GENERAL_INFO_ONBOARD_8); --NumVisits; break; } SET_GAME_STATE (TALKING_PET_INFO, NumVisits); DISABLE_PHRASE (whats_up_onboard); } else if (PLAYER_SAID (R, any_suggestions)) { NumVisits = GET_GAME_STATE (TALKING_PET_SUGGESTIONS); switch (NumVisits++) { case 0: NPCPhrase (SUGGESTION_1); break; case 1: NPCPhrase (SUGGESTION_2); break; case 2: NPCPhrase (SUGGESTION_3); break; case 3: NPCPhrase (SUGGESTION_4); break; case 4: NPCPhrase (SUGGESTION_5); break; case 5: NPCPhrase (SUGGESTION_6); break; case 6: NPCPhrase (SUGGESTION_7); break; case 7: NPCPhrase (SUGGESTION_8); --NumVisits; break; } SET_GAME_STATE (TALKING_PET_SUGGESTIONS, NumVisits); DISABLE_PHRASE (any_suggestions); } else if (PLAYER_SAID (R, enough_info)) NPCPhrase (OK_ENOUGH_INFO); else if (PLAYER_SAID (R, you_lied)) { NPCPhrase (SO_WHAT); SET_GAME_STATE (DNYARRI_LIED, 0); } if (GET_GAME_STATE (SHIP_TO_COMPEL)) { Response (compel_that_ship, ExitConversation); } if (PHRASE_ENABLED (whats_up_onboard)) Response (whats_up_onboard, PetDevice); if (PHRASE_ENABLED (any_suggestions)) Response (any_suggestions, PetDevice); Response (about_your_race, PetInfo); if (GET_GAME_STATE (DNYARRI_LIED) && GET_GAME_STATE (LEARNED_TALKING_PET)) Response (you_lied, PetDevice); Response (bye_onboard, ExitConversation); } static void CompelPlayer (RESPONSE_REF R) { BYTE i, LastStack; RESPONSE_REF pStr[3]; LastStack = 0; pStr[0] = pStr[1] = pStr[2] = 0; if (PLAYER_SAID (R, what_are_you)) { NPCPhrase (JUST_TALKING_PET); DISABLE_PHRASE (what_are_you); } else if (PLAYER_SAID (R, what_do_to_umgah)) { NPCPhrase (DID_NOTHING); DISABLE_PHRASE (what_do_to_umgah); LastStack = 1; } else if (PLAYER_SAID (R, we_are_vindicator0)) { NPCPhrase (GOOD_FOR_YOU); DISABLE_PHRASE (we_are_vindicator0); LastStack = 2; } else if (R != 0) { if (PLAYER_SAID (R, bye_at_umgah)) NPCPhrase (GOODBYE_AT_UMGAH); else if (PLAYER_SAID (R, must_explain_presence)) NPCPhrase (EXPLAIN_NOTHING_MONKEY_BOY); else if (PLAYER_SAID (R, umgah_zombies)) NPCPhrase (WORKS_LIKE_THIS); else if (PLAYER_SAID (R, talking_pets_dumb)) NPCPhrase (OH_NO_YOU_DONT); SET_GAME_STATE (KNOW_UMGAH_ZOMBIES, 1); if (!GET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP)) { SET_GAME_STATE (PLAYER_HYPNOTIZED, 1); } else { NPCPhrase (CANT_COMPEL); SET_GAME_STATE (BATTLE_SEGUE, 1); } return; } if (PHRASE_ENABLED (what_are_you)) pStr[0] = what_are_you; else pStr[0] = talking_pets_dumb; if (GET_GAME_STATE (KNOW_UMGAH_ZOMBIES)) { if (PHRASE_ENABLED (what_do_to_umgah)) pStr[1] = what_do_to_umgah; else pStr[1] = umgah_zombies; } if (PHRASE_ENABLED (we_are_vindicator0)) { construct_response ( shared_phrase_buf, we_are_vindicator0, GLOBAL_SIS (ShipName), we_are_vindicator1, NULL_PTR ); pStr[2] = we_are_vindicator0; } else pStr[2] = must_explain_presence; if (pStr[LastStack]) { if (pStr[LastStack] != we_are_vindicator0) Response (pStr[LastStack], CompelPlayer); else DoResponsePhrase (pStr[LastStack], CompelPlayer, shared_phrase_buf); } for (i = 0; i < 3; ++i) { if (i != LastStack && pStr[i]) { if (pStr[i] != we_are_vindicator0) Response (pStr[i], CompelPlayer); else DoResponsePhrase (pStr[i], CompelPlayer, shared_phrase_buf); } } Response (bye_at_umgah, CompelPlayer); } static void PetDeal (RESPONSE_REF R); static void KillPet (RESPONSE_REF R) { if (PLAYER_SAID (R, must_kill)) { NPCPhrase (DONT_KILL); AlienTalkSegue ((COUNT)~0); MindControlStrobe (); } Response (want_kill_1, ExitConversation); Response (want_kill_2, ExitConversation); Response (want_kill_3, ExitConversation); } static void PetDeal (RESPONSE_REF R) { if (PLAYER_SAID (R, what_kind_of_deal)) { NPCPhrase (HELP_DEFEAT_URQUAN); DISABLE_PHRASE (what_kind_of_deal); } else if (PLAYER_SAID (R, how_trust)) { NPCPhrase (TRUST); DISABLE_PHRASE (how_trust); } else if (PLAYER_SAID (R, boneless_dweeb)) { NPCPhrase (YOUR_BONELESS_DWEEB); DISABLE_PHRASE (boneless_dweeb); } else if (PLAYER_SAID (R, what_are_you_really)) { NPCPhrase (POOR_DNYARRI); DISABLE_PHRASE (what_are_you_really); } else if (PLAYER_SAID (R, hard_to_believe)) { NPCPhrase (ITS_TRUE); SET_GAME_STATE (DNYARRI_LIED, 1); DISABLE_PHRASE (hard_to_believe); } else if (PLAYER_SAID (R, bullshit)) { NPCPhrase (WORTH_A_TRY); DISABLE_PHRASE (bullshit); } else if (PLAYER_SAID (R, kill_you)) { NPCPhrase (PLEASE_DONT); DISABLE_PHRASE (kill_you); } if (PHRASE_ENABLED (what_kind_of_deal)) Response (what_kind_of_deal, PetDeal); else { if (PHRASE_ENABLED (how_trust)) Response (how_trust, PetDeal); else if (PHRASE_ENABLED (boneless_dweeb)) Response (boneless_dweeb, PetDeal); Response (ok_lets_do_it, ExitConversation); } if (PHRASE_ENABLED (what_are_you_really)) Response (what_are_you_really, PetDeal); else { if (PHRASE_ENABLED (hard_to_believe) && !GET_GAME_STATE (LEARNED_TALKING_PET)) Response (hard_to_believe, PetDeal); else if (PHRASE_ENABLED (bullshit) && GET_GAME_STATE (LEARNED_TALKING_PET)) Response (bullshit, PetDeal); } if (PHRASE_ENABLED (kill_you)) Response (kill_you, PetDeal); else if (PHRASE_ENABLED (must_kill)) { Response (must_kill, KillPet); } } static void Intro (void) { BYTE NumVisits; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) { SET_GAME_STATE (SHIP_TO_COMPEL, 0); SET_GAME_STATE (BATTLE_SEGUE, 1); if (!(GLOBAL (glob_flags) & CYBORG_ENABLED)) { NPCPhrase (HUMAN_PEP_TALK); } else { NPCPhrase (CYBORG_PEP_TALK); } } else if (GET_GAME_STATE (READY_TO_CONFUSE_URQUAN)) { SET_GAME_STATE (SHIP_TO_COMPEL, 0); SET_GAME_STATE (READY_TO_CONFUSE_URQUAN, 0); SET_GAME_STATE (AWARE_OF_SAMATRA, 1); if (GET_GAME_STATE (CHMMR_BOMB_STATE) != 3) { NPCPhrase (HAVENT_GOT_EVERYTHING); if (!GET_GAME_STATE (UTWIG_BOMB_ON_SHIP)) NPCPhrase (NEED_BOMB); else NPCPhrase (SOUP_UP_BOMB); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (GET_GAME_STATE (URQUAN_MESSED_UP)) { NPCPhrase (HELLO_AFTER_COMPEL_URQUAN); SET_GAME_STATE (BATTLE_SEGUE, 0); } else { NPCPhrase (I_SENSE_MY_SLAVES); MindFuckUrquan ((RESPONSE_REF)0); } } else if (GET_GAME_STATE (TALKING_PET_ON_SHIP)) { NumVisits = GET_GAME_STATE (TALKING_PET_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_AS_DEVICE_1); break; case 1: NPCPhrase (HELLO_AS_DEVICE_2); break; case 2: NPCPhrase (HELLO_AS_DEVICE_3); break; case 3: NPCPhrase (HELLO_AS_DEVICE_4); break; case 4: NPCPhrase (HELLO_AS_DEVICE_5); break; case 5: NPCPhrase (HELLO_AS_DEVICE_6); break; case 6: NPCPhrase (HELLO_AS_DEVICE_7); break; case 7: NPCPhrase (HELLO_AS_DEVICE_8); --NumVisits; break; } SET_GAME_STATE (TALKING_PET_VISITS, NumVisits); PetDevice ((RESPONSE_REF)0); } else if (GetHeadLink (&GLOBAL (npc_built_ship_q))) { NumVisits = GET_GAME_STATE (TALKING_PET_HOME_VISITS); switch (NumVisits++) { case 0: SET_GAME_STATE (UMGAH_VISITS, 0); NPCPhrase (HELLO_AT_UMGAH); break; case 1: NPCPhrase (HYPNOTIZE_AGAIN_1); break; case 2: NPCPhrase (HYPNOTIZE_AGAIN_2); break; case 3: NPCPhrase (HYPNOTIZE_AGAIN_3); break; case 4: NPCPhrase (HYPNOTIZE_AGAIN_4); --NumVisits; break; } SET_GAME_STATE (TALKING_PET_HOME_VISITS, NumVisits); if (NumVisits == 1) { CompelPlayer ((RESPONSE_REF)0); } else if (!GET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP)) { SET_GAME_STATE (PLAYER_HYPNOTIZED, 1); SET_GAME_STATE (BATTLE_SEGUE, 0); } else { NPCPhrase (CANT_COMPEL); SET_GAME_STATE (BATTLE_SEGUE, 1); } } else { if (ActivateStarShip (UMGAH_SHIP, SPHERE_TRACKING)) NPCPhrase (LETS_MAKE_A_DEAL); else NPCPhrase (UMGAH_ALL_GONE); PetDeal ((RESPONSE_REF)0); } } static COUNT uninit_talkpet (void) { return (0); } static void post_talkpet_enc (void) { // nothing defined so far } LOCDATAPTR init_talkpet_comm (void) { LOCDATAPTR retval; talkpet_desc.init_encounter_func = Intro; talkpet_desc.post_encounter_func = post_talkpet_enc; talkpet_desc.uninit_encounter_func = uninit_talkpet; talkpet_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); talkpet_desc.AlienTextBaseline.y = 0; talkpet_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if (LOBYTE (GLOBAL (CurrentActivity)) != IN_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &talkpet_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/talkpet/Makeinfo0000600000175000017500000000002710543202026017653 0ustar joeyjoeyuqm_CFILES="talkpet.c" uqm-0.6.2/sc2/src/sc2code/comm/talkpet/respkg.h0000600000175000017500000000004410543202026017642 0ustar joeyjoeyenum { TALKING_PET_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/talkpet/resinst.h0000600000175000017500000000012610543202026020037 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/pkunk/0000755000175000017500000000000010552600275015704 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/pkunk/pkunk.res0000600000175000017500000000034710543202023017530 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/pkunk PACKAGE PKUNK_PACKAGE pkunk.con GFXRES PKUNK_PMAP_ANIM pkunk.ani FONTRES PKUNK_FONT pkunk.fon MUSICRES PKUNK_MUSIC pkunk.mod STRTAB PKUNK_CONVERSATION_PHRASES pkunk.txt uqm-0.6.2/sc2/src/sc2code/comm/pkunk/ifontres.h0000600000175000017500000000004110543202023017656 0ustar joeyjoey#define PKUNK_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/pkunk/restypes.h0000600000175000017500000000024110543202023017705 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/pkunk/strings.h0000600000175000017500000001040710543202023017525 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, GIVE_SPINDLE, name_1, name_2, name_3, name_40, name_41, NEUTRAL_SPACE_HELLO_1, NEUTRAL_SPACE_HELLO_3, NEUTRAL_SPACE_HELLO_2, NEUTRAL_SPACE_HELLO_4, FRIENDLY_SPACE_HELLO_1, FRIENDLY_SPACE_HELLO_2, FRIENDLY_SPACE_HELLO_3, FRIENDLY_SPACE_HELLO_4, FRIENDLY_SPACE_HELLO_5, FRIENDLY_SPACE_HELLO_6, FRIENDLY_SPACE_HELLO_7, FRIENDLY_SPACE_HELLO_8, NEUTRAL_HOMEWORLD_HELLO_1, NEUTRAL_HOMEWORLD_HELLO_2, NEUTRAL_HOMEWORLD_HELLO_3, NEUTRAL_HOMEWORLD_HELLO_4, FRIENDLY_HOMEWORLD_HELLO_1, FRIENDLY_HOMEWORLD_HELLO_2, FRIENDLY_HOMEWORLD_HELLO_3, FRIENDLY_HOMEWORLD_HELLO_4, FRIENDLY_HOMEWORLD_HELLO_5, FRIENDLY_HOMEWORLD_HELLO_6, FRIENDLY_HOMEWORLD_HELLO_7, FRIENDLY_HOMEWORLD_HELLO_8, whats_up_neutral, GENERAL_INFO_NEUTRAL_1, GENERAL_INFO_NEUTRAL_2, GENERAL_INFO_NEUTRAL_3, GENERAL_INFO_NEUTRAL_4, good_reason_1, WE_GO_HOME_1, good_reason_2, WE_GO_HOME_2, bad_reason_1, NO_GO_HOME_1, bad_reason_2, NO_GO_HOME_2, SENSE_KOHRAH_VICTORY, SPIRITUAL_PROBLEMS_1, SPIRITUAL_PROBLEMS_2, SPIRITUAL_PROBLEMS_3, SPIRITUAL_PROBLEMS_4, HATE_YOU_FOREVER_1, HATE_YOU_FOREVER_2, HATE_YOU_FOREVER_3, HATE_YOU_FOREVER_4, MIGRATING_SPACE_1, MIGRATING_SPACE_2, MIGRATING_SPACE_3, MIGRATING_SPACE_4, MIGRATING_SPACE_5, MIGRATING_SPACE_6, MIGRATING_SPACE_7, MIGRATING_SPACE_8, die_idiot_fools, VERY_WELL, why_insults, RELEASE_TENSION, what_about_you_angry, ABOUT_US_ANGRY, what_about_you, should_be_friends, YES_FRIENDS, try_to_be_nicer, CANT_ASK_FOR_MORE, VISIT_OUR_HOMEWORLD, CAN_BE_FRIENDS, bye_angry, GOODBYE_ANGRY, we_conquer, WHY_CONQUER, conquer_because_1, #if 0 NOT_CONQUER_10, NOT_CONQUER_11, NOT_CONQUER_12, #endif NOT_CONQUER_1, conquer_because_2, NOT_CONQUER_2, must_conquer, BAD_IDEA, no_conquest, GOOD_IDEA, we_are_vindicator0, we_are_vindicator1, we_are_vindicator2, WHY_YOU_HERE, we_here_to_help, NEED_HELP, we_need_help, GIVE_HELP, exploring_universe, SENSE_DEEPER_CONFLICT, fun_cruise, REPRESS, why_ilwrath_fight, ILWRATH_FIGHT_BECAUSE, when_fight_start, FIGHT_START_WHEN, how_goes_fight, FIGHT_GOES, how_goes_war, WAR_GOES_1, WAR_GOES_2, WAR_GOES_3, WAR_GOES_4, how_stop_fight, STOP_FIGHT_LIKE_SO, enough_ilwrath, OK_ENOUGH_ILWRATH, what_about_history, ABOUT_HISTORY, what_about_yehat, ABOUT_YEHAT, what_about_culture, ABOUT_CULTURE, elaborate_culture, OK_ELABORATE_CULTURE, what_about_future, ABOUT_FUTURE, enough_about_you, OK_ENOUGH_ABOUT_US, ABOUT_US, where_fleet_1, where_fleet_2, where_fleet_3, MIGRATING_HOMEWORLD_1, MIGRATING_HOMEWORLD_2, MIGRATING_HOMEWORLD_3, RETURNING_FROM_YEHAT_1, RETURNING_FROM_YEHAT_2, am_worried_1, am_worried_2, am_worried_3, DONT_WORRY_1, DONT_WORRY_2, DONT_WORRY_3, form_alliance, GO_TO_HOMEWORLD, can_you_help, GO_TO_HOMEWORLD_AGAIN, hostile_greeting, DONT_BE_HOSTILE, obey, NO_OBEY, neutral_bye_space, NEUTRAL_GOODBYE_SPACE, SHIP_GIFT, NO_ROOM, friendly_bye_space, FRIENDLY_GOODBYE_SPACE, bye_friendly, GOODBYE_FRIENDLY, ALMOST_ALLIANCE, INIT_NO_ROOM, INIT_SHIP_GIFT, suit_yourself, GOODBYE_MIGRATION, what_about_ilwrath, ABOUT_ILWRATH, whats_up_space, SHIPS_AT_HOME, GENERAL_INFO_SPACE_1, GENERAL_INFO_SPACE_2, GENERAL_INFO_SPACE_3, GENERAL_INFO_SPACE_4, GENERAL_INFO_SPACE_5, GENERAL_INFO_SPACE_6, GENERAL_INFO_SPACE_7, GENERAL_INFO_SPACE_8, tell_my_fortune, FORTUNE_IS_1, FORTUNE_IS_2, FORTUNE_IS_3, FORTUNE_IS_4, FORTUNE_IS_5, FORTUNE_IS_6, FORTUNE_IS_7, FORTUNE_IS_8, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/pkunk/igfxres.h0000600000175000017500000000004610543202023017501 0ustar joeyjoey#define PKUNK_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/pkunk/istrtab.h0000600000175000017500000000012410543202023017477 0ustar joeyjoey#define PKUNK_CONVERSATION_PHRASES 0x00200004L #define PKUNK_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/pkunk/imusicre.h0000600000175000017500000000004210543202023017646 0ustar joeyjoey#define PKUNK_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/pkunk/Makeinfo0000600000175000017500000000002610543202023017333 0ustar joeyjoeyuqm_CFILES="pkunkc.c" uqm-0.6.2/sc2/src/sc2code/comm/pkunk/pkunkc.c0000600000175000017500000006126310543202023017330 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/pkunk/resinst.h" #include "comm/pkunk/strings.h" #include "build.h" #include "gameev.h" static LOCDATA pkunk_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)PKUNK_PMAP_ANIM, /* AlienFrame */ (FONT)PKUNK_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)PKUNK_COLOR_MAP, /* AlienColorMap */ PKUNK_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ PKUNK_CONVERSATION_PHRASES, /* PlayerPhrases */ 3, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 3, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 7, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 2), /* BlockMask */ }, { 11, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 1), /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 2, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 6, /* FrameRate */ ONE_SECOND / 12, ONE_SECOND / 2, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static BOOLEAN ShipsReady (void) { SIZE i; return (GET_GAME_STATE (PKUNK_MANNER) == 3 && !((i = (GLOBAL (GameClock.year_index) - START_YEAR) - GET_GAME_STATE (PKUNK_SHIP_YEAR)) < 0 || ((i == 0 && (i = GLOBAL (GameClock.month_index) - GET_GAME_STATE (PKUNK_SHIP_MONTH)) < 0) || (i == 0 && GLOBAL (GameClock.day_index) < GET_GAME_STATE (PKUNK_SHIP_DAY))))); } static void PrepareShip (void) { #define MAX_PKUNK_SHIPS 4 if (ActivateStarShip (PKUNK_SHIP, MAX_PKUNK_SHIPS)) { BYTE mi, di, yi; mi = GLOBAL (GameClock.month_index); SET_GAME_STATE (PKUNK_SHIP_MONTH, mi); if ((di = GLOBAL (GameClock.day_index)) > 28) di = 28; SET_GAME_STATE (PKUNK_SHIP_DAY, di); yi = (BYTE)(GLOBAL (GameClock.year_index) - START_YEAR) + 1; SET_GAME_STATE (PKUNK_SHIP_YEAR, yi); } } #define GOOD_REASON_1 (1 << 0) #define GOOD_REASON_2 (1 << 1) #define BAD_REASON_1 (1 << 2) #define BAD_REASON_2 (1 << 3) static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (PLAYER_SAID (R, friendly_bye_space)) NPCPhrase (FRIENDLY_GOODBYE_SPACE); else if (PLAYER_SAID (R, neutral_bye_space)) NPCPhrase (NEUTRAL_GOODBYE_SPACE); else if (PLAYER_SAID (R, bye_angry)) NPCPhrase (GOODBYE_ANGRY); else if (PLAYER_SAID (R, bye_friendly)) NPCPhrase (GOODBYE_FRIENDLY); else if (PLAYER_SAID (R, we_here_to_help) || PLAYER_SAID (R, we_need_help)) { if (PLAYER_SAID (R, we_here_to_help)) NPCPhrase (NEED_HELP); else NPCPhrase (GIVE_HELP); NPCPhrase (ALMOST_ALLIANCE); SET_GAME_STATE (PKUNK_MANNER, 3); SET_GAME_STATE (PKUNK_VISITS, 0); SET_GAME_STATE (PKUNK_HOME_VISITS, 0); SET_GAME_STATE (PKUNK_INFO, 0); AddEvent (RELATIVE_EVENT, 6, 0, 0, ADVANCE_PKUNK_MISSION); if (ActivateStarShip (PKUNK_SHIP, FEASIBILITY_STUDY) == 0) NPCPhrase (INIT_NO_ROOM); else { NPCPhrase (INIT_SHIP_GIFT); AlienTalkSegue ((COUNT)~0); PrepareShip (); } } else if (PLAYER_SAID (R, try_to_be_nicer)) { NPCPhrase (CANT_ASK_FOR_MORE); NPCPhrase (VISIT_OUR_HOMEWORLD); SET_GAME_STATE (PKUNK_MANNER, 3); SET_GAME_STATE (PKUNK_VISITS, 0); SET_GAME_STATE (PKUNK_HOME_VISITS, 0); SET_GAME_STATE (PKUNK_INFO, 0); } else if (PLAYER_SAID (R, must_conquer) || PLAYER_SAID (R, obey)) { if (PLAYER_SAID (R, obey)) NPCPhrase (NO_OBEY); else { NPCPhrase (BAD_IDEA); SET_GAME_STATE (PKUNK_MANNER, 2); } SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, die_idiot_fools)) { NPCPhrase (VERY_WELL); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, suit_yourself)) NPCPhrase (GOODBYE_MIGRATION); else { BYTE ReasonMask; ReasonMask = GET_GAME_STATE (PKUNK_REASONS); if (PLAYER_SAID (R, good_reason_1)) { NPCPhrase (WE_GO_HOME_1); ReasonMask |= GOOD_REASON_1; AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_PKUNK_MISSION); } else if (PLAYER_SAID (R, good_reason_2)) { NPCPhrase (WE_GO_HOME_2); ReasonMask |= GOOD_REASON_2; AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_PKUNK_MISSION); } else if (PLAYER_SAID (R, bad_reason_1)) { NPCPhrase (NO_GO_HOME_1); ReasonMask |= BAD_REASON_1; } else if (PLAYER_SAID (R, bad_reason_2)) { NPCPhrase (NO_GO_HOME_2); ReasonMask |= BAD_REASON_2; } SET_GAME_STATE (PKUNK_REASONS, ReasonMask); } } static void PkunkHome (RESPONSE_REF R); static void PkunkAngry (RESPONSE_REF R) { if (PLAYER_SAID (R, why_insults)) { NPCPhrase (RELEASE_TENSION); DISABLE_PHRASE (why_insults); } else if (PLAYER_SAID (R, what_about_you)) { NPCPhrase (ABOUT_US); DISABLE_PHRASE (what_about_you); } else if (PLAYER_SAID (R, should_be_friends)) { NPCPhrase (YES_FRIENDS); DISABLE_PHRASE (should_be_friends); } if (PHRASE_ENABLED (should_be_friends)) { Response (should_be_friends, PkunkAngry); } else { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) Response (try_to_be_nicer, PkunkHome); else Response (try_to_be_nicer, ExitConversation); } Response (die_idiot_fools, ExitConversation); if (PHRASE_ENABLED (why_insults)) Response (why_insults, PkunkAngry); if (PHRASE_ENABLED (what_about_you)) Response (what_about_you, PkunkAngry); Response (bye_angry, ExitConversation); } static void DiscussConquer (RESPONSE_REF R) { if (PLAYER_SAID (R, we_conquer)) { NPCPhrase (WHY_CONQUER); DISABLE_PHRASE (we_conquer); } else if (PLAYER_SAID (R, conquer_because_1)) { #if 0 NPCPhrase (NOT_CONQUER_10); NPCPhrase (GLOBAL_ALLIANCE_NAME + name_1); NPCPhrase (NOT_CONQUER_11); NPCPhrase (GLOBAL_ALLIANCE_NAME + name_1); NPCPhrase (NOT_CONQUER_12); #endif NPCPhrase (NOT_CONQUER_1); DISABLE_PHRASE (conquer_because_1); } else if (PLAYER_SAID (R, conquer_because_2)) { NPCPhrase (NOT_CONQUER_2); DISABLE_PHRASE (conquer_because_2); } if (PHRASE_ENABLED (conquer_because_1)) { #if 0 UNICODE buf[ALLIANCE_NAME_BUFSIZE]; GetAllianceName (buf, name_1); construct_response ( shared_phrase_buf, conquer_because_1, buf, (RESPONSE_REF)-1 ); DoResponsePhrase (conquer_because_1, DiscussConquer, shared_phrase_buf); #endif Response(conquer_because_1, DiscussConquer); } if (PHRASE_ENABLED (conquer_because_2)) Response (conquer_because_2, DiscussConquer); Response (must_conquer, ExitConversation); Response (no_conquest, PkunkHome); } static void OfferAlliance (RESPONSE_REF R) { if (PLAYER_SAID (R, we_are_vindicator0)) NPCPhrase (WHY_YOU_HERE); else if (PLAYER_SAID (R, exploring_universe)) { NPCPhrase (SENSE_DEEPER_CONFLICT); DISABLE_PHRASE (exploring_universe); } else if (PLAYER_SAID (R, fun_cruise)) { NPCPhrase (REPRESS); DISABLE_PHRASE (fun_cruise); } Response (we_here_to_help, ExitConversation); Response (we_need_help, ExitConversation); if (PHRASE_ENABLED (exploring_universe)) Response (exploring_universe, OfferAlliance); if (PHRASE_ENABLED (fun_cruise)) Response (fun_cruise, OfferAlliance); } static void AboutPkunk (RESPONSE_REF R) { BYTE InfoLeft; InfoLeft = FALSE; if (PLAYER_SAID (R, what_about_you)) NPCPhrase (ABOUT_US); else if (PLAYER_SAID (R, what_about_history)) { NPCPhrase (ABOUT_HISTORY); DISABLE_PHRASE (what_about_history); } else if (PLAYER_SAID (R, what_about_yehat)) { NPCPhrase (ABOUT_YEHAT); DISABLE_PHRASE (what_about_yehat); } else if (PLAYER_SAID (R, what_about_culture)) { NPCPhrase (ABOUT_CULTURE); DISABLE_PHRASE (what_about_culture); } else if (PLAYER_SAID (R, elaborate_culture)) { NPCPhrase (OK_ELABORATE_CULTURE); DISABLE_PHRASE (elaborate_culture); } else if (PLAYER_SAID (R, what_about_future)) { NPCPhrase (ABOUT_FUTURE); DISABLE_PHRASE (what_about_future); } if (PHRASE_ENABLED (what_about_history)) { Response (what_about_history, AboutPkunk); InfoLeft = TRUE; } else if (PHRASE_ENABLED (what_about_yehat)) { Response (what_about_yehat, AboutPkunk); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_culture)) { Response (what_about_culture, AboutPkunk); InfoLeft = TRUE; } else if (PHRASE_ENABLED (elaborate_culture)) { Response (elaborate_culture, AboutPkunk); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_future)) { Response (what_about_future, AboutPkunk); InfoLeft = TRUE; } Response (enough_about_you, PkunkHome); if (!InfoLeft) { DISABLE_PHRASE (what_about_you); } } static void AboutIlwrath (RESPONSE_REF R) { BYTE InfoLeft; InfoLeft = FALSE; if (PLAYER_SAID (R, what_about_ilwrath)) NPCPhrase (ABOUT_ILWRATH); else if (PLAYER_SAID (R, why_ilwrath_fight)) { NPCPhrase (ILWRATH_FIGHT_BECAUSE); DISABLE_PHRASE (why_ilwrath_fight); } else if (PLAYER_SAID (R, when_fight_start)) { NPCPhrase (FIGHT_START_WHEN); DISABLE_PHRASE (when_fight_start); } else if (PLAYER_SAID (R, how_goes_fight)) { NPCPhrase (FIGHT_GOES); DISABLE_PHRASE (how_goes_fight); } else if (PLAYER_SAID (R, how_stop_fight)) { NPCPhrase (STOP_FIGHT_LIKE_SO); DISABLE_PHRASE (how_stop_fight); } if (PHRASE_ENABLED (why_ilwrath_fight)) { Response (why_ilwrath_fight, AboutIlwrath); InfoLeft = TRUE; } if (PHRASE_ENABLED (when_fight_start)) { Response (when_fight_start, AboutIlwrath); InfoLeft = TRUE; } if (PHRASE_ENABLED (how_goes_fight)) { Response (how_goes_fight, AboutIlwrath); InfoLeft = TRUE; } if (PHRASE_ENABLED (how_stop_fight)) { Response (how_stop_fight, AboutIlwrath); InfoLeft = TRUE; } Response (enough_ilwrath, PkunkHome); if (!InfoLeft) { DISABLE_PHRASE (what_about_ilwrath); } } static void PkunkHome (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, no_conquest)) NPCPhrase (GOOD_IDEA); else if (PLAYER_SAID (R, enough_ilwrath)) NPCPhrase (OK_ENOUGH_ILWRATH); else if (PLAYER_SAID (R, enough_about_you)) NPCPhrase (OK_ENOUGH_ABOUT_US); else if (PLAYER_SAID (R, where_fleet_1) || PLAYER_SAID (R, where_fleet_2) || PLAYER_SAID (R, where_fleet_3)) { SET_GAME_STATE (PKUNK_SWITCH, 1); if (!(GET_GAME_STATE (PKUNK_MISSION) & 1)) { NumVisits = GET_GAME_STATE (PKUNK_RETURN); switch (NumVisits++) { case 0: NPCPhrase (RETURNING_FROM_YEHAT_1); break; case 1: NPCPhrase (RETURNING_FROM_YEHAT_2); --NumVisits; break; } SET_GAME_STATE (PKUNK_RETURN, NumVisits); } else { NumVisits = GET_GAME_STATE (PKUNK_MIGRATE); switch (NumVisits++) { case 0: NPCPhrase (MIGRATING_HOMEWORLD_1); break; case 1: NPCPhrase (MIGRATING_HOMEWORLD_2); break; case 2: NPCPhrase (MIGRATING_HOMEWORLD_3); --NumVisits; break; } SET_GAME_STATE (PKUNK_MIGRATE, NumVisits); } NumVisits = GET_GAME_STATE (PKUNK_FLEET) + 1; SET_GAME_STATE (PKUNK_FLEET, NumVisits); DISABLE_PHRASE (where_fleet_1); } else if (PLAYER_SAID (R, am_worried_1) || PLAYER_SAID (R, am_worried_2) || PLAYER_SAID (R, am_worried_3)) { NumVisits = GET_GAME_STATE (PKUNK_WORRY); switch (NumVisits++) { case 0: NPCPhrase (DONT_WORRY_1); break; case 1: NPCPhrase (DONT_WORRY_2); break; case 2: NPCPhrase (DONT_WORRY_3); --NumVisits; break; } SET_GAME_STATE (PKUNK_WORRY, NumVisits); DISABLE_PHRASE (am_worried_1); } else if (PLAYER_SAID (R, try_to_be_nicer)) { NPCPhrase (CANT_ASK_FOR_MORE); if (!GET_GAME_STATE (CLEAR_SPINDLE)) { NPCPhrase (GIVE_SPINDLE); SET_GAME_STATE (CLEAR_SPINDLE, 1); SET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 1); } NPCPhrase (CAN_BE_FRIENDS); SET_GAME_STATE (PKUNK_MANNER, 3); SET_GAME_STATE (PKUNK_VISITS, 0); SET_GAME_STATE (PKUNK_HOME_VISITS, 0); } else if (PLAYER_SAID (R, what_about_ilwrath)) { NPCPhrase (ABOUT_ILWRATH /* ILWRATH_GONE */); DISABLE_PHRASE (what_about_ilwrath); } if (PHRASE_ENABLED (we_conquer) && GET_GAME_STATE (PKUNK_MANNER) == 0) { Response (we_conquer, DiscussConquer); } if (GET_GAME_STATE (PKUNK_ON_THE_MOVE)) { if (PHRASE_ENABLED (where_fleet_1) && !GET_GAME_STATE (PKUNK_SWITCH)) { switch (GET_GAME_STATE (PKUNK_FLEET)) { case 0: Response (where_fleet_1, PkunkHome); break; case 1: Response (where_fleet_2, PkunkHome); break; case 2: Response (where_fleet_3, PkunkHome); break; } } else if (!PHRASE_ENABLED (where_fleet_1) && PHRASE_ENABLED (am_worried_1) && (GET_GAME_STATE (PKUNK_MISSION) & 1)) { switch (GET_GAME_STATE (PKUNK_WORRY)) { case 0: Response (am_worried_1, PkunkHome); break; case 1: Response (am_worried_2, PkunkHome); break; case 2: Response (am_worried_3, PkunkHome); break; } } } if (!GET_GAME_STATE (PKUNK_SHIP_MONTH)) { construct_response (shared_phrase_buf, we_are_vindicator0, GLOBAL_SIS (CommanderName), we_are_vindicator1, GLOBAL_SIS (ShipName), we_are_vindicator2, NULL_PTR); DoResponsePhrase (we_are_vindicator0, OfferAlliance, shared_phrase_buf); } if (PHRASE_ENABLED (what_about_you)) { Response (what_about_you, AboutPkunk); } if (PHRASE_ENABLED (what_about_ilwrath)) { if (!GET_GAME_STATE (ILWRATH_DECEIVED)) { Response (what_about_ilwrath, AboutIlwrath); } else { Response (what_about_ilwrath, PkunkHome); } } Response (bye_friendly, ExitConversation); } static void PkunkFriendlySpace (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, whats_up_space)) { if (ShipsReady ()) NPCPhrase (SHIPS_AT_HOME); else { NumVisits = GET_GAME_STATE (PKUNK_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_SPACE_1); break; case 1: NPCPhrase (GENERAL_INFO_SPACE_2); break; case 2: NPCPhrase (GENERAL_INFO_SPACE_3); break; case 3: NPCPhrase (GENERAL_INFO_SPACE_4); break; case 4: NPCPhrase (GENERAL_INFO_SPACE_5); break; case 5: NPCPhrase (GENERAL_INFO_SPACE_6); break; case 6: NPCPhrase (GENERAL_INFO_SPACE_7); break; case 7: NPCPhrase (GENERAL_INFO_SPACE_8); --NumVisits; break; } SET_GAME_STATE (PKUNK_INFO, NumVisits); } DISABLE_PHRASE (whats_up_space); } else if (PLAYER_SAID (R, how_goes_war)) { NumVisits = GET_GAME_STATE (PKUNK_WAR); switch (NumVisits++) { case 0: NPCPhrase (WAR_GOES_1); SET_GAME_STATE (KNOW_URQUAN_STORY, 1); SET_GAME_STATE (KNOW_KOHR_AH_STORY, 1); break; case 1: NPCPhrase (WAR_GOES_2); break; case 2: NPCPhrase (WAR_GOES_3); break; case 3: NPCPhrase (WAR_GOES_4); SET_GAME_STATE (PKUNK_DONE_WAR, 1); --NumVisits; break; } SET_GAME_STATE (PKUNK_WAR, NumVisits); DISABLE_PHRASE (how_goes_war); } else if (PLAYER_SAID (R, tell_my_fortune)) { NumVisits = GET_GAME_STATE (PKUNK_FORTUNE); switch (NumVisits++) { case 0: NPCPhrase (FORTUNE_IS_1); break; case 1: NPCPhrase (FORTUNE_IS_2); break; case 2: NPCPhrase (FORTUNE_IS_3); break; case 3: NPCPhrase (FORTUNE_IS_4); break; case 4: NPCPhrase (FORTUNE_IS_5); break; case 5: NPCPhrase (FORTUNE_IS_6); break; case 6: NPCPhrase (FORTUNE_IS_7); break; case 7: NPCPhrase (FORTUNE_IS_8); --NumVisits; break; } SET_GAME_STATE (PKUNK_FORTUNE, NumVisits); DISABLE_PHRASE (tell_my_fortune); } if (PHRASE_ENABLED (whats_up_space)) Response (whats_up_space, PkunkFriendlySpace); if (!GET_GAME_STATE (PKUNK_DONE_WAR) && PHRASE_ENABLED (how_goes_war)) Response (how_goes_war, PkunkFriendlySpace); if (PHRASE_ENABLED (tell_my_fortune)) Response (tell_my_fortune, PkunkFriendlySpace); Response (friendly_bye_space, ExitConversation); } static void PkunkNeutralSpace (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, form_alliance)) { NPCPhrase (GO_TO_HOMEWORLD); DISABLE_PHRASE (form_alliance); } else if (PLAYER_SAID (R, can_you_help)) { NPCPhrase (GO_TO_HOMEWORLD_AGAIN); DISABLE_PHRASE (can_you_help); } else if (PLAYER_SAID (R, hostile_greeting)) { NPCPhrase (DONT_BE_HOSTILE); DISABLE_PHRASE (hostile_greeting); } else if (PLAYER_SAID (R, whats_up_neutral)) { NumVisits = GET_GAME_STATE (PKUNK_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_SPACE_1); break; case 1: NPCPhrase (GENERAL_INFO_SPACE_2); break; case 2: NPCPhrase (GENERAL_INFO_SPACE_6 /* was 3 */); break; case 3: NPCPhrase (GENERAL_INFO_SPACE_7 /* was 4 */); --NumVisits; break; } SET_GAME_STATE (PKUNK_INFO, NumVisits); DISABLE_PHRASE (whats_up_neutral); } if (PHRASE_ENABLED (form_alliance)) Response (form_alliance, PkunkNeutralSpace); else if (PHRASE_ENABLED (can_you_help)) Response (can_you_help, PkunkNeutralSpace); if (PHRASE_ENABLED (hostile_greeting)) Response (hostile_greeting, PkunkNeutralSpace); else { Response (obey, ExitConversation); } if (PHRASE_ENABLED (whats_up_neutral)) Response (whats_up_neutral, PkunkNeutralSpace); Response (neutral_bye_space, ExitConversation); } static void PkunkMigrate (RESPONSE_REF R) { BYTE ReasonMask; (void) R; // ignored ReasonMask = GET_GAME_STATE (PKUNK_REASONS); if (!(ReasonMask & GOOD_REASON_1)) Response (good_reason_1, ExitConversation); if (!(ReasonMask & BAD_REASON_1)) Response (bad_reason_1, ExitConversation); if (!(ReasonMask & GOOD_REASON_2)) Response (good_reason_2, ExitConversation); if (!(ReasonMask & BAD_REASON_2)) Response (bad_reason_2, ExitConversation); Response (suit_yourself, ExitConversation); } static void Intro (void) { BYTE NumVisits, Manner; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } Manner = GET_GAME_STATE (PKUNK_MANNER); if (Manner == 2) { // Irreparably Pissed off the Pkunk. NumVisits = GET_GAME_STATE (PKUNK_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HATE_YOU_FOREVER_1); break; case 1: NPCPhrase (HATE_YOU_FOREVER_2); break; case 2: NPCPhrase (HATE_YOU_FOREVER_3); break; case 3: NPCPhrase (HATE_YOU_FOREVER_4); --NumVisits; break; } SET_GAME_STATE (PKUNK_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (Manner == 1) { // Bad relations with the Pkunk, but not irreparably. NumVisits = GET_GAME_STATE (PKUNK_VISITS); switch (NumVisits++) { case 0: NPCPhrase (SPIRITUAL_PROBLEMS_1); break; case 1: NPCPhrase (SPIRITUAL_PROBLEMS_2); break; case 2: NPCPhrase (SPIRITUAL_PROBLEMS_3); break; case 3: NPCPhrase (SPIRITUAL_PROBLEMS_4); --NumVisits; break; } SET_GAME_STATE (PKUNK_VISITS, NumVisits); PkunkAngry ((RESPONSE_REF)0); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { // Encountering the Pkunk at their home world. if (!GET_GAME_STATE (CLEAR_SPINDLE)) { NPCPhrase (GIVE_SPINDLE); SET_GAME_STATE (CLEAR_SPINDLE, 1); SET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 1); } else if (!GET_GAME_STATE (PKUNK_SENSE_VICTOR) && GLOBAL (GameClock.year_index) > START_YEAR && !GET_GAME_STATE (KOHR_AH_FRENZY)) { NPCPhrase (SENSE_KOHRAH_VICTORY); SET_GAME_STATE (PKUNK_SENSE_VICTOR, 1); } NumVisits = GET_GAME_STATE (PKUNK_HOME_VISITS); if (Manner == 0) { switch (NumVisits++) { case 0: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_2); break; case 2: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_3); break; case 3: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_4); --NumVisits; break; } } else { if (NumVisits && ShipsReady ()) { if (ActivateStarShip (PKUNK_SHIP, FEASIBILITY_STUDY) == 0) NPCPhrase (NO_ROOM); else { NPCPhrase (SHIP_GIFT); PrepareShip (); } } else switch (NumVisits++) { case 0: NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_2); break; case 2: NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_3); break; case 3: NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_4); break; case 4: NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_5); break; case 5: NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_6); break; case 6: NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_7); break; case 7: NPCPhrase (FRIENDLY_HOMEWORLD_HELLO_8); --NumVisits; break; } } SET_GAME_STATE (PKUNK_HOME_VISITS, NumVisits); PkunkHome ((RESPONSE_REF)0); } else if ((NumVisits = GET_GAME_STATE (PKUNK_MISSION)) == 0 || !(NumVisits & 1)) { // Encountering a Pkunk ship in space, while they are not // migrating. NumVisits = GET_GAME_STATE (PKUNK_VISITS); if (Manner == 3) { switch (NumVisits++) { case 0: NPCPhrase (FRIENDLY_SPACE_HELLO_1); break; case 1: NPCPhrase (FRIENDLY_SPACE_HELLO_2); break; case 2: NPCPhrase (FRIENDLY_SPACE_HELLO_3); break; case 3: NPCPhrase (FRIENDLY_SPACE_HELLO_4); break; case 4: NPCPhrase (FRIENDLY_SPACE_HELLO_5); break; case 5: NPCPhrase (FRIENDLY_SPACE_HELLO_6); break; case 6: NPCPhrase (FRIENDLY_SPACE_HELLO_7); break; case 7: NPCPhrase (FRIENDLY_SPACE_HELLO_8); --NumVisits; break; } PkunkFriendlySpace ((RESPONSE_REF)0); } else { switch (NumVisits++) { case 0: NPCPhrase (NEUTRAL_SPACE_HELLO_1); break; case 1: NPCPhrase (NEUTRAL_SPACE_HELLO_2); break; case 2: NPCPhrase (NEUTRAL_SPACE_HELLO_3); break; case 3: NPCPhrase (NEUTRAL_SPACE_HELLO_4); --NumVisits; break; } PkunkNeutralSpace ((RESPONSE_REF)0); } SET_GAME_STATE (PKUNK_VISITS, NumVisits); } else { // Encountering a Pkunk ship in space, while they are // migrating. NumVisits = GET_GAME_STATE (PKUNK_MIGRATE_VISITS); switch (NumVisits++) { case 0: NPCPhrase (MIGRATING_SPACE_1); break; case 1: NPCPhrase (MIGRATING_SPACE_2); break; case 2: NPCPhrase (MIGRATING_SPACE_3); break; case 3: NPCPhrase (MIGRATING_SPACE_4); break; case 4: NPCPhrase (MIGRATING_SPACE_5); break; case 5: NPCPhrase (MIGRATING_SPACE_6); break; case 6: NPCPhrase (MIGRATING_SPACE_7); break; case 7: NPCPhrase (MIGRATING_SPACE_8); --NumVisits; break; } SET_GAME_STATE (PKUNK_MIGRATE_VISITS, NumVisits); PkunkMigrate ((RESPONSE_REF)0); } } // Called after combat or communications static COUNT uninit_pkunk (void) { return (0); } static void post_pkunk_enc (void) { BYTE Manner; if (GET_GAME_STATE (BATTLE_SEGUE) == 1 && (Manner = GET_GAME_STATE (PKUNK_MANNER)) != 2) { SET_GAME_STATE (PKUNK_MANNER, 1); if (Manner != 1) { SET_GAME_STATE (PKUNK_VISITS, 0); SET_GAME_STATE (PKUNK_HOME_VISITS, 0); } } } LOCDATAPTR init_pkunk_comm (void) { LOCDATAPTR retval; pkunk_desc.init_encounter_func = Intro; pkunk_desc.post_encounter_func = post_pkunk_enc; pkunk_desc.uninit_encounter_func = uninit_pkunk; pkunk_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); pkunk_desc.AlienTextBaseline.y = 0; pkunk_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if (GET_GAME_STATE (PKUNK_MANNER) == 3 || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { // Enter communications immediately. SET_GAME_STATE (BATTLE_SEGUE, 0); } else { // Ask the player whether to attack or talk. SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &pkunk_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/pkunk/respkg.h0000600000175000017500000000003610543202023017324 0ustar joeyjoeyenum { PKUNK_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/pkunk/resinst.h0000600000175000017500000000012610543202023017520 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/rebel/0000755000175000017500000000000010552600275015645 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/rebel/strings.h0000600000175000017500000000264310543202024017472 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, REBEL_HELLO_1, REBEL_HELLO_2, REBEL_HELLO_3, REBEL_HELLO_4, how_goes_revolution, REBEL_REVOLUTION_1, REBEL_REVOLUTION_2, REBEL_REVOLUTION_3, REBEL_REVOLUTION_4, any_ships, NO_ROOM, HAVE_ALL_SHIPS, HAVE_FEW_SHIPS, NO_SHIPS_YET, give_info_rebels, WHAT_INFO, what_about_royalty, ABOUT_ROYALTY, what_about_war, ABOUT_WAR, what_about_urquan, ABOUT_URQUAN, what_about_vux, ABOUT_VUX, what_about_clue, ABOUT_CLUE, enough_info, OK_ENOUGH_INFO, bye_rebel, GOODBYE_REBEL, YEHAT_CAVALRY, what_about_pkunk_rebel, PKUNK_ABSORBED_REBEL, HATE_PKUNK_REBEL, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/rebel/rebel.c0000600000175000017500000002531110543202024017062 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/yehat/resinst.h" #include "comm/rebel/strings.h" #include "build.h" static LOCDATA yehat_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)YEHAT_PMAP_ANIM, /* AlienFrame */ (FONT)YEHAT_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* (SIS_TEXT_WIDTH - 16) * 2 / 3, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_MIDDLE, /* AlienTextValign */ (COLORMAP)YEHAT_COLOR_MAP, /* AlienColorMap */ YEHAT_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ REBEL_CONVERSATION_PHRASES, /* PlayerPhrases */ 15, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { /* right hand-wing tapping keyboard; front guy */ 4, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 10, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 6) | (1 << 7), }, { /* left hand-wing tapping keyboard; front guy */ 7, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 10, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 6) | (1 << 7), }, { 10, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 4) | (1 << 14), }, { 13, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 5), }, { 16, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3,/* RestartRate */ (1 << 2) | (1 << 14), }, { 21, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3,/* RestartRate */ (1 << 3), }, { /* right arm-wing rising; front guy */ 26, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3,/* RestartRate */ (1 << 0) | (1 << 1), }, { /* left arm-wing rising; front guy */ 28, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3,/* RestartRate */ (1 << 0) | (1 << 1), }, { 30, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 33, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 36, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 39, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 42, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 45, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 48, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 2) | (1 << 4), }, }, { /* AlienTransitionDesc - empty */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 3, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void PrepareShip (void) { BYTE mi, di, yi; mi = (GLOBAL (GameClock.month_index) % 12) + 1; SET_GAME_STATE (YEHAT_SHIP_MONTH, mi); if ((di = GLOBAL (GameClock.day_index)) > 28) di = 28; SET_GAME_STATE (YEHAT_SHIP_DAY, di); yi = (BYTE)(GLOBAL (GameClock.year_index) - START_YEAR); if (mi == 1) ++yi; SET_GAME_STATE (YEHAT_SHIP_YEAR, yi); } static void ExitConversation (RESPONSE_REF R) { if (PLAYER_SAID (R, bye_rebel)) NPCPhrase (GOODBYE_REBEL); } static void Rebels (RESPONSE_REF R); static void RebelInfo (RESPONSE_REF R) { BYTE InfoLeft; InfoLeft = FALSE; if (PLAYER_SAID (R, give_info_rebels)) NPCPhrase (WHAT_INFO); else if (PLAYER_SAID (R, what_about_urquan)) { NPCPhrase (ABOUT_URQUAN); DISABLE_PHRASE (what_about_urquan); } else if (PLAYER_SAID (R, what_about_royalty)) { NPCPhrase (ABOUT_ROYALTY); DISABLE_PHRASE (what_about_royalty); } else if (PLAYER_SAID (R, what_about_war)) { NPCPhrase (ABOUT_WAR); DISABLE_PHRASE (what_about_war); } else if (PLAYER_SAID (R, what_about_vux)) { NPCPhrase (ABOUT_VUX); DISABLE_PHRASE (what_about_vux); } else if (PLAYER_SAID (R, what_about_clue)) { NPCPhrase (ABOUT_CLUE); DISABLE_PHRASE (what_about_clue); } if (PHRASE_ENABLED (what_about_urquan)) { Response (what_about_urquan, RebelInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_royalty)) { Response (what_about_royalty, RebelInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_war)) { Response (what_about_war, RebelInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_vux)) { Response (what_about_vux, RebelInfo); InfoLeft = TRUE; } if (PHRASE_ENABLED (what_about_clue)) { Response (what_about_clue, RebelInfo); InfoLeft = TRUE; } Response (enough_info, Rebels); if (!InfoLeft) { DISABLE_PHRASE (give_info_rebels); } } static void Rebels (RESPONSE_REF R) { SBYTE NumVisits; if (PLAYER_SAID (R, how_goes_revolution)) { NumVisits = GET_GAME_STATE (YEHAT_REBEL_INFO); switch (NumVisits++) { case 0: NPCPhrase (REBEL_REVOLUTION_1); break; case 1: NPCPhrase (REBEL_REVOLUTION_2); break; case 2: NPCPhrase (REBEL_REVOLUTION_3); break; case 3: NPCPhrase (REBEL_REVOLUTION_4); --NumVisits; break; } SET_GAME_STATE (YEHAT_REBEL_INFO, NumVisits); DISABLE_PHRASE (how_goes_revolution); } else if (PLAYER_SAID (R, any_ships)) { if (GET_GAME_STATE (YEHAT_SHIP_MONTH) && ((NumVisits = (GLOBAL (GameClock.year_index) - START_YEAR) - GET_GAME_STATE (YEHAT_SHIP_YEAR)) < 0 || ((NumVisits == 0 && (NumVisits = GLOBAL (GameClock.month_index) - GET_GAME_STATE (YEHAT_SHIP_MONTH)) < 0) || (NumVisits == 0 && GLOBAL (GameClock.day_index) < GET_GAME_STATE (YEHAT_SHIP_DAY))))) NPCPhrase (NO_SHIPS_YET); else if ((NumVisits = ActivateStarShip (YEHAT_SHIP, FEASIBILITY_STUDY)) == 0) NPCPhrase (NO_ROOM); else { #define NUM_YEHAT_SHIPS 4 if (NumVisits < NUM_YEHAT_SHIPS) NPCPhrase (HAVE_FEW_SHIPS); else { NumVisits = NUM_YEHAT_SHIPS; NPCPhrase (HAVE_ALL_SHIPS); } AlienTalkSegue ((COUNT)~0); ActivateStarShip (YEHAT_SHIP, NumVisits); PrepareShip (); } DISABLE_PHRASE (any_ships); } else if (PLAYER_SAID (R, what_about_pkunk_rebel)) { if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK)) NPCPhrase (PKUNK_ABSORBED_REBEL); else NPCPhrase (HATE_PKUNK_REBEL); SET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK, 1); } else if (PLAYER_SAID (R, enough_info)) NPCPhrase (OK_ENOUGH_INFO); if (PHRASE_ENABLED (how_goes_revolution)) Response (how_goes_revolution, Rebels); if (!GET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK) && GET_GAME_STATE (PKUNK_VISITS) && GET_GAME_STATE (PKUNK_HOME_VISITS)) Response (what_about_pkunk_rebel, Rebels); if (PHRASE_ENABLED (any_ships)) Response (any_ships, Rebels); if (PHRASE_ENABLED (give_info_rebels)) { Response (give_info_rebels, RebelInfo); } Response (bye_rebel, ExitConversation); } static void Intro (void) { BYTE NumVisits; SET_GAME_STATE (BATTLE_SEGUE, 0); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) { NPCPhrase (YEHAT_CAVALRY); AlienTalkSegue ((COUNT)~0); if ((NumVisits = (BYTE)ActivateStarShip ( YEHAT_REBEL_SHIP, FEASIBILITY_STUDY )) > 8) NumVisits = 8; ActivateStarShip (YEHAT_REBEL_SHIP, NumVisits - (NumVisits >> 1)); ActivateStarShip (PKUNK_SHIP, NumVisits >> 1); } else { NumVisits = GET_GAME_STATE (YEHAT_REBEL_VISITS); switch (NumVisits++) { case 0: NPCPhrase (REBEL_HELLO_1); break; case 1: NPCPhrase (REBEL_HELLO_2); break; case 2: NPCPhrase (REBEL_HELLO_3); break; case 3: NPCPhrase (REBEL_HELLO_4); --NumVisits; break; } SET_GAME_STATE (YEHAT_REBEL_VISITS, NumVisits); Rebels ((RESPONSE_REF)0); } } static COUNT uninit_yehat (void) { return (0); } static void post_yehat_enc (void) { // nothing defined so far } LOCDATAPTR init_rebel_yehat_comm (void) { LOCDATAPTR retval; yehat_desc.init_encounter_func = Intro; yehat_desc.post_encounter_func = post_yehat_enc; yehat_desc.uninit_encounter_func = uninit_yehat; yehat_desc.AlienTextBaseline.x = SIS_SCREEN_WIDTH * 2 / 3; yehat_desc.AlienTextBaseline.y = 60; yehat_desc.AlienTextWidth = (SIS_TEXT_WIDTH - 16) * 2 / 3; // use alternate "Rebels" track if available yehat_desc.AlienAltSong = REBEL_MUSIC; yehat_desc.AlienSongFlags |= LDASF_USE_ALTERNATE; SET_GAME_STATE (BATTLE_SEGUE, 0); retval = &yehat_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/rebel/Makeinfo0000600000175000017500000000002510543202024017274 0ustar joeyjoeyuqm_CFILES="rebel.c" uqm-0.6.2/sc2/src/sc2code/comm/Makeinfo0000600000175000017500000000031310543202034016204 0ustar joeyjoeyuqm_SUBDIRS="arilou blackur chmmr comandr druuge ilwrath melnorm mycon orz pkunk rebel shofixt slyhome slyland spahome spathi starbas supox syreen talkpet thradd umgah urquan utwig vux yehat zoqfot" uqm-0.6.2/sc2/src/sc2code/comm/commall.h0000600000175000017500000000160310543202034016330 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _COMMALL_H #define _COMMALL_H #include "colors.h" #include "comm.h" #include "commglue.h" #include "encount.h" #include "reslib.h" #endif /* _COMMALL_H */ uqm-0.6.2/sc2/src/sc2code/comm/utwig/0000755000175000017500000000000010552600275015713 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/utwig/ifontres.h0000600000175000017500000000004110543202025017667 0ustar joeyjoey#define UTWIG_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/utwig/restypes.h0000600000175000017500000000024110543202025017716 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/utwig/strings.h0000600000175000017500000000607410543202025017543 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, NEUTRAL_SPACE_HELLO_1, NEUTRAL_SPACE_HELLO_2, HOSTILE_SPACE_HELLO_1, HOSTILE_SPACE_HELLO_2, BOMB_WORLD_HELLO_1, BOMB_WORLD_HELLO_2, HOSTILE_BOMB_HELLO_1, HOSTILE_BOMB_HELLO_2, NEUTRAL_HOMEWORLD_HELLO_1, NEUTRAL_HOMEWORLD_HELLO_2, NEUTRAL_HOMEWORLD_HELLO_3, NEUTRAL_HOMEWORLD_HELLO_4, HOSTILE_HOMEWORLD_HELLO_1, HOSTILE_HOMEWORLD_HELLO_2, why_you_here, WE_GUARD_BOMB, what_about_bomb, ABOUT_BOMB, give_us_bomb_or_die, GUARDS_WARN, demand_bomb, GUARDS_FIGHT, may_we_have_bomb, NO_BOMB, please, SORRY_NO_BOMB, whats_up_bomb, GENERAL_INFO_BOMB_1, GENERAL_INFO_BOMB_2, bye_bomb, GOODBYE_BOMB, hey_wait_got_ultron, TAUNT_US_BUT_WE_LOOK, TRICKED_US_1, TRICKED_US_2, we_are_vindicator0, we_are_vindicator1, we_are_vindicator2, WOULD_BE_HAPPY_BUT, why_sad, ULTRON_BROKE, what_ultron, GLORIOUS_ULTRON, dont_be_babies, MOCK_OUR_PAIN, real_sorry_about_ultron, APPRECIATE_SYMPATHY, what_about_you_1, ABOUT_US_1, what_about_you_2, ABOUT_US_2, what_about_you_3, ABOUT_US_3, what_about_urquan_1, ABOUT_URQUAN_1, what_about_urquan_2, ABOUT_URQUAN_2, got_ultron, DONT_WANT_TO_LOOK, SICK_TRICK_1, SICK_TRICK_2, bye_neutral, GOODBYE_NEUTRAL, TOO_LATE, name_1, name_2, name_3, name_40, name_41, HAPPY_DAYS, OK_ATTACK_KOHRAH, whats_up_after_space, GENERAL_INFO_AFTER_SPACE_1, GENERAL_INFO_AFTER_SPACE_2, what_now_after_space, DO_THIS_AFTER_SPACE, bye_after_space, GOODBYE_AFTER_SPACE, whats_up_before_space, GENERAL_INFO_BEFORE_SPACE_1, GENERAL_INFO_BEFORE_SPACE_2, what_now_before_space, DO_THIS_BEFORE_SPACE, bye_before_space, GOODBYE_BEFORE_SPACE, how_went_war, ABOUT_BATTLE, how_goes_war, BATTLE_HAPPENS_1, BATTLE_HAPPENS_2, FLEET_ON_WAY, learn_new_info, NO_NEW_INFO, SAMATRA, what_now_homeworld, HOPE_KILL_EACH_OTHER, how_is_ultron, ULTRON_IS_GREAT, bye_allied_homeworld, GOODBYE_ALLIED_HOMEWORLD, ALLIED_HOMEWORLD_HELLO_1, ALLIED_HOMEWORLD_HELLO_2, ALLIED_HOMEWORLD_HELLO_3, ALLIED_HOMEWORLD_HELLO_4, HELLO_BEFORE_KOHRAH_SPACE_1, HELLO_BEFORE_KOHRAH_SPACE_2, HELLO_DURING_KOHRAH_SPACE_1, HELLO_DURING_KOHRAH_SPACE_2, HELLO_AFTER_KOHRAH_SPACE_1, HELLO_AFTER_KOHRAH_SPACE_2, UP_TO_YOU, can_you_help, HOW_HELP, DONT_NEED, HAVE_4_SHIPS, NO_ULTRON_AT_BOMB, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/utwig/igfxres.h0000600000175000017500000000004610543202025017512 0ustar joeyjoey#define UTWIG_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/utwig/utwig.res0000600000175000017500000000035010543202025017542 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/utwig PACKAGE UTWIG_PACKAGE utwig.con GFXRES UTWIG_PMAP_ANIM utwig.ani FONTRES UTWIG_FONT utwig.fon MUSICRES UTWIG_MUSIC utwig.mod STRTAB UTWIG_CONVERSATION_PHRASES utwig.txt uqm-0.6.2/sc2/src/sc2code/comm/utwig/istrtab.h0000600000175000017500000000012410543202025017510 0ustar joeyjoey#define UTWIG_CONVERSATION_PHRASES 0x00200004L #define UTWIG_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/utwig/imusicre.h0000600000175000017500000000011210543202025017655 0ustar joeyjoey#define UTWIG_MUSIC 0x00200006L #define UTWIG_ULTRON_MUSIC 0x00400106L uqm-0.6.2/sc2/src/sc2code/comm/utwig/Makeinfo0000600000175000017500000000002610543202025017344 0ustar joeyjoeyuqm_CFILES="utwigc.c" uqm-0.6.2/sc2/src/sc2code/comm/utwig/respkg.h0000600000175000017500000000007410543202025017337 0ustar joeyjoeyenum { UTWIG_PACKAGE = 1, UTWIG_ULTRON_MUSIC_PACKAGE, }; uqm-0.6.2/sc2/src/sc2code/comm/utwig/utwigc.c0000600000175000017500000005317010543202025017346 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/utwig/resinst.h" #include "comm/utwig/strings.h" #include "build.h" #include "gameev.h" static LOCDATA utwig_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)UTWIG_PMAP_ANIM, /* AlienFrame */ (FONT)UTWIG_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_MIDDLE, /* AlienTextValign */ (COLORMAP)UTWIG_COLOR_MAP, /* AlienColorMap */ UTWIG_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ UTWIG_CONVERSATION_PHRASES, /* PlayerPhrases */ 16, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 4, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 7, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ (1 << 2), /* BlockMask */ }, { 11, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ (1 << 1), /* BlockMask */ }, { 13, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 12, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, { 18, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 20, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 22, /* StartIndex */ 3, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 25, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 27, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 30, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 32, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 34, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 36, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 38, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 40, /* StartIndex */ 2, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 42, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND * 2 / 15, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND * 10, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 3, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 20, ONE_SECOND / 20, /* FrameRate */ ONE_SECOND * 7 / 60, ONE_SECOND / 2, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (PLAYER_SAID (R, bye_neutral)) NPCPhrase (GOODBYE_NEUTRAL); else if (PLAYER_SAID (R, bye_after_space)) NPCPhrase (GOODBYE_AFTER_SPACE); else if (PLAYER_SAID (R, bye_before_space)) NPCPhrase (GOODBYE_BEFORE_SPACE); else if (PLAYER_SAID (R, bye_allied_homeworld)) NPCPhrase (GOODBYE_ALLIED_HOMEWORLD); else if (PLAYER_SAID (R, bye_bomb)) NPCPhrase (GOODBYE_BOMB); else if (PLAYER_SAID (R, demand_bomb)) { NPCPhrase (GUARDS_FIGHT); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, got_ultron) || PLAYER_SAID (R, hey_wait_got_ultron)) { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { NPCPhrase (NO_ULTRON_AT_BOMB); SET_GAME_STATE (REFUSED_ULTRON_AT_BOMB, 1); } else { if (PLAYER_SAID (R, got_ultron)) NPCPhrase (DONT_WANT_TO_LOOK); else NPCPhrase (TAUNT_US_BUT_WE_LOOK); if (GET_GAME_STATE (ULTRON_CONDITION) < 4) { switch (GET_GAME_STATE (UTWIG_INFO)) { case 0: if (PLAYER_SAID (R, got_ultron)) NPCPhrase (SICK_TRICK_1); else { NPCPhrase (TRICKED_US_1); SET_GAME_STATE (BATTLE_SEGUE, 1); } break; case 1: if (PLAYER_SAID (R, got_ultron)) NPCPhrase (SICK_TRICK_2); else { NPCPhrase (TRICKED_US_2); SET_GAME_STATE (BATTLE_SEGUE, 1); } break; } SET_GAME_STATE (UTWIG_INFO, 1); } else { NPCPhrase (HAPPY_DAYS); if (GET_GAME_STATE (KOHR_AH_FRENZY)) NPCPhrase (TOO_LATE); else { NPCPhrase (OK_ATTACK_KOHRAH); AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_UTWIG_SUPOX_MISSION); } SET_GAME_STATE (UTWIG_HAVE_ULTRON, 1); SET_GAME_STATE (ULTRON_CONDITION, 5); SET_GAME_STATE (UTWIG_VISITS, 0); SET_GAME_STATE (SUPOX_VISITS, 0); SET_GAME_STATE (UTWIG_HOME_VISITS, 0); SET_GAME_STATE (SUPOX_HOME_VISITS, 0); SET_GAME_STATE (BOMB_VISITS, 0); SET_GAME_STATE (SUPOX_INFO, 0); SET_GAME_STATE (UTWIG_INFO, 0); SET_GAME_STATE (SUPOX_WAR_NEWS, 0); SET_GAME_STATE (UTWIG_WAR_NEWS, 0); SET_GAME_STATE (SUPOX_HOSTILE, 0); SET_GAME_STATE (UTWIG_HOSTILE, 0); ActivateStarShip (UTWIG_SHIP, 0); ActivateStarShip (SUPOX_SHIP, 0); } } } else if (PLAYER_SAID (R, can_you_help)) { NPCPhrase (HOW_HELP); if (ActivateStarShip (UTWIG_SHIP, FEASIBILITY_STUDY) == 0) NPCPhrase (DONT_NEED); else { NPCPhrase (HAVE_4_SHIPS); AlienTalkSegue ((COUNT)~0); ActivateStarShip (UTWIG_SHIP, 4); } } } static void AlliedHome (RESPONSE_REF R); static void AlliedHome (RESPONSE_REF R) { BYTE NumVisits, News; News = GET_GAME_STATE (UTWIG_WAR_NEWS); NumVisits = GET_GAME_STATE (UTWIG_SUPOX_MISSION); if (PLAYER_SAID (R, how_went_war)) { NPCPhrase (ABOUT_BATTLE); News |= (1 << 0); } else if (PLAYER_SAID (R, how_goes_war)) { if (NumVisits == 1) { NPCPhrase (FLEET_ON_WAY); SET_GAME_STATE (UTWIG_WAR_NEWS, 1); } else switch (GET_GAME_STATE (UTWIG_WAR_NEWS)) { case 0: NPCPhrase (BATTLE_HAPPENS_1); News = 1; break; case 1: NPCPhrase (BATTLE_HAPPENS_2); News = 2; break; } DISABLE_PHRASE (how_goes_war); } else if (PLAYER_SAID (R, learn_new_info)) { if (NumVisits < 5) NPCPhrase (NO_NEW_INFO); else { NPCPhrase (SAMATRA); News |= (1 << 1); } DISABLE_PHRASE (learn_new_info); } else if (PLAYER_SAID (R, what_now_homeworld)) { if (NumVisits < 5) NPCPhrase (UP_TO_YOU); else NPCPhrase (HOPE_KILL_EACH_OTHER); DISABLE_PHRASE (what_now_homeworld); } else if (PLAYER_SAID (R, how_is_ultron)) { NPCPhrase (ULTRON_IS_GREAT); DISABLE_PHRASE (how_is_ultron); } SET_GAME_STATE (UTWIG_WAR_NEWS, News); if (NumVisits >= 5) { if (!(News & (1 << 0))) Response (how_went_war, AlliedHome); } else if (PHRASE_ENABLED (how_goes_war) && ((NumVisits == 1 && News == 0) || (NumVisits && News < 2))) Response (how_goes_war, AlliedHome); if (PHRASE_ENABLED (learn_new_info)) Response (learn_new_info, AlliedHome); if (PHRASE_ENABLED (what_now_homeworld)) Response (what_now_homeworld, AlliedHome); if (PHRASE_ENABLED (how_is_ultron)) Response (how_is_ultron, AlliedHome); if (NumVisits == 0) Response (can_you_help, ExitConversation); Response (bye_allied_homeworld, ExitConversation); } static void BeforeKohrAh (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, whats_up_before_space)) { NumVisits = GET_GAME_STATE (UTWIG_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_BEFORE_SPACE_1); break; case 1: NPCPhrase (GENERAL_INFO_BEFORE_SPACE_2); --NumVisits; break; } SET_GAME_STATE (UTWIG_INFO, NumVisits); DISABLE_PHRASE (whats_up_before_space); } else if (PLAYER_SAID (R, what_now_before_space)) { NPCPhrase (DO_THIS_BEFORE_SPACE); DISABLE_PHRASE (what_now_before_space); } if (PHRASE_ENABLED (whats_up_before_space)) Response (whats_up_before_space, BeforeKohrAh); if (PHRASE_ENABLED (what_now_before_space)) Response (what_now_before_space, BeforeKohrAh); Response (bye_before_space, ExitConversation); } static void AfterKohrAh (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, whats_up_after_space)) { NumVisits = GET_GAME_STATE (UTWIG_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_AFTER_SPACE_1); break; case 1: NPCPhrase (GENERAL_INFO_AFTER_SPACE_2); --NumVisits; break; } SET_GAME_STATE (UTWIG_INFO, NumVisits); DISABLE_PHRASE (whats_up_after_space); } else if (PLAYER_SAID (R, what_now_after_space)) { NPCPhrase (DO_THIS_AFTER_SPACE); DISABLE_PHRASE (what_now_after_space); } if (PHRASE_ENABLED (whats_up_after_space)) Response (whats_up_after_space, AfterKohrAh); if (PHRASE_ENABLED (what_now_after_space)) Response (what_now_after_space, AfterKohrAh); Response (bye_after_space, ExitConversation); } static void NeutralUtwig (RESPONSE_REF R) { BYTE i, LastStack; RESPONSE_REF pStr[4]; LastStack = 0; pStr[0] = pStr[1] = pStr[2] = pStr[3] = 0; if (PLAYER_SAID (R, we_are_vindicator0)) { NPCPhrase (WOULD_BE_HAPPY_BUT); SET_GAME_STATE (UTWIG_STACK1, 1); } else if (PLAYER_SAID (R, why_sad)) { NPCPhrase (ULTRON_BROKE); SET_GAME_STATE (UTWIG_STACK1, 2); } else if (PLAYER_SAID (R, what_ultron)) { NPCPhrase (GLORIOUS_ULTRON); SET_GAME_STATE (UTWIG_STACK1, 3); } else if (PLAYER_SAID (R, dont_be_babies)) { NPCPhrase (MOCK_OUR_PAIN); SET_GAME_STATE (BATTLE_SEGUE, 1); SET_GAME_STATE (UTWIG_STACK1, 4); SET_GAME_STATE (UTWIG_HOSTILE, 1); SET_GAME_STATE (UTWIG_INFO, 0); SET_GAME_STATE (UTWIG_HOME_VISITS, 0); SET_GAME_STATE (UTWIG_VISITS, 0); SET_GAME_STATE (BOMB_VISITS, 0); return; } else if (PLAYER_SAID (R, real_sorry_about_ultron)) { NPCPhrase (APPRECIATE_SYMPATHY); SET_GAME_STATE (UTWIG_STACK1, 4); return; } else if (PLAYER_SAID (R, what_about_you_1)) { NPCPhrase (ABOUT_US_1); LastStack = 2; SET_GAME_STATE (UTWIG_WAR_NEWS, 1); } else if (PLAYER_SAID (R, what_about_you_2)) { NPCPhrase (ABOUT_US_2); LastStack = 2; ActivateStarShip (SUPOX_SHIP, SPHERE_TRACKING); SET_GAME_STATE (UTWIG_WAR_NEWS, 2); } else if (PLAYER_SAID (R, what_about_you_3)) { NPCPhrase (ABOUT_US_3); SET_GAME_STATE (UTWIG_WAR_NEWS, 3); } else if (PLAYER_SAID (R, what_about_urquan_1)) { NPCPhrase (ABOUT_URQUAN_1); LastStack = 3; SET_GAME_STATE (UTWIG_STACK2, 1); } else if (PLAYER_SAID (R, what_about_urquan_2)) { NPCPhrase (ABOUT_URQUAN_2); SET_GAME_STATE (UTWIG_STACK2, 2); } switch (GET_GAME_STATE (UTWIG_STACK1)) { case 0: { UNICODE buf[ALLIANCE_NAME_BUFSIZE]; GetAllianceName (buf, name_1); construct_response ( shared_phrase_buf, we_are_vindicator0, GLOBAL_SIS (CommanderName), we_are_vindicator1, buf, we_are_vindicator2, NULL_PTR ); } pStr[0] = we_are_vindicator0; break; case 1: pStr[0] = why_sad; break; case 2: pStr[0] = what_ultron; break; case 3: pStr[0] = dont_be_babies; pStr[1] = real_sorry_about_ultron; break; } switch (GET_GAME_STATE (UTWIG_WAR_NEWS)) { case 0: pStr[2] = what_about_you_1; break; case 1: pStr[2] = what_about_you_2; break; case 2: pStr[2] = what_about_you_3; break; } switch (GET_GAME_STATE (UTWIG_STACK2)) { case 0: pStr[2] = what_about_urquan_1; break; case 1: pStr[2] = what_about_urquan_2; break; } if (pStr[LastStack]) { if (pStr[LastStack] != we_are_vindicator0) Response (pStr[LastStack], NeutralUtwig); else DoResponsePhrase (pStr[LastStack], NeutralUtwig, shared_phrase_buf); } for (i = 0; i < 4; ++i) { if (i != LastStack && pStr[i]) { if (pStr[i] != we_are_vindicator0) Response (pStr[i], NeutralUtwig); else DoResponsePhrase (pStr[i], NeutralUtwig, shared_phrase_buf); } } if (GET_GAME_STATE (ULTRON_CONDITION)) Response (got_ultron, ExitConversation); Response (bye_neutral, ExitConversation); } static void BombWorld (RESPONSE_REF R) { BYTE LastStack; RESPONSE_REF pStr[2]; LastStack = 0; pStr[0] = pStr[1] = 0; if (PLAYER_SAID (R, why_you_here)) { NPCPhrase (WE_GUARD_BOMB); SET_GAME_STATE (BOMB_STACK1, 1); } else if (PLAYER_SAID (R, what_about_bomb)) { NPCPhrase (ABOUT_BOMB); SET_GAME_STATE (BOMB_STACK1, 2); } else if (PLAYER_SAID (R, give_us_bomb_or_die)) { NPCPhrase (GUARDS_WARN); SET_GAME_STATE (BOMB_STACK1, 3); } else if (PLAYER_SAID (R, demand_bomb)) { NPCPhrase (GUARDS_FIGHT); SET_GAME_STATE (BATTLE_SEGUE, 1); SET_GAME_STATE (UTWIG_HOSTILE, 1); SET_GAME_STATE (UTWIG_INFO, 0); SET_GAME_STATE (UTWIG_HOME_VISITS, 0); SET_GAME_STATE (UTWIG_VISITS, 0); SET_GAME_STATE (BOMB_VISITS, 0); return; } else if (PLAYER_SAID (R, may_we_have_bomb)) { NPCPhrase (NO_BOMB); LastStack = 1; SET_GAME_STATE (BOMB_STACK2, 1); } else if (PLAYER_SAID (R, please)) { NPCPhrase (SORRY_NO_BOMB); SET_GAME_STATE (BOMB_STACK2, 2); } else if (PLAYER_SAID (R, whats_up_bomb)) { if (GET_GAME_STATE (BOMB_INFO)) NPCPhrase (GENERAL_INFO_BOMB_2); else { NPCPhrase (GENERAL_INFO_BOMB_1); SET_GAME_STATE (BOMB_INFO, 1); } DISABLE_PHRASE (whats_up_bomb); } switch (GET_GAME_STATE (BOMB_STACK2)) { case 0: pStr[1] = may_we_have_bomb; break; case 1: pStr[1] = please; break; } switch (GET_GAME_STATE (BOMB_STACK1)) { case 0: pStr[0] = why_you_here; pStr[1] = 0; break; case 1: pStr[0] = what_about_bomb; pStr[1] = 0; break; case 2: pStr[0] = give_us_bomb_or_die; break; case 3: pStr[0] = demand_bomb; break; } if (pStr[LastStack]) Response (pStr[LastStack], BombWorld); LastStack ^= 1; if (pStr[LastStack]) Response (pStr[LastStack], BombWorld); if (PHRASE_ENABLED (whats_up_bomb) && (GET_GAME_STATE (BOMB_STACK1) > 1)) Response (whats_up_bomb, BombWorld); if (GET_GAME_STATE (ULTRON_CONDITION) && !GET_GAME_STATE (REFUSED_ULTRON_AT_BOMB)) Response (got_ultron, ExitConversation); if (GET_GAME_STATE (BOMB_INFO)) { Response (bye_bomb, ExitConversation); } else { Response (bye_neutral, ExitConversation); } } static void Intro (void) { BYTE NumVisits; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (GET_GAME_STATE (UTWIG_HOSTILE)) { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { NumVisits = GET_GAME_STATE (BOMB_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_BOMB_HELLO_1); break; case 1: NPCPhrase (HOSTILE_BOMB_HELLO_2); --NumVisits; break; } SET_GAME_STATE (BOMB_VISITS, NumVisits); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (UTWIG_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (HOSTILE_HOMEWORLD_HELLO_2); --NumVisits; break; } SET_GAME_STATE (UTWIG_HOME_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (UTWIG_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_SPACE_HELLO_1); break; case 1: NPCPhrase (HOSTILE_SPACE_HELLO_2); --NumVisits; break; } SET_GAME_STATE (UTWIG_VISITS, NumVisits); } if (!GET_GAME_STATE (ULTRON_CONDITION) || (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6))) { SET_GAME_STATE (BATTLE_SEGUE, 1); } else { Response (hey_wait_got_ultron, ExitConversation); } } else if (ActivateStarShip (UTWIG_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (UTWIG_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (ALLIED_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (ALLIED_HOMEWORLD_HELLO_2); break; case 2: NPCPhrase (ALLIED_HOMEWORLD_HELLO_3); break; case 3: NPCPhrase (ALLIED_HOMEWORLD_HELLO_4); --NumVisits; break; } SET_GAME_STATE (UTWIG_HOME_VISITS, NumVisits); AlliedHome ((RESPONSE_REF)0); } else { NumVisits = GET_GAME_STATE (UTWIG_SUPOX_MISSION); if (NumVisits == 1) { NumVisits = GET_GAME_STATE (UTWIG_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_BEFORE_KOHRAH_SPACE_1); break; case 1: NPCPhrase (HELLO_BEFORE_KOHRAH_SPACE_2); --NumVisits; break; } SET_GAME_STATE (UTWIG_VISITS, NumVisits); BeforeKohrAh ((RESPONSE_REF)0); } else if (NumVisits < 5) { NumVisits = GET_GAME_STATE (UTWIG_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_DURING_KOHRAH_SPACE_1); break; case 1: NPCPhrase (HELLO_DURING_KOHRAH_SPACE_2); --NumVisits; break; } SET_GAME_STATE (UTWIG_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (UTWIG_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_AFTER_KOHRAH_SPACE_1); break; case 1: NPCPhrase (HELLO_AFTER_KOHRAH_SPACE_2); --NumVisits; break; } SET_GAME_STATE (UTWIG_VISITS, NumVisits); AfterKohrAh ((RESPONSE_REF)0); } } } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 6)) { NumVisits = GET_GAME_STATE (BOMB_VISITS); switch (NumVisits++) { case 0: NPCPhrase (BOMB_WORLD_HELLO_1); break; case 1: NPCPhrase (BOMB_WORLD_HELLO_2); --NumVisits; break; } SET_GAME_STATE (BOMB_VISITS, NumVisits); BombWorld ((RESPONSE_REF)0); } else { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (UTWIG_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_2); break; case 2: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_3); break; case 3: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_4); --NumVisits; break; } SET_GAME_STATE (UTWIG_HOME_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (UTWIG_VISITS); switch (NumVisits++) { case 0: NPCPhrase (NEUTRAL_SPACE_HELLO_1); break; case 1: NPCPhrase (NEUTRAL_SPACE_HELLO_2); --NumVisits; break; } SET_GAME_STATE (UTWIG_VISITS, NumVisits); } NeutralUtwig ((RESPONSE_REF)0); } } static COUNT uninit_utwig (void) { return (0); } static void post_utwig_enc (void) { // nothing defined so far } LOCDATAPTR init_utwig_comm (void) { LOCDATAPTR retval; utwig_desc.init_encounter_func = Intro; utwig_desc.post_encounter_func = post_utwig_enc; utwig_desc.uninit_encounter_func = uninit_utwig; utwig_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); utwig_desc.AlienTextBaseline.y = 70; utwig_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if (GET_GAME_STATE (UTWIG_HAVE_ULTRON)) { // use alternate 'Happy Utwig!' track utwig_desc.AlienAltSong = UTWIG_ULTRON_MUSIC; utwig_desc.AlienSongFlags |= LDASF_USE_ALTERNATE; } else { // regular track -- let's make sure utwig_desc.AlienSongFlags &= ~LDASF_USE_ALTERNATE; } if (GET_GAME_STATE (UTWIG_HAVE_ULTRON) || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &utwig_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/utwig/resinst.h0000600000175000017500000000012610543202025017531 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/umgah/0000755000175000017500000000000010552600275015655 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/umgah/ifontres.h0000600000175000017500000000004110543202026017632 0ustar joeyjoey#define UMGAH_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/umgah/restypes.h0000600000175000017500000000024110543202026017661 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/umgah/umgah.res0000600000175000017500000000035010543202026017447 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/umgah PACKAGE UMGAH_PACKAGE umgah.con GFXRES UMGAH_PMAP_ANIM umgah.ani FONTRES UMGAH_FONT umgah.fon MUSICRES UMGAH_MUSIC umgah.mod STRTAB UMGAH_CONVERSATION_PHRASES umgah.txt uqm-0.6.2/sc2/src/sc2code/comm/umgah/strings.h0000600000175000017500000000471010543202026017501 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, HWLD_PRE_ZOMBIE_HELLO_1, HWLD_PRE_ZOMBIE_HELLO_2, HWLD_PRE_ZOMBIE_HELLO_3, HWLD_PRE_ZOMBIE_HELLO_4, SPACE_PRE_ZOMBIE_HELLO_1, SPACE_PRE_ZOMBIE_HELLO_2, SPACE_PRE_ZOMBIE_HELLO_3, SPACE_PRE_ZOMBIE_HELLO_4, UNKNOWN_ZOMBIE_HELLO_1, UNKNOWN_ZOMBIE_HELLO_2, UNKNOWN_ZOMBIE_HELLO_3, UNKNOWN_ZOMBIE_HELLO_4, DESTROY_INTERFERER_1, DESTROY_INTERFERER_2, DESTROY_INTERFERER_3, DESTROY_INTERFERER_4, REVEALED_ZOMBIE_HELLO_1, REVEALED_ZOMBIE_HELLO_2, REVEALED_ZOMBIE_HELLO_3, REVEALED_ZOMBIE_HELLO_4, HOSTILE_HELLO_1, HOSTILE_HELLO_2, HOSTILE_HELLO_3, HOSTILE_HELLO_4, REWARD_AT_HOMEWORLD_1, REWARD_AT_HOMEWORLD_2, POST_ZOMBIE_HWLD_HELLO, owe_me_big_time, our_largesse, GIVE_LIFEDATA, THANKS, what_do_with_tpet, TRICK_URQUAN, any_jokes, SURE, what_before_tpet, TRKD_SPATHI_AND_ILWRATH, where_caster, SPATHI_TOOK_THEM, so_what_for_now, DO_THIS_NOW, bye_post_zombie, FUNNY_IDEA, whats_up_pre_zombie, GENERAL_INFO_PRE_ZOMBIE, evil_blobbies_give_up, NOT_EVIL_BLOBBIES, evil_blobbies_must_die, OH_NO_WE_WONT, can_we_be_friends, SURE_FRIENDS, want_to_defeat_urquan, FINE_BY_US, bye_pre_zombie, GOODBYE_PRE_ZOMBIE, threat, NO_THREAT, whats_up_zombies, GENERAL_INFO_ZOMBIE, how_goes_tpet, WHAT_TPET, you_told_us, SADLY_IT_DIED, dont_believe, THEN_DIE, bye_unknown, GOODBYE_UNKNOWN, evil_blobbies, YES_VERY_EVIL, give_up_or_die, NOT_GIVE_UP, we_vindicator0, we_vindicator1, we_vindicator2, GOOD_FOR_YOU_1, come_in_peace, GOOD_FOR_YOU_2, know_any_jokes, JOKE_1, better_joke, JOKE_2, not_very_funny, YES_WE_ARE, what_about_tpet, arilou_told_us, bye_zombie, GOODBYE_ZOMBIE, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/umgah/igfxres.h0000600000175000017500000000004610543202026017455 0ustar joeyjoey#define UMGAH_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/umgah/istrtab.h0000600000175000017500000000012410543202026017453 0ustar joeyjoey#define UMGAH_CONVERSATION_PHRASES 0x00200004L #define UMGAH_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/umgah/imusicre.h0000600000175000017500000000004210543202026017622 0ustar joeyjoey#define UMGAH_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/umgah/Makeinfo0000600000175000017500000000002610543202026017307 0ustar joeyjoeyuqm_CFILES="umgahc.c" uqm-0.6.2/sc2/src/sc2code/comm/umgah/respkg.h0000600000175000017500000000003610543202026017300 0ustar joeyjoeyenum { UMGAH_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/umgah/umgahc.c0000600000175000017500000003774110543202026017261 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/umgah/resinst.h" #include "comm/umgah/strings.h" #include "build.h" static LOCDATA umgah_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)UMGAH_PMAP_ANIM, /* AlienFrame */ (FONT)UMGAH_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)UMGAH_COLOR_MAP, /* AlienColorMap */ UMGAH_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ UMGAH_CONVERSATION_PHRASES, /* PlayerPhrases */ 16, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 5, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 5), }, { 8, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 6), }, { 11, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 7), }, { 13, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 8), }, { 15, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 9), }, { 17, /* StartIndex */ 3, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 7 / 60, 0, /* FrameRate */ ONE_SECOND * 3, ONE_SECOND * 3, /* RestartRate */ (1 << 0), }, { 20, /* StartIndex */ 3, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 7 / 60, 0, /* FrameRate */ ONE_SECOND * 3, ONE_SECOND * 3, /* RestartRate */ (1 << 1), }, { 23, /* StartIndex */ 2, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 7 / 60, 0, /* FrameRate */ ONE_SECOND * 3, ONE_SECOND * 3, /* RestartRate */ (1 << 2), }, { 25, /* StartIndex */ 2, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 7 / 60, 0, /* FrameRate */ ONE_SECOND * 3, ONE_SECOND * 3, /* RestartRate */ (1 << 3), }, { 27, /* StartIndex */ 2, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND * 7 / 60, 0, /* FrameRate */ ONE_SECOND * 3, ONE_SECOND * 3, /* RestartRate */ (1 << 4), }, { 29, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 32, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 35, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 40, /* StartIndex */ 6, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND / 10, 0, /* RestartRate */ 0, /* BlockMask */ }, { 46, /* StartIndex */ 2, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 5, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 15), /* BlockMask */ }, { 48, /* StartIndex */ 2, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 5, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 14), /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 4, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void CombatIsInevitable (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, bye_zombie)) { NPCPhrase (GOODBYE_ZOMBIE); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (PLAYER_SAID (R, bye_pre_zombie)) NPCPhrase (GOODBYE_PRE_ZOMBIE); else if (PLAYER_SAID (R, can_we_be_friends)) { NPCPhrase (SURE_FRIENDS); SET_GAME_STATE (UMGAH_MENTIONED_TRICKS, 1); } else if (PLAYER_SAID (R, evil_blobbies_give_up)) { NPCPhrase (NOT_EVIL_BLOBBIES); SET_GAME_STATE (UMGAH_EVIL_BLOBBIES, 1); } else if (PLAYER_SAID (R, evil_blobbies_must_die)) NPCPhrase (OH_NO_WE_WONT); else if (PLAYER_SAID (R, threat)) NPCPhrase (NO_THREAT); else if (PLAYER_SAID (R, dont_believe)) { NPCPhrase (THEN_DIE); SET_GAME_STATE (KNOW_UMGAH_ZOMBIES, 1); SET_GAME_STATE (UMGAH_VISITS, 0); } else if (PLAYER_SAID (R, bye_unknown)) { NPCPhrase (GOODBYE_UNKNOWN); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (PLAYER_SAID (R, bye_post_zombie)) { NPCPhrase (FUNNY_IDEA); AlienTalkSegue ((COUNT)~0); ActivateStarShip (UMGAH_SHIP, 4); SET_GAME_STATE (UMGAH_HOSTILE, 1); } } static void Zombies (RESPONSE_REF R) { if (GET_GAME_STATE (MET_NORMAL_UMGAH)) { if (PLAYER_SAID (R, whats_up_zombies)) { NPCPhrase (GENERAL_INFO_ZOMBIE); DISABLE_PHRASE (whats_up_zombies); } else if (PLAYER_SAID (R, how_goes_tpet)) { NPCPhrase (WHAT_TPET); DISABLE_PHRASE (how_goes_tpet); } else if (PLAYER_SAID (R, you_told_us)) { NPCPhrase (SADLY_IT_DIED); DISABLE_PHRASE (you_told_us); } if (PHRASE_ENABLED (whats_up_zombies) && PHRASE_ENABLED (how_goes_tpet)) Response (whats_up_zombies, Zombies); if (PHRASE_ENABLED (how_goes_tpet)) Response (how_goes_tpet, Zombies); else if (PHRASE_ENABLED (you_told_us)) Response (you_told_us, Zombies); else { Response (dont_believe, CombatIsInevitable); } if (PHRASE_ENABLED (whats_up_zombies) && !PHRASE_ENABLED (how_goes_tpet)) Response (whats_up_zombies, Zombies); Response (threat, CombatIsInevitable); Response (bye_unknown, CombatIsInevitable); } else { BYTE i, LastStack; RESPONSE_REF pStr[4]; LastStack = 0; pStr[0] = pStr[1] = pStr[2] = pStr[3] = 0; if (PLAYER_SAID (R, evil_blobbies)) { NPCPhrase (YES_VERY_EVIL); DISABLE_PHRASE (evil_blobbies); LastStack = 0; } else if (PLAYER_SAID (R, we_vindicator0)) { NPCPhrase (GOOD_FOR_YOU_1); DISABLE_PHRASE (we_vindicator0); LastStack = 1; } else if (PLAYER_SAID (R, come_in_peace)) { NPCPhrase (GOOD_FOR_YOU_2); DISABLE_PHRASE (come_in_peace); LastStack = 1; } else if (PLAYER_SAID (R, know_any_jokes)) { NPCPhrase (JOKE_1); DISABLE_PHRASE (know_any_jokes); LastStack = 2; } else if (PLAYER_SAID (R, better_joke)) { NPCPhrase (JOKE_2); DISABLE_PHRASE (better_joke); LastStack = 2; } else if (PLAYER_SAID (R, not_very_funny)) { NPCPhrase (YES_WE_ARE); DISABLE_PHRASE (not_very_funny); LastStack = 2; } else if (PLAYER_SAID (R, what_about_tpet)) { NPCPhrase (WHAT_TPET); DISABLE_PHRASE (what_about_tpet); LastStack = 3; } else if (PLAYER_SAID (R, give_up_or_die)) { NPCPhrase (NOT_GIVE_UP); SET_GAME_STATE (BATTLE_SEGUE, 1); return; } else if (PLAYER_SAID (R, arilou_told_us)) { NPCPhrase (THEN_DIE); SET_GAME_STATE (BATTLE_SEGUE, 1); SET_GAME_STATE (KNOW_UMGAH_ZOMBIES, 1); SET_GAME_STATE (UMGAH_VISITS, 0); return; } if (PHRASE_ENABLED (evil_blobbies)) pStr[0] = evil_blobbies; else pStr[0] = give_up_or_die; if (PHRASE_ENABLED (we_vindicator0)) { construct_response (shared_phrase_buf, we_vindicator0, GLOBAL_SIS (CommanderName), we_vindicator1, GLOBAL_SIS (ShipName), we_vindicator2, NULL_PTR); pStr[1] = we_vindicator0; } else if (PHRASE_ENABLED (come_in_peace)) pStr[1] = come_in_peace; if (PHRASE_ENABLED (know_any_jokes)) pStr[2] = know_any_jokes; else if (PHRASE_ENABLED (better_joke)) pStr[2] = better_joke; else if (PHRASE_ENABLED (not_very_funny)) pStr[2] = not_very_funny; if (PHRASE_ENABLED (what_about_tpet)) pStr[3] = what_about_tpet; else pStr[3] = arilou_told_us; if (pStr[LastStack]) { if (pStr[LastStack] != we_vindicator0) Response (pStr[LastStack], Zombies); else DoResponsePhrase (pStr[LastStack], Zombies, shared_phrase_buf); } for (i = 0; i < 4; ++i) { if (i != LastStack && pStr[i]) { if (pStr[i] != we_vindicator0) Response (pStr[i], Zombies); else DoResponsePhrase (pStr[i], Zombies, shared_phrase_buf); } } Response (bye_zombie, CombatIsInevitable); } } static void NormalUmgah (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_up_pre_zombie)) { NPCPhrase (GENERAL_INFO_PRE_ZOMBIE); DISABLE_PHRASE (whats_up_pre_zombie); } else if (PLAYER_SAID (R, want_to_defeat_urquan)) { NPCPhrase (FINE_BY_US); DISABLE_PHRASE (want_to_defeat_urquan); } if (!GET_GAME_STATE (UMGAH_EVIL_BLOBBIES)) Response (evil_blobbies_give_up, CombatIsInevitable); else Response (evil_blobbies_must_die, CombatIsInevitable); if (PHRASE_ENABLED (whats_up_pre_zombie)) Response (whats_up_pre_zombie, NormalUmgah); if (PHRASE_ENABLED (want_to_defeat_urquan)) Response (want_to_defeat_urquan, NormalUmgah); switch (GET_GAME_STATE (UMGAH_MENTIONED_TRICKS)) { case 0: Response (can_we_be_friends, CombatIsInevitable); break; } Response (bye_pre_zombie, CombatIsInevitable); } static void UmgahReward (RESPONSE_REF R) { if (PLAYER_SAID (R, what_before_tpet)) { NPCPhrase (TRKD_SPATHI_AND_ILWRATH); DISABLE_PHRASE (what_before_tpet); } else if (PLAYER_SAID (R, where_caster)) { NPCPhrase (SPATHI_TOOK_THEM); DISABLE_PHRASE (where_caster); } else if (PLAYER_SAID (R, owe_me_big_time)) { NPCPhrase (THANKS); GLOBAL_SIS (TotalBioMass) += 1000 / BIO_CREDIT_VALUE; DISABLE_PHRASE (owe_me_big_time); DISABLE_PHRASE (our_largesse); } else if (PLAYER_SAID (R, our_largesse)) { NPCPhrase (GIVE_LIFEDATA); GLOBAL_SIS (TotalBioMass) += 1000 / BIO_CREDIT_VALUE; DISABLE_PHRASE (our_largesse); DISABLE_PHRASE (owe_me_big_time); } else if (PLAYER_SAID (R, what_do_with_tpet)) { NPCPhrase (TRICK_URQUAN); DISABLE_PHRASE (what_do_with_tpet); } else if (PLAYER_SAID (R, any_jokes)) { NPCPhrase (SURE); DISABLE_PHRASE (any_jokes); } else if (PLAYER_SAID (R, so_what_for_now)) { NPCPhrase (DO_THIS_NOW); DISABLE_PHRASE (so_what_for_now); } if (!GET_GAME_STATE (MET_NORMAL_UMGAH)) { if (PHRASE_ENABLED (what_before_tpet)) Response (what_before_tpet, UmgahReward); else if (PHRASE_ENABLED (where_caster)) Response (where_caster, UmgahReward); } if (PHRASE_ENABLED (owe_me_big_time)) { Response (owe_me_big_time, UmgahReward); Response (our_largesse, UmgahReward); } if (PHRASE_ENABLED (what_do_with_tpet)) Response (what_do_with_tpet, UmgahReward); else if (PHRASE_ENABLED (any_jokes) && GET_GAME_STATE (UMGAH_MENTIONED_TRICKS) < 2) Response (any_jokes, UmgahReward); if (PHRASE_ENABLED (so_what_for_now)) Response (so_what_for_now, UmgahReward); Response (bye_post_zombie, CombatIsInevitable); } static void Intro (void) { BYTE NumVisits; if (GET_GAME_STATE (UMGAH_HOSTILE)) { NumVisits = GET_GAME_STATE (UMGAH_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_HELLO_1); break; case 1: NPCPhrase (HOSTILE_HELLO_2); break; case 2: NPCPhrase (HOSTILE_HELLO_3); break; case 3: NPCPhrase (HOSTILE_HELLO_4); --NumVisits; break; } SET_GAME_STATE (UMGAH_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (GET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES)) { NumVisits = GET_GAME_STATE (UMGAH_VISITS); if (GET_GAME_STATE (TALKING_PET_VISITS)) { switch (NumVisits++) { case 0: NPCPhrase (DESTROY_INTERFERER_1); break; case 1: NPCPhrase (DESTROY_INTERFERER_2); break; case 2: NPCPhrase (DESTROY_INTERFERER_3); break; case 3: NPCPhrase (DESTROY_INTERFERER_4); --NumVisits; break; } SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (GET_GAME_STATE (KNOW_UMGAH_ZOMBIES)) { switch (NumVisits++) { case 0: NPCPhrase (REVEALED_ZOMBIE_HELLO_1); break; case 1: NPCPhrase (REVEALED_ZOMBIE_HELLO_2); break; case 2: NPCPhrase (REVEALED_ZOMBIE_HELLO_3); break; case 3: NPCPhrase (REVEALED_ZOMBIE_HELLO_4); --NumVisits; break; } SET_GAME_STATE (BATTLE_SEGUE, 1); } else { switch (NumVisits++) { case 0: NPCPhrase (UNKNOWN_ZOMBIE_HELLO_1); break; case 1: NPCPhrase (UNKNOWN_ZOMBIE_HELLO_2); break; case 2: NPCPhrase (UNKNOWN_ZOMBIE_HELLO_3); break; case 3: NPCPhrase (UNKNOWN_ZOMBIE_HELLO_4); --NumVisits; break; } Zombies ((RESPONSE_REF)0); } SET_GAME_STATE (UMGAH_VISITS, NumVisits); } else if (!GET_GAME_STATE (TALKING_PET)) { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (UMGAH_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HWLD_PRE_ZOMBIE_HELLO_1); break; case 1: NPCPhrase (HWLD_PRE_ZOMBIE_HELLO_2); break; case 2: NPCPhrase (HWLD_PRE_ZOMBIE_HELLO_3); break; case 3: NPCPhrase (HWLD_PRE_ZOMBIE_HELLO_4); --NumVisits; break; } SET_GAME_STATE (UMGAH_HOME_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (UMGAH_VISITS); switch (NumVisits++) { case 0: NPCPhrase (SPACE_PRE_ZOMBIE_HELLO_1); break; case 1: NPCPhrase (SPACE_PRE_ZOMBIE_HELLO_2); break; case 2: NPCPhrase (SPACE_PRE_ZOMBIE_HELLO_3); break; case 3: NPCPhrase (SPACE_PRE_ZOMBIE_HELLO_4); --NumVisits; break; } SET_GAME_STATE (UMGAH_VISITS, NumVisits); } NormalUmgah ((RESPONSE_REF)0); } else { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NPCPhrase (POST_ZOMBIE_HWLD_HELLO); UmgahReward ((RESPONSE_REF)0); } else { NumVisits = GET_GAME_STATE (UMGAH_VISITS); switch (NumVisits++) { case 0: NPCPhrase (REWARD_AT_HOMEWORLD_1); break; case 1: NPCPhrase (REWARD_AT_HOMEWORLD_2); --NumVisits; break; } SET_GAME_STATE (UMGAH_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 0); } } } static COUNT uninit_umgah (void) { return (0); } static void post_umgah_enc (void) { if (!GET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES)) { SET_GAME_STATE (MET_NORMAL_UMGAH, 1); } } LOCDATAPTR init_umgah_comm (void) { LOCDATAPTR retval; umgah_desc.init_encounter_func = Intro; umgah_desc.post_encounter_func = post_umgah_enc; umgah_desc.uninit_encounter_func = uninit_umgah; umgah_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); umgah_desc.AlienTextBaseline.y = 0; umgah_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if ((GET_GAME_STATE (TALKING_PET) && !GET_GAME_STATE (UMGAH_HOSTILE)) || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &umgah_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/umgah/resinst.h0000600000175000017500000000012610543202026017474 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/supox/0000755000175000017500000000000010552600275015732 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/supox/ifontres.h0000600000175000017500000000004110543202033017705 0ustar joeyjoey#define SUPOX_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/supox/restypes.h0000600000175000017500000000024110543202033017734 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/supox/supox.res0000600000175000017500000000035010543202033017577 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/supox PACKAGE SUPOX_PACKAGE supox.con GFXRES SUPOX_PMAP_ANIM supox.ani FONTRES SUPOX_FONT supox.fon MUSICRES SUPOX_MUSIC supox.mod STRTAB SUPOX_CONVERSATION_PHRASES supox.txt uqm-0.6.2/sc2/src/sc2code/comm/supox/strings.h0000600000175000017500000000523710543202033017561 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, NEUTRAL_SPACE_HELLO_1, NEUTRAL_SPACE_HELLO_2, NEUTRAL_HOMEWORLD_HELLO_1, NEUTRAL_HOMEWORLD_HELLO_2, HOSTILE_SPACE_HELLO_1, HOSTILE_SPACE_HELLO_2, ALLIED_HOMEWORLD_HELLO_1, ALLIED_HOMEWORLD_HELLO_2, ALLIED_HOMEWORLD_HELLO_3, ALLIED_HOMEWORLD_HELLO_4, i_am0, i_am1, WE_ARE_SUPOX, my_ship0, my_ship1, OUR_SHIP, from_alliance0, from_alliance1, FROM_SUPOX, are_you_copying, YEAH_SORRY, why_copy, SYMBIOTS, tell_us_of_your_species, OUR_SPECIES, plants_arent_intelligent, PROVES_WERE_SPECIAL, anyone_around_here, UTWIG_NEARBY, what_relation_to_utwig, UTWIG_ALLIES, whats_wrong_with_utwig, BROKE_ULTRON, whats_ultron, TAKE_ULTRON, what_do_i_do_now, FIX_IT, thanks_now_we_eat_you, HIDEOUS_MONSTERS, got_fixed_ultron, GOOD_GIVE_TO_UTWIG, look_i_repaired_lots, ALMOST_THERE, look_i_slightly_repaired, GREAT_DO_MORE, where_get_repairs, ANCIENT_RHYME, bye_neutral, GOODBYE_NEUTRAL, ABOUT_BATTLE, HELLO_BEFORE_KOHRAH_SPACE_1, HELLO_BEFORE_KOHRAH_SPACE_2, HELLO_DURING_KOHRAH_SPACE_1, HELLO_DURING_KOHRAH_SPACE_2, HELLO_AFTER_KOHRAH_SPACE_1, HELLO_AFTER_KOHRAH_SPACE_2, whats_up_after_space, GENERAL_INFO_AFTER_SPACE_1, GENERAL_INFO_AFTER_SPACE_2, what_now_after_space, DO_THIS_AFTER_SPACE, bye_after_space, GOODBYE_AFTER_SPACE, whats_up_before_space, GENERAL_INFO_BEFORE_SPACE_1, GENERAL_INFO_BEFORE_SPACE_2, what_now_before_space, DO_THIS_BEFORE_SPACE, bye_before_space, GOODBYE_BEFORE_SPACE, how_went_war, how_goes_war, BATTLE_HAPPENS_1, BATTLE_HAPPENS_2, FLEET_ON_WAY, learn_new_info, NO_NEW_INFO, SAMATRA, what_now_homeworld, HOPE_KILL_EACH_OTHER, UP_TO_YOU, can_you_help, HOW_HELP, DONT_NEED, HAVE_4_SHIPS, give_info, GOOD_HINTS, how_is_ultron, ULTRON_IS_GREAT, bye_allied_homeworld, GOODBYE_ALLIED_HOMEWORLD, name_1, name_2, name_3, name_40, name_41, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/supox/igfxres.h0000600000175000017500000000004610543202033017530 0ustar joeyjoey#define SUPOX_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/supox/istrtab.h0000600000175000017500000000012410543202034017527 0ustar joeyjoey#define SUPOX_CONVERSATION_PHRASES 0x00200004L #define SUPOX_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/supox/imusicre.h0000600000175000017500000000004210543202033017675 0ustar joeyjoey#define SUPOX_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/supox/Makeinfo0000600000175000017500000000002610543202033017362 0ustar joeyjoeyuqm_CFILES="supoxc.c" uqm-0.6.2/sc2/src/sc2code/comm/supox/respkg.h0000600000175000017500000000003610543202033017353 0ustar joeyjoeyenum { SUPOX_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/supox/supoxc.c0000600000175000017500000003576210543202033017412 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/supox/resinst.h" #include "comm/supox/strings.h" #include "build.h" static LOCDATA supox_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)SUPOX_PMAP_ANIM, /* AlienFrame */ (FONT)SUPOX_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)SUPOX_COLOR_MAP, /* AlienColorMap */ SUPOX_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ SUPOX_CONVERSATION_PHRASES, /* PlayerPhrases */ 4, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 4, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 10, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 9, /* StartIndex */ 10, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 19, /* StartIndex */ 10, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 29, /* StartIndex */ 13, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 3, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 0); if (PLAYER_SAID (R, bye_neutral)) NPCPhrase (GOODBYE_NEUTRAL); else if (PLAYER_SAID (R, what_do_i_do_now)) NPCPhrase (FIX_IT); else if (PLAYER_SAID (R, thanks_now_we_eat_you)) { NPCPhrase (HIDEOUS_MONSTERS); SET_GAME_STATE (SUPOX_HOSTILE, 1); SET_GAME_STATE (SUPOX_HOME_VISITS, 0); SET_GAME_STATE (SUPOX_VISITS, 0); } else if (PLAYER_SAID (R, bye_after_space)) NPCPhrase (GOODBYE_AFTER_SPACE); else if (PLAYER_SAID (R, bye_before_space)) NPCPhrase (GOODBYE_BEFORE_SPACE); else if (PLAYER_SAID (R, bye_allied_homeworld)) NPCPhrase (GOODBYE_ALLIED_HOMEWORLD); else if (PLAYER_SAID (R, can_you_help)) { NPCPhrase (HOW_HELP); if (ActivateStarShip (SUPOX_SHIP, FEASIBILITY_STUDY) == 0) NPCPhrase (DONT_NEED); else { NPCPhrase (HAVE_4_SHIPS); AlienTalkSegue ((COUNT)~0); ActivateStarShip (SUPOX_SHIP, 4); } } } static void AlliedHome (RESPONSE_REF R); static void AlliedHome (RESPONSE_REF R) { BYTE NumVisits, News; News = GET_GAME_STATE (SUPOX_WAR_NEWS); NumVisits = GET_GAME_STATE (UTWIG_SUPOX_MISSION); if (PLAYER_SAID (R, how_went_war)) { NPCPhrase (ABOUT_BATTLE); News |= (1 << 0); } else if (PLAYER_SAID (R, how_goes_war)) { if (NumVisits == 1) { NPCPhrase (FLEET_ON_WAY); SET_GAME_STATE (SUPOX_WAR_NEWS, 1); } else switch (GET_GAME_STATE (SUPOX_WAR_NEWS)) { case 0: NPCPhrase (BATTLE_HAPPENS_1); News = 1; break; case 1: NPCPhrase (BATTLE_HAPPENS_2); News = 2; break; } DISABLE_PHRASE (how_goes_war); } else if (PLAYER_SAID (R, learn_new_info)) { if (NumVisits < 5) NPCPhrase (NO_NEW_INFO); else { NPCPhrase (SAMATRA); News |= (1 << 1); } DISABLE_PHRASE (learn_new_info); } else if (PLAYER_SAID (R, what_now_homeworld)) { if (NumVisits < 5) NPCPhrase (UP_TO_YOU); else NPCPhrase (HOPE_KILL_EACH_OTHER); DISABLE_PHRASE (what_now_homeworld); } else if (PLAYER_SAID (R, how_is_ultron)) { NPCPhrase (ULTRON_IS_GREAT); DISABLE_PHRASE (how_is_ultron); } SET_GAME_STATE (SUPOX_WAR_NEWS, News); if (NumVisits >= 5) { if (!(News & (1 << 0))) Response (how_went_war, AlliedHome); } else if (PHRASE_ENABLED (how_goes_war) && ((NumVisits == 1 && News == 0) || (NumVisits && News < 2))) Response (how_goes_war, AlliedHome); if (PHRASE_ENABLED (learn_new_info)) Response (learn_new_info, AlliedHome); if (PHRASE_ENABLED (what_now_homeworld)) Response (what_now_homeworld, AlliedHome); if (PHRASE_ENABLED (how_is_ultron)) Response (how_is_ultron, AlliedHome); if (NumVisits == 0) Response (can_you_help, ExitConversation); Response (bye_allied_homeworld, ExitConversation); } static void BeforeKohrAh (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, whats_up_before_space)) { NumVisits = GET_GAME_STATE (SUPOX_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_BEFORE_SPACE_1); break; case 1: NPCPhrase (GENERAL_INFO_BEFORE_SPACE_2); --NumVisits; break; } SET_GAME_STATE (SUPOX_INFO, NumVisits); DISABLE_PHRASE (whats_up_before_space); } else if (PLAYER_SAID (R, what_now_before_space)) { NPCPhrase (DO_THIS_BEFORE_SPACE); DISABLE_PHRASE (what_now_before_space); } if (PHRASE_ENABLED (whats_up_before_space)) Response (whats_up_before_space, BeforeKohrAh); if (PHRASE_ENABLED (what_now_before_space)) Response (what_now_before_space, BeforeKohrAh); Response (bye_before_space, ExitConversation); } static void AfterKohrAh (RESPONSE_REF R) { BYTE NumVisits; if (PLAYER_SAID (R, whats_up_after_space)) { NumVisits = GET_GAME_STATE (SUPOX_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_AFTER_SPACE_1); break; case 1: NPCPhrase (GENERAL_INFO_AFTER_SPACE_2); --NumVisits; break; } SET_GAME_STATE (SUPOX_INFO, NumVisits); DISABLE_PHRASE (whats_up_after_space); } else if (PLAYER_SAID (R, what_now_after_space)) { NPCPhrase (DO_THIS_AFTER_SPACE); DISABLE_PHRASE (what_now_after_space); } if (PHRASE_ENABLED (whats_up_after_space)) Response (whats_up_after_space, AfterKohrAh); if (PHRASE_ENABLED (what_now_after_space)) Response (what_now_after_space, AfterKohrAh); Response (bye_after_space, ExitConversation); } static void NeutralSupox (RESPONSE_REF R) { BYTE i, LastStack, NumVisits; RESPONSE_REF pStr[3]; LastStack = 0; pStr[0] = pStr[1] = pStr[2] = 0; if (PLAYER_SAID (R, i_am0)) { NPCPhrase (WE_ARE_SUPOX); SET_GAME_STATE (SUPOX_STACK1, 1); DISABLE_PHRASE (i_am0); } else if (PLAYER_SAID (R, my_ship0)) { NPCPhrase (OUR_SHIP); SET_GAME_STATE (SUPOX_STACK1, 2); DISABLE_PHRASE (my_ship0); } else if (PLAYER_SAID (R, from_alliance0)) { NPCPhrase (FROM_SUPOX); SET_GAME_STATE (SUPOX_STACK1, 3); DISABLE_PHRASE (from_alliance0); } else if (PLAYER_SAID (R, are_you_copying)) { NPCPhrase (YEAH_SORRY); SET_GAME_STATE (SUPOX_STACK1, 4); } else if (PLAYER_SAID (R, why_copy)) { NPCPhrase (SYMBIOTS); SET_GAME_STATE (SUPOX_STACK1, 5); } else if (PLAYER_SAID (R, tell_us_of_your_species)) { NPCPhrase (OUR_SPECIES); LastStack = 1; SET_GAME_STATE (SUPOX_STACK2, 1); } else if (PLAYER_SAID (R, plants_arent_intelligent)) { NPCPhrase (PROVES_WERE_SPECIAL); SET_GAME_STATE (SUPOX_STACK2, 2); } else if (PLAYER_SAID (R, anyone_around_here)) { NPCPhrase (UTWIG_NEARBY); LastStack = 2; SET_GAME_STATE (SUPOX_WAR_NEWS, 1); ActivateStarShip (UTWIG_SHIP, SPHERE_TRACKING); } else if (PLAYER_SAID (R, what_relation_to_utwig)) { NPCPhrase (UTWIG_ALLIES); LastStack = 2; SET_GAME_STATE (SUPOX_WAR_NEWS, 1); } else if (PLAYER_SAID (R, whats_wrong_with_utwig)) { NPCPhrase (BROKE_ULTRON); LastStack = 2; SET_GAME_STATE (SUPOX_WAR_NEWS, 2); } else if (PLAYER_SAID (R, whats_ultron)) { NPCPhrase (TAKE_ULTRON); SET_GAME_STATE (SUPOX_WAR_NEWS, 0); SET_GAME_STATE (ULTRON_CONDITION, 1); Response (what_do_i_do_now, ExitConversation); Response (thanks_now_we_eat_you, ExitConversation); return; } else if (PLAYER_SAID (R, got_fixed_ultron)) { NPCPhrase (GOOD_GIVE_TO_UTWIG); SET_GAME_STATE (SUPOX_ULTRON_HELP, 1); } else if (PLAYER_SAID (R, look_i_repaired_lots)) { NPCPhrase (ALMOST_THERE); SET_GAME_STATE (SUPOX_ULTRON_HELP, 1); } else if (PLAYER_SAID (R, look_i_slightly_repaired)) { NPCPhrase (GREAT_DO_MORE); SET_GAME_STATE (SUPOX_ULTRON_HELP, 1); } else if (PLAYER_SAID (R, where_get_repairs)) { NPCPhrase (ANCIENT_RHYME); SET_GAME_STATE (SUPOX_ULTRON_HELP, 1); } switch (GET_GAME_STATE (SUPOX_STACK2)) { case 0: pStr[1] = tell_us_of_your_species; break; case 1: pStr[1] = plants_arent_intelligent; break; } switch (GET_GAME_STATE (SUPOX_STACK1)) { case 0: construct_response (shared_phrase_buf, i_am0, GLOBAL_SIS (CommanderName), i_am1, NULL_PTR); pStr[0] = i_am0; pStr[1] = 0; break; case 1: construct_response (shared_phrase_buf, my_ship0, GLOBAL_SIS (ShipName), my_ship1, NULL_PTR); pStr[0] = my_ship0; pStr[1] = 0; break; case 2: { UNICODE buf[ALLIANCE_NAME_BUFSIZE]; GetAllianceName (buf, name_1); construct_response ( shared_phrase_buf, from_alliance0, buf, from_alliance1, NULL_PTR ); } pStr[0] = from_alliance0; pStr[1] = 0; break; case 3: pStr[0] = are_you_copying; pStr[1] = 0; break; case 4: pStr[0] = why_copy; pStr[1] = 0; break; } NumVisits = GET_GAME_STATE (ULTRON_CONDITION); if (NumVisits == 0) { switch (GET_GAME_STATE (SUPOX_WAR_NEWS)) { case 0: if (GET_GAME_STATE (UTWIG_VISITS) || GET_GAME_STATE (UTWIG_HOME_VISITS) || GET_GAME_STATE (BOMB_VISITS)) pStr[2] = what_relation_to_utwig; else pStr[2] = anyone_around_here; break; case 1: pStr[2] = whats_wrong_with_utwig; break; case 2: pStr[2] = whats_ultron; break; } } if (pStr[LastStack]) { if (LastStack != 0 || GET_GAME_STATE (SUPOX_STACK1) > 2) Response (pStr[LastStack], NeutralSupox); else DoResponsePhrase (pStr[LastStack], NeutralSupox, shared_phrase_buf); } for (i = 0; i < 3; ++i) { if (i != LastStack && pStr[i]) { if (i != 0 || GET_GAME_STATE (SUPOX_STACK1) > 2) Response (pStr[i], NeutralSupox); else DoResponsePhrase (pStr[i], NeutralSupox, shared_phrase_buf); } } if (!GET_GAME_STATE (SUPOX_ULTRON_HELP)) { switch (NumVisits) { case 1: Response (where_get_repairs, NeutralSupox); break; case 2: Response (look_i_slightly_repaired, NeutralSupox); break; case 3: Response (look_i_repaired_lots, NeutralSupox); break; case 4: Response (got_fixed_ultron, NeutralSupox); break; } } Response (bye_neutral, ExitConversation); } static void Intro (void) { BYTE NumVisits; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (GET_GAME_STATE (SUPOX_HOSTILE)) { NumVisits = GET_GAME_STATE (SUPOX_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOSTILE_SPACE_HELLO_1); break; case 1: NPCPhrase (HOSTILE_SPACE_HELLO_2); --NumVisits; break; } SET_GAME_STATE (SUPOX_VISITS, NumVisits); SET_GAME_STATE (BATTLE_SEGUE, 0); } else if (ActivateStarShip (SUPOX_SHIP, CHECK_ALLIANCE) & GOOD_GUY) { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (SUPOX_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (ALLIED_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (ALLIED_HOMEWORLD_HELLO_2); break; case 2: NPCPhrase (ALLIED_HOMEWORLD_HELLO_3); break; case 3: NPCPhrase (ALLIED_HOMEWORLD_HELLO_4); --NumVisits; break; } SET_GAME_STATE (SUPOX_HOME_VISITS, NumVisits); AlliedHome ((RESPONSE_REF)0); } else { NumVisits = GET_GAME_STATE (UTWIG_SUPOX_MISSION); if (NumVisits == 1) { NumVisits = GET_GAME_STATE (SUPOX_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_BEFORE_KOHRAH_SPACE_1); break; case 1: NPCPhrase (HELLO_BEFORE_KOHRAH_SPACE_2); --NumVisits; break; } SET_GAME_STATE (SUPOX_VISITS, NumVisits); BeforeKohrAh ((RESPONSE_REF)0); } else if (NumVisits < 5) { NumVisits = GET_GAME_STATE (SUPOX_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_DURING_KOHRAH_SPACE_1); break; case 1: NPCPhrase (HELLO_DURING_KOHRAH_SPACE_2); --NumVisits; break; } SET_GAME_STATE (SUPOX_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (SUPOX_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HELLO_AFTER_KOHRAH_SPACE_1); break; case 1: NPCPhrase (HELLO_AFTER_KOHRAH_SPACE_2); --NumVisits; break; } SET_GAME_STATE (SUPOX_VISITS, NumVisits); AfterKohrAh ((RESPONSE_REF)0); } } } else { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (SUPOX_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (NEUTRAL_HOMEWORLD_HELLO_2); --NumVisits; break; } SET_GAME_STATE (SUPOX_HOME_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (SUPOX_VISITS); switch (NumVisits++) { case 0: NPCPhrase (NEUTRAL_SPACE_HELLO_1); break; case 1: NPCPhrase (NEUTRAL_SPACE_HELLO_2); --NumVisits; break; } SET_GAME_STATE (SUPOX_VISITS, NumVisits); } NeutralSupox ((RESPONSE_REF)0); } } static COUNT uninit_supox (void) { return (0); } static void post_supox_enc (void) { // nothing defined so far } LOCDATAPTR init_supox_comm (void) { LOCDATAPTR retval; supox_desc.init_encounter_func = Intro; supox_desc.post_encounter_func = post_supox_enc; supox_desc.uninit_encounter_func = uninit_supox; supox_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); supox_desc.AlienTextBaseline.y = 0; supox_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if (!GET_GAME_STATE (SUPOX_HOSTILE) || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 0); } else { SET_GAME_STATE (BATTLE_SEGUE, 1); } retval = &supox_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/supox/resinst.h0000600000175000017500000000012610543202034017550 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/yehat/0000755000175000017500000000000010552600275015666 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/yehat/ifontres.h0000600000175000017500000000004110543202032017640 0ustar joeyjoey#define YEHAT_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/yehat/restypes.h0000600000175000017500000000024110543202032017667 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/yehat/yehat.res0000600000175000017500000000056310543202032017474 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/yehat PACKAGE YEHAT_PACKAGE yehat.con GFXRES YEHAT_PMAP_ANIM yehat.ani FONTRES YEHAT_FONT yehat.ani MUSICRES YEHAT_MUSIC yehat.mod PACKAGE YEHAT_PHRASE_PACKAGE yehat.con STRTAB YEHAT_CONVERSATION_PHRASES yehat.txt PATH comm/rebel PACKAGE REBEL_PHRASE_PACKAGE yehat.con STRTAB REBEL_CONVERSATION_PHRASES rebel.txt uqm-0.6.2/sc2/src/sc2code/comm/yehat/strings.h0000600000175000017500000000446110543202032017512 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, HOMEWORLD_HELLO_1, HOMEWORLD_HELLO_2, whats_up_homeworld, GENERAL_INFO_HOMEWORLD_1, GENERAL_INFO_HOMEWORLD_2, i_demand_you_ally_homeworld0, i_demand_you_ally_homeworld1, i_demand_you_ally_homeworld2, i_demand_you_ally_homeworld3, ENEMY_MUST_DIE, at_least_help_us_homeworld, NO_HELP_ENEMY, give_info, NO_INFO_FOR_ENEMY, what_about_pkunk_royalist, PKUNK_ABSORBED_ROYALIST, HATE_PKUNK_ROYALIST, bye_homeworld, GOODBYE_AND_DIE_HOMEWORLD, SPACE_HELLO_1, SPACE_HELLO_2, SPACE_HELLO_3, SPACE_HELLO_4, whats_up_space_1, GENERAL_INFO_SPACE_1, whats_up_space_2, GENERAL_INFO_SPACE_2, whats_up_space_3, GENERAL_INFO_SPACE_3, whats_up_space_4, GENERAL_INFO_SPACE_4, i_demand_you_ally_space0, i_demand_you_ally_space1, i_demand_you_ally_space2, i_demand_you_ally_space3, WE_CANNOT_1, obligation, WE_CANNOT_2, at_least_help_us_space, SORRY_CANNOT, dishonor, HERES_A_HINT, what_about_pkunk_space, PKUNK_ABSORBED_SPACE, HATE_PKUNK_SPACE, bye_space, GO_IN_PEACE, GOODBYE_AND_DIE_SPACE, shofixti_alive_1, shofixti_alive_2, SEND_HIM_OVER_1, SEND_HIM_OVER_2, not_here, not_send, JUST_A_TRICK_1, JUST_A_TRICK_2, ok_send, WE_REVOLT, ROYALIST_SPACE_HELLO_1, ROYALIST_SPACE_HELLO_2, ROYALIST_HOMEWORLD_HELLO_1, ROYALIST_HOMEWORLD_HELLO_2, how_is_rebellion, ROYALIST_REBELLION_1, ROYALIST_REBELLION_2, sorry_about_revolution, ALL_YOUR_FAULT, bye_royalist, GOODBYE_AND_DIE_ROYALIST, name_1, name_2, name_3, name_40, name_41, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/yehat/igfxres.h0000600000175000017500000000004610543202033017464 0ustar joeyjoey#define YEHAT_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/yehat/istrtab.h0000600000175000017500000000020410543202033017461 0ustar joeyjoey#define YEHAT_CONVERSATION_PHRASES 0x00400004L #define REBEL_CONVERSATION_PHRASES 0x00600104L #define YEHAT_COLOR_MAP 0x00200204L uqm-0.6.2/sc2/src/sc2code/comm/yehat/imusicre.h0000600000175000017500000000010310543202032017626 0ustar joeyjoey#define YEHAT_MUSIC 0x00200006L #define REBEL_MUSIC 0x00800106L uqm-0.6.2/sc2/src/sc2code/comm/yehat/Makeinfo0000600000175000017500000000002610543202033017316 0ustar joeyjoeyuqm_CFILES="yehatc.c" uqm-0.6.2/sc2/src/sc2code/comm/yehat/respkg.h0000600000175000017500000000014310543202032017305 0ustar joeyjoeyenum { YEHAT_PACKAGE = 1, YEHAT_PHRASE_PACKAGE, REBEL_PHRASE_PACKAGE, REBEL_MUSIC_PACKAGE, }; uqm-0.6.2/sc2/src/sc2code/comm/yehat/yehatc.c0000600000175000017500000003723510543202033017277 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/yehat/resinst.h" #include "comm/yehat/strings.h" #include "build.h" #include "gameev.h" #include "libs/mathlib.h" static LOCDATA yehat_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)YEHAT_PMAP_ANIM, /* AlienFrame */ (FONT)YEHAT_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* (SIS_TEXT_WIDTH - 16) * 2 / 3, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_MIDDLE, /* AlienTextValign */ (COLORMAP)YEHAT_COLOR_MAP, /* AlienColorMap */ YEHAT_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ YEHAT_CONVERSATION_PHRASES, /* PlayerPhrases */ 15, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { /* right hand-wing tapping keyboard; front guy */ 4, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 10, /* FrameRate */ ONE_SECOND / 4, ONE_SECOND / 2,/* RestartRate */ (1 << 6) | (1 << 7), }, { /* left hand-wing tapping keyboard; front guy */ 7, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 10, /* FrameRate */ ONE_SECOND / 4, ONE_SECOND / 2,/* RestartRate */ (1 << 6) | (1 << 7), }, { 10, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 4) | (1 << 14), }, { 13, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 5), }, { 16, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 6, ONE_SECOND * 3,/* RestartRate */ (1 << 2) | (1 << 14), }, { 21, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 6, ONE_SECOND * 3,/* RestartRate */ (1 << 3), }, { /* right arm-wing rising; front guy */ 26, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 6, ONE_SECOND * 3,/* RestartRate */ (1 << 0) | (1 << 1), }, { /* left arm-wing rising; front guy */ 28, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 15, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND * 6, ONE_SECOND * 3,/* RestartRate */ (1 << 0) | (1 << 1), }, { 30, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 33, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 36, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 39, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 42, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 45, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 30, ONE_SECOND / 30, /* FrameRate */ ONE_SECOND / 30, ONE_SECOND / 30, /* RestartRate */ 0, /* BlockMask */ }, { 48, /* StartIndex */ 4, /* NumFrames */ YOYO_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 30, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ (1 << 2) | (1 << 4), }, }, { /* AlienTransitionDesc - empty */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 3, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void ExitConversation (RESPONSE_REF R) { SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, bye_homeworld)) NPCPhrase (GOODBYE_AND_DIE_HOMEWORLD); else if (PLAYER_SAID (R, bye_royalist)) NPCPhrase (GOODBYE_AND_DIE_ROYALIST); else if (PLAYER_SAID (R, i_demand_you_ally_homeworld0)) { NPCPhrase (ENEMY_MUST_DIE); SET_GAME_STATE (NO_YEHAT_ALLY_HOME, 1); } else if (PLAYER_SAID (R, bye_space)) { if ((BYTE)TFB_Random () & 1) NPCPhrase (GOODBYE_AND_DIE_SPACE); else { NPCPhrase (GO_IN_PEACE); SET_GAME_STATE (BATTLE_SEGUE, 0); } } else if (PLAYER_SAID (R, not_here) || PLAYER_SAID (R, not_send)) { switch (GET_GAME_STATE (YEHAT_REBEL_VISITS)) { case 0: NPCPhrase (JUST_A_TRICK_1); break; case 1: NPCPhrase (JUST_A_TRICK_2); break; } SET_GAME_STATE (YEHAT_REBEL_VISITS, 1); } else if (PLAYER_SAID (R, ok_send)) { NPCPhrase (WE_REVOLT); SET_GAME_STATE (BATTLE_SEGUE, 0); SET_GAME_STATE (YEHAT_CIVIL_WAR, 1); SET_GAME_STATE (YEHAT_VISITS, 0); SET_GAME_STATE (YEHAT_HOME_VISITS, 0); SET_GAME_STATE (YEHAT_REBEL_VISITS, 0); SET_GAME_STATE (YEHAT_REBEL_INFO, 0); SET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK, 0); SET_GAME_STATE (NO_YEHAT_INFO, 0); AddEvent (RELATIVE_EVENT, 0, 0, 0, YEHAT_REBEL_EVENT); } } static void Royalists (RESPONSE_REF R) { if (PLAYER_SAID (R, how_is_rebellion)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (YEHAT_ROYALIST_INFO); switch (NumVisits++) { case 0: NPCPhrase (ROYALIST_REBELLION_1); break; case 1: NPCPhrase (ROYALIST_REBELLION_2); --NumVisits; break; } SET_GAME_STATE (YEHAT_ROYALIST_INFO, NumVisits); DISABLE_PHRASE (how_is_rebellion); } else if (PLAYER_SAID (R, what_about_pkunk_royalist)) { if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK)) NPCPhrase (PKUNK_ABSORBED_ROYALIST); else NPCPhrase (HATE_PKUNK_ROYALIST); SET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK, 1); } else if (PLAYER_SAID (R, sorry_about_revolution)) { NPCPhrase (ALL_YOUR_FAULT); SET_GAME_STATE (NO_YEHAT_INFO, 1); } if (PHRASE_ENABLED (how_is_rebellion)) Response (how_is_rebellion, Royalists); if (!GET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK) && GET_GAME_STATE (PKUNK_VISITS) && GET_GAME_STATE (PKUNK_HOME_VISITS)) Response (what_about_pkunk_royalist, Royalists); if (!GET_GAME_STATE (NO_YEHAT_INFO)) Response (sorry_about_revolution, Royalists); Response (bye_royalist, ExitConversation); } static void StartRevolt (RESPONSE_REF R) { if (PLAYER_SAID (R, shofixti_alive_1)) { NPCPhrase (SEND_HIM_OVER_1); SET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK, 1); } else if (PLAYER_SAID (R, shofixti_alive_2)) NPCPhrase (SEND_HIM_OVER_2); if (ActivateStarShip (SHOFIXTI_SHIP, ESCORTING_FLAGSHIP)) Response (ok_send, ExitConversation); else Response (not_here, ExitConversation); Response (not_send, ExitConversation); } static void YehatHome (RESPONSE_REF R) { if (PLAYER_SAID (R, whats_up_homeworld)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (YEHAT_ROYALIST_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_HOMEWORLD_1); break; case 1: NPCPhrase (GENERAL_INFO_HOMEWORLD_2); --NumVisits; break; } SET_GAME_STATE (YEHAT_ROYALIST_INFO, NumVisits); DISABLE_PHRASE (whats_up_homeworld); } else if (PLAYER_SAID (R, at_least_help_us_homeworld)) { NPCPhrase (NO_HELP_ENEMY); SET_GAME_STATE (NO_YEHAT_HELP_HOME, 1); } else if (PLAYER_SAID (R, give_info)) { NPCPhrase (NO_INFO_FOR_ENEMY); SET_GAME_STATE (NO_YEHAT_INFO, 1); } else if (PLAYER_SAID (R, what_about_pkunk_royalist)) { if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK)) NPCPhrase (PKUNK_ABSORBED_ROYALIST); else NPCPhrase (HATE_PKUNK_ROYALIST); SET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK, 1); } if (PHRASE_ENABLED (whats_up_homeworld)) Response (whats_up_homeworld, YehatHome); if (!GET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK) && GET_GAME_STATE (PKUNK_VISITS) && GET_GAME_STATE (PKUNK_HOME_VISITS)) Response (what_about_pkunk_royalist, YehatHome); if (!GET_GAME_STATE (NO_YEHAT_HELP_HOME)) Response (at_least_help_us_homeworld, YehatHome); if (!GET_GAME_STATE (NO_YEHAT_INFO)) Response (give_info, YehatHome); if (!GET_GAME_STATE (NO_YEHAT_ALLY_HOME)) { UNICODE buf[ALLIANCE_NAME_BUFSIZE]; GetAllianceName (buf, name_1); construct_response ( shared_phrase_buf, i_demand_you_ally_homeworld0, GLOBAL_SIS (CommanderName), i_demand_you_ally_homeworld1, buf, i_demand_you_ally_homeworld2, GLOBAL_SIS (ShipName), i_demand_you_ally_homeworld3, NULL_PTR ); DoResponsePhrase (i_demand_you_ally_homeworld0, ExitConversation, shared_phrase_buf); } Response (bye_homeworld, ExitConversation); } static void YehatSpace (RESPONSE_REF R) { BYTE i, LastStack; RESPONSE_REF pStr[3]; LastStack = 0; pStr[0] = pStr[1] = pStr[2] = 0; if (PLAYER_SAID (R, whats_up_space_1) || PLAYER_SAID (R, whats_up_space_2) || PLAYER_SAID (R, whats_up_space_3) || PLAYER_SAID (R, whats_up_space_4)) { BYTE NumVisits; NumVisits = GET_GAME_STATE (YEHAT_REBEL_INFO); switch (NumVisits++) { case 0: NPCPhrase (GENERAL_INFO_SPACE_1); break; case 1: NPCPhrase (GENERAL_INFO_SPACE_2); break; case 2: NPCPhrase (GENERAL_INFO_SPACE_3); break; case 3: NPCPhrase (GENERAL_INFO_SPACE_4); --NumVisits; break; } SET_GAME_STATE (YEHAT_REBEL_INFO, NumVisits); DISABLE_PHRASE (whats_up_space_1); } else if (PLAYER_SAID (R, i_demand_you_ally_space0)) { NPCPhrase (WE_CANNOT_1); LastStack = 2; SET_GAME_STATE (NO_YEHAT_ALLY_SPACE, 1); } else if (PLAYER_SAID (R, obligation)) { NPCPhrase (WE_CANNOT_2); SET_GAME_STATE (BATTLE_SEGUE, 0); SET_GAME_STATE (NO_YEHAT_ALLY_SPACE, 2); return; } else if (PLAYER_SAID (R, at_least_help_us_space)) { NPCPhrase (SORRY_CANNOT); LastStack = 1; SET_GAME_STATE (NO_YEHAT_HELP_SPACE, 1); } else if (PLAYER_SAID (R, dishonor)) { NPCPhrase (HERES_A_HINT); SET_GAME_STATE (NO_YEHAT_HELP_SPACE, 2); } else if (PLAYER_SAID (R, what_about_pkunk_royalist)) { if (GET_GAME_STATE (YEHAT_ABSORBED_PKUNK)) NPCPhrase (PKUNK_ABSORBED_ROYALIST); else NPCPhrase (HATE_PKUNK_ROYALIST); SET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK, 1); } // SET_FUNCPTR (&PtrDesc, YehatSpace); if (PHRASE_ENABLED (whats_up_space_1)) { switch (GET_GAME_STATE (YEHAT_REBEL_INFO)) { case 0: pStr[0] = whats_up_space_1; break; case 1: pStr[0] = whats_up_space_2; break; case 2: pStr[0] = whats_up_space_3; break; case 3: pStr[0] = whats_up_space_4; break; } } switch (GET_GAME_STATE (NO_YEHAT_HELP_SPACE)) { case 0: pStr[1] = at_least_help_us_space; break; case 1: pStr[1] = dishonor; break; } switch (GET_GAME_STATE (NO_YEHAT_ALLY_SPACE)) { case 0: { UNICODE buf[ALLIANCE_NAME_BUFSIZE]; GetAllianceName (buf, name_1); construct_response ( shared_phrase_buf, i_demand_you_ally_space0, GLOBAL_SIS (CommanderName), i_demand_you_ally_space1, GLOBAL_SIS (ShipName), i_demand_you_ally_space2, buf, i_demand_you_ally_space3, NULL_PTR ); pStr[2] = i_demand_you_ally_space0; break; } case 1: pStr[2] = obligation; break; } if (pStr[LastStack]) { if (pStr[LastStack] != i_demand_you_ally_space0) Response (pStr[LastStack], YehatSpace); else DoResponsePhrase (pStr[LastStack], YehatSpace, shared_phrase_buf); } for (i = 0; i < 3; ++i) { if (i != LastStack && pStr[i]) { if (pStr[i] != i_demand_you_ally_space0) Response (pStr[i], YehatSpace); else DoResponsePhrase (pStr[i], YehatSpace, shared_phrase_buf); } } if (!GET_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK) && GET_GAME_STATE (PKUNK_VISITS) && GET_GAME_STATE (PKUNK_HOME_VISITS)) Response (what_about_pkunk_royalist, YehatSpace); if (GET_GAME_STATE (SHOFIXTI_VISITS)) { switch (GET_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK)) { case 0: Response (shofixti_alive_1, StartRevolt); break; case 1: Response (shofixti_alive_2, StartRevolt); break; } } Response (bye_space, ExitConversation); } static void Intro (void) { BYTE NumVisits; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (GET_GAME_STATE (YEHAT_CIVIL_WAR)) { if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (YEHAT_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (ROYALIST_HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (ROYALIST_HOMEWORLD_HELLO_2); --NumVisits; break; } SET_GAME_STATE (YEHAT_HOME_VISITS, NumVisits); } else { NumVisits = GET_GAME_STATE (YEHAT_VISITS); switch (NumVisits++) { case 0: NPCPhrase (ROYALIST_SPACE_HELLO_1); break; case 1: NPCPhrase (ROYALIST_SPACE_HELLO_2); --NumVisits; break; } SET_GAME_STATE (YEHAT_VISITS, NumVisits); } Royalists ((RESPONSE_REF)0); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7)) { NumVisits = GET_GAME_STATE (YEHAT_HOME_VISITS); switch (NumVisits++) { case 0: NPCPhrase (HOMEWORLD_HELLO_1); break; case 1: NPCPhrase (HOMEWORLD_HELLO_2); --NumVisits; break; } SET_GAME_STATE (YEHAT_HOME_VISITS, NumVisits); YehatHome ((RESPONSE_REF)0); } else { NumVisits = GET_GAME_STATE (YEHAT_VISITS); switch (NumVisits++) { case 0: NPCPhrase (SPACE_HELLO_1); break; case 1: NPCPhrase (SPACE_HELLO_2); break; case 2: NPCPhrase (SPACE_HELLO_3); break; case 3: NPCPhrase (SPACE_HELLO_4); --NumVisits; break; } SET_GAME_STATE (YEHAT_VISITS, NumVisits); YehatSpace ((RESPONSE_REF)0); } } static COUNT uninit_yehat (void) { return (0); } static void post_yehat_enc (void) { // nothing defined so far } LOCDATAPTR init_yehat_comm (void) { LOCDATAPTR retval; yehat_desc.init_encounter_func = Intro; yehat_desc.post_encounter_func = post_yehat_enc; yehat_desc.uninit_encounter_func = uninit_yehat; yehat_desc.AlienTextBaseline.x = SIS_SCREEN_WIDTH * 2 / 3; yehat_desc.AlienTextBaseline.y = 60; yehat_desc.AlienTextWidth = (SIS_TEXT_WIDTH - 16) * 2 / 3; if (LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 1); } else { SET_GAME_STATE (BATTLE_SEGUE, 0); } retval = &yehat_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/yehat/resinst.h0000600000175000017500000000012610543202033017503 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/blackur/0000755000175000017500000000000010552600275016177 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/blackur/ifontres.h0000600000175000017500000000004410543202022020153 0ustar joeyjoey#define BLACKURQ_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/blackur/restypes.h0000600000175000017500000000024110543202022020177 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/blackur/strings.h0000600000175000017500000000425410543202022020022 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, SENSE_EVIL, HELLO_AND_DIE_1, HELLO_AND_DIE_2, HELLO_AND_DIE_3, HELLO_AND_DIE_4, HELLO_AND_DIE_5, HELLO_AND_DIE_6, HELLO_AND_DIE_7, HELLO_AND_DIE_8, HELLO_SAMATRA, WE_KILL_ALL_1, WE_KILL_ALL_2, WE_KILL_ALL_3, WE_KILL_ALL_4, why_kill_all_1, why_kill_all_2, why_kill_all_3, why_kill_all_4, KILL_BECAUSE_1, KILL_BECAUSE_2, KILL_BECAUSE_3, KILL_BECAUSE_4, please_dont_kill_1, WILL_KILL_1, please_dont_kill_2, WILL_KILL_2, please_dont_kill_3, WILL_KILL_3, please_dont_kill_4, WILL_KILL_4, bye_frenzy_1, bye_frenzy_2, bye_frenzy_3, bye_frenzy_4, GOODBYE_AND_DIE_FRENZY_1, GOODBYE_AND_DIE_FRENZY_2, GOODBYE_AND_DIE_FRENZY_3, GOODBYE_AND_DIE_FRENZY_4, threat_1, RESISTANCE_IS_USELESS_1, threat_2, RESISTANCE_IS_USELESS_2, threat_3, RESISTANCE_IS_USELESS_3, threat_4, RESISTANCE_IS_USELESS_4, key_phrase, RESPONSE_TO_KEY_PHRASE, why_do_you_destroy, WE_WERE_SLAVES, relationship_with_urquan, WE_ARE_URQUAN_TOO, what_about_culture, BONE_GARDENS, how_leave_me_alone, YOU_DIE, guess_thats_all, THEN_DIE, what_are_you_hovering_over, BONE_PILE, you_sure_are_creepy, YES_CREEPY, stop_that_gross_blinking, DIE_HUMAN, plead_1, PLEADING_IS_USELESS_1, plead_2, PLEADING_IS_USELESS_2, plead_3, PLEADING_IS_USELESS_3, plead_4, PLEADING_IS_USELESS_4, bye, GOODBYE_AND_DIE, GAME_OVER_DUDE, OUT_TAKES, }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/blackur/igfxres.h0000600000175000017500000000005110543202022017767 0ustar joeyjoey#define BLACKURQ_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/blackur/istrtab.h0000600000175000017500000000013210543202022017770 0ustar joeyjoey#define BLACKURQ_CONVERSATION_PHRASES 0x00200004L #define BLACKURQ_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/blackur/imusicre.h0000600000175000017500000000004510543202022020143 0ustar joeyjoey#define BLACKURQ_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/blackur/blackurc.c0000600000175000017500000003054610543202022020115 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/blackur/resinst.h" #include "comm/blackur/strings.h" static LOCDATA blackurq_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)BLACKURQ_PMAP_ANIM, /* AlienFrame */ (FONT)BLACKURQ_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ (COLORMAP)BLACKURQ_COLOR_MAP, /* AlienColorMap */ BLACKURQ_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ BLACKURQ_CONVERSATION_PHRASES, /* PlayerPhrases */ 8, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 7, /* StartIndex */ 6, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 13, /* StartIndex */ 7, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 20, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 23, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 26, /* StartIndex */ 3, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 29, /* StartIndex */ 4, /* NumFrames */ RANDOM_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND / 10, 0, /* RestartRate */ 0, /* BlockMask */ }, { 33, /* StartIndex */ 5, /* NumFrames */ CIRCULAR_ANIM | WAIT_TALKING, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 38, /* StartIndex */ 4, /* NumFrames */ CIRCULAR_ANIM, /* AnimFlags */ ONE_SECOND / 10, 0, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 1, /* StartIndex */ 2, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 6, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 2, /* StartIndex */ 5, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, NULL_PTR, /* AlienNumberSpeech - none */ }; static void CombatIsInevitable (RESPONSE_REF R) { BYTE NumVisits; SET_GAME_STATE (BATTLE_SEGUE, 1); if (PLAYER_SAID (R, bye)) { if (GET_GAME_STATE (KOHR_AH_BYES) == 0) NPCPhrase (GOODBYE_AND_DIE); else NPCPhrase (DIE_HUMAN /* GOODBYE_AND_DIE_2 */); SET_GAME_STATE (KOHR_AH_BYES, 1); } else if (PLAYER_SAID (R, guess_thats_all)) NPCPhrase (THEN_DIE); else if (PLAYER_SAID (R, what_are_you_hovering_over)) { NPCPhrase (BONE_PILE); SET_GAME_STATE (KOHR_AH_INFO, 1); } else if (PLAYER_SAID (R, you_sure_are_creepy)) { NPCPhrase (YES_CREEPY); SET_GAME_STATE (KOHR_AH_INFO, 2); } else if (PLAYER_SAID (R, stop_that_gross_blinking)) { NPCPhrase (DIE_HUMAN); SET_GAME_STATE (KOHR_AH_INFO, 3); } else if (PLAYER_SAID (R, threat_1) || PLAYER_SAID (R, threat_2) || PLAYER_SAID (R, threat_3) || PLAYER_SAID (R, threat_4)) { NumVisits = GET_GAME_STATE (KOHR_AH_REASONS); switch (NumVisits++) { case 0: NPCPhrase (RESISTANCE_IS_USELESS_1); break; case 1: NPCPhrase (RESISTANCE_IS_USELESS_2); break; case 2: NPCPhrase (RESISTANCE_IS_USELESS_3); break; case 3: NPCPhrase (RESISTANCE_IS_USELESS_4); --NumVisits; break; } SET_GAME_STATE (KOHR_AH_REASONS, NumVisits); } else if (PLAYER_SAID (R, plead_1) || PLAYER_SAID (R, plead_2) || PLAYER_SAID (R, plead_3) || PLAYER_SAID (R, plead_4)) { NumVisits = GET_GAME_STATE (KOHR_AH_PLEAD); switch (NumVisits++) { case 0: NPCPhrase (PLEADING_IS_USELESS_1); break; case 1: NPCPhrase (PLEADING_IS_USELESS_2); break; case 2: // This response disabled due to lack of a speech file. // NPCPhrase (PLEADING_IS_USELESS_3); // break; case 3: NPCPhrase (PLEADING_IS_USELESS_4); --NumVisits; break; } SET_GAME_STATE (KOHR_AH_PLEAD, NumVisits); } else if (PLAYER_SAID (R, why_kill_all_1) || PLAYER_SAID (R, why_kill_all_2) || PLAYER_SAID (R, why_kill_all_3) || PLAYER_SAID (R, why_kill_all_4)) { NumVisits = GET_GAME_STATE (KOHR_AH_REASONS); switch (NumVisits++) { case 0: NPCPhrase (KILL_BECAUSE_1); break; case 1: NPCPhrase (KILL_BECAUSE_2); break; case 2: NPCPhrase (KILL_BECAUSE_3); break; case 3: NPCPhrase (KILL_BECAUSE_4); --NumVisits; break; } SET_GAME_STATE (KOHR_AH_REASONS, NumVisits); } else if (PLAYER_SAID (R, please_dont_kill_1) || PLAYER_SAID (R, please_dont_kill_2) || PLAYER_SAID (R, please_dont_kill_3) || PLAYER_SAID (R, please_dont_kill_4)) { NumVisits = GET_GAME_STATE (KOHR_AH_PLEAD); switch (NumVisits++) { case 0: NPCPhrase (WILL_KILL_1); break; case 1: NPCPhrase (WILL_KILL_2); break; case 2: NPCPhrase (WILL_KILL_3); break; case 3: NPCPhrase (WILL_KILL_4); --NumVisits; break; } SET_GAME_STATE (KOHR_AH_PLEAD, NumVisits); } else if (PLAYER_SAID (R, bye_frenzy_1) || PLAYER_SAID (R, bye_frenzy_2) || PLAYER_SAID (R, bye_frenzy_3) || PLAYER_SAID (R, bye_frenzy_4)) { NumVisits = GET_GAME_STATE (KOHR_AH_INFO); switch (NumVisits++) { case 0: NPCPhrase (GOODBYE_AND_DIE_FRENZY_1); break; case 1: NPCPhrase (GOODBYE_AND_DIE_FRENZY_2); break; case 2: NPCPhrase (GOODBYE_AND_DIE_FRENZY_3); break; case 3: NPCPhrase (GOODBYE_AND_DIE_FRENZY_4); --NumVisits; break; } SET_GAME_STATE (KOHR_AH_INFO, NumVisits); } } static void Frenzy (RESPONSE_REF R) { (void) R; // ignored switch (GET_GAME_STATE (KOHR_AH_REASONS)) { case 0: Response (why_kill_all_1, CombatIsInevitable); break; case 1: Response (why_kill_all_2, CombatIsInevitable); break; case 2: Response (why_kill_all_3, CombatIsInevitable); break; case 3: Response (why_kill_all_4, CombatIsInevitable); break; } switch (GET_GAME_STATE (KOHR_AH_PLEAD)) { case 0: Response (please_dont_kill_1, CombatIsInevitable); break; case 1: Response (please_dont_kill_2, CombatIsInevitable); break; case 2: Response (please_dont_kill_3, CombatIsInevitable); break; case 3: Response (please_dont_kill_4, CombatIsInevitable); break; } switch (GET_GAME_STATE (KOHR_AH_INFO)) { case 0: Response (bye_frenzy_1, CombatIsInevitable); break; case 1: Response (bye_frenzy_2, CombatIsInevitable); break; case 2: Response (bye_frenzy_3, CombatIsInevitable); break; case 3: Response (bye_frenzy_4, CombatIsInevitable); break; } } static void KohrAhStory (RESPONSE_REF R) { if (PLAYER_SAID (R, key_phrase)) { NPCPhrase (RESPONSE_TO_KEY_PHRASE); SET_GAME_STATE (KNOW_KOHR_AH_STORY, 2); } else if (PLAYER_SAID (R, why_do_you_destroy)) { NPCPhrase (WE_WERE_SLAVES); DISABLE_PHRASE (why_do_you_destroy); } else if (PLAYER_SAID (R, relationship_with_urquan)) { NPCPhrase (WE_ARE_URQUAN_TOO); DISABLE_PHRASE (relationship_with_urquan); } else if (PLAYER_SAID (R, what_about_culture)) { NPCPhrase (BONE_GARDENS); DISABLE_PHRASE (what_about_culture); } else if (PLAYER_SAID (R, how_leave_me_alone)) { NPCPhrase (YOU_DIE); DISABLE_PHRASE (how_leave_me_alone); } if (PHRASE_ENABLED (why_do_you_destroy)) Response (why_do_you_destroy, KohrAhStory); if (PHRASE_ENABLED (relationship_with_urquan)) Response (relationship_with_urquan, KohrAhStory); if (PHRASE_ENABLED (what_about_culture)) Response (what_about_culture, KohrAhStory); if (PHRASE_ENABLED (how_leave_me_alone)) Response (how_leave_me_alone, KohrAhStory); Response (guess_thats_all, CombatIsInevitable); } static void DieHuman (RESPONSE_REF R) { (void) R; // ignored switch (GET_GAME_STATE (KOHR_AH_REASONS)) { case 0: Response (threat_1, CombatIsInevitable); break; case 1: Response (threat_2, CombatIsInevitable); break; case 2: Response (threat_3, CombatIsInevitable); break; case 3: Response (threat_4, CombatIsInevitable); break; } if (GET_GAME_STATE (KNOW_KOHR_AH_STORY) == 1) { Response (key_phrase, KohrAhStory); } switch (GET_GAME_STATE (KOHR_AH_INFO)) { case 0: Response (what_are_you_hovering_over, CombatIsInevitable); break; case 1: Response (you_sure_are_creepy, CombatIsInevitable); break; case 2: Response (stop_that_gross_blinking, CombatIsInevitable); break; } switch (GET_GAME_STATE (KOHR_AH_PLEAD)) { case 0: Response (plead_1, CombatIsInevitable); break; case 1: Response (plead_2, CombatIsInevitable); break; case 2: // This response disabled due to lack of a speech file. // Response (plead_3, CombatIsInevitable); // break; case 3: Response (plead_4, CombatIsInevitable); break; } Response (bye, CombatIsInevitable); } static void Intro (void) { DWORD GrpOffs; if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { NPCPhrase (OUT_TAKES); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (GET_GAME_STATE (KOHR_AH_KILLED_ALL)) { NPCPhrase (GAME_OVER_DUDE); SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (!GET_GAME_STATE (KOHR_AH_SENSES_EVIL) && GET_GAME_STATE (TALKING_PET_ON_SHIP)) { NPCPhrase (SENSE_EVIL); SET_GAME_STATE (KOHR_AH_SENSES_EVIL, 1); } GrpOffs = GET_GAME_STATE_32 (SAMATRA_GRPOFFS0); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && GLOBAL (BattleGroupRef) && GLOBAL (BattleGroupRef) == GrpOffs) { NPCPhrase (HELLO_SAMATRA); SET_GAME_STATE (AWARE_OF_SAMATRA, 1); SET_GAME_STATE (BATTLE_SEGUE, 1); } else { BYTE NumVisits; NumVisits = GET_GAME_STATE (KOHR_AH_VISITS); if (GET_GAME_STATE (KOHR_AH_FRENZY)) { switch (NumVisits++) { case 0: NPCPhrase (WE_KILL_ALL_1); break; case 1: NPCPhrase (WE_KILL_ALL_2); break; case 2: NPCPhrase (WE_KILL_ALL_3); break; case 3: NPCPhrase (WE_KILL_ALL_4); --NumVisits; break; } Frenzy ((RESPONSE_REF)0); } else { switch (NumVisits++) { case 0: NPCPhrase (HELLO_AND_DIE_1); break; case 1: NPCPhrase (HELLO_AND_DIE_2); break; case 2: NPCPhrase (HELLO_AND_DIE_3); break; case 3: NPCPhrase (HELLO_AND_DIE_4); --NumVisits; break; } DieHuman ((RESPONSE_REF)0); } SET_GAME_STATE (KOHR_AH_VISITS, NumVisits); } } static COUNT uninit_blackurq (void) { return (0); } static void post_blackurq_enc (void) { // nothing defined so far } LOCDATAPTR init_blackurq_comm (void) { LOCDATAPTR retval; blackurq_desc.init_encounter_func = Intro; blackurq_desc.post_encounter_func = post_blackurq_enc; blackurq_desc.uninit_encounter_func = uninit_blackurq; blackurq_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); blackurq_desc.AlienTextBaseline.y = 0; blackurq_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; if (!GET_GAME_STATE (KOHR_AH_KILLED_ALL) && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) { SET_GAME_STATE (BATTLE_SEGUE, 1); } else { SET_GAME_STATE (BATTLE_SEGUE, 0); } retval = &blackurq_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/blackur/Makeinfo0000600000175000017500000000003010543202022017620 0ustar joeyjoeyuqm_CFILES="blackurc.c" uqm-0.6.2/sc2/src/sc2code/comm/blackur/respkg.h0000600000175000017500000000004110543202022017612 0ustar joeyjoeyenum { BLACKURQ_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/blackur/blackur.res0000600000175000017500000000040110543202022020304 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/blackur PACKAGE BLACKURQ_PACKAGE blackur.con GFXRES BLACKURQ_PMAP_ANIM blackur.ani FONTRES BLACKURQ_FONT blackur.fon MUSICRES BLACKURQ_MUSIC blackur.mod STRTAB BLACKURQ_CONVERSATION_PHRASES blackur.txt uqm-0.6.2/sc2/src/sc2code/comm/blackur/resinst.h0000600000175000017500000000012610543202022020012 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/comm/melnorm/0000755000175000017500000000000010552600275016225 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/comm/melnorm/ifontres.h0000600000175000017500000000004410543202031020201 0ustar joeyjoey#define MELNORME_FONT 0x00200003L uqm-0.6.2/sc2/src/sc2code/comm/melnorm/restypes.h0000600000175000017500000000024110543202031020225 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/comm/melnorm/melnorm.res0000600000175000017500000000045110543202031020365 0ustar joeyjoeyINCLUDE ../../star3do.typ PATH comm/melnorm PACKAGE MELNORME_PACKAGE melnorm.con GFXRES MELNORME_PMAP_ANIM melnorm.ani FONTRES MELNORME_FONT melnorm.fon MUSICRES MELNORME_MUSIC melnorm.mod STRTAB MELNORME_CONVERSATION_PHRASES melnorm.txt STRTAB MELNORME_COLOR_MAP melnorm.ct uqm-0.6.2/sc2/src/sc2code/comm/melnorm/strings.h0000600000175000017500000001363410543202031020052 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGS_H #define _STRINGS_H enum { NULL_PHRASE, HELLO_NOW_DOWN_TO_BUSINESS_1, HELLO_NOW_DOWN_TO_BUSINESS_2, HELLO_NOW_DOWN_TO_BUSINESS_3, KNOW_OF_YOU, how_know, KNOW_BECAUSE, what_about_yourselves, NO_TALK_ABOUT_OURSELVES, what_factors, FACTORS_ARE, what_about_universe, NO_FREE_LUNCH, giving_is_good_1, GIVING_IS_BAD_1, giving_is_good_2, GIVING_IS_BAD_2, get_on_with_business, trade_is_for_the_weak, WERE_NOT_AFRAID, no_trade_now, OK_NO_TRADE_NOW_BYE, HELLO_AND_DOWN_TO_BUSINESS_1, HELLO_AND_DOWN_TO_BUSINESS_2, HELLO_AND_DOWN_TO_BUSINESS_3, HELLO_AND_DOWN_TO_BUSINESS_4, HELLO_AND_DOWN_TO_BUSINESS_5, HELLO_AND_DOWN_TO_BUSINESS_6, HELLO_AND_DOWN_TO_BUSINESS_7, HELLO_AND_DOWN_TO_BUSINESS_8, HELLO_AND_DOWN_TO_BUSINESS_9, HELLO_AND_DOWN_TO_BUSINESS_10, whats_my_credit, HELLO_SLIGHTLY_ANGRY_1, HELLO_SLIGHTLY_ANGRY_2, HELLO_SLIGHTLY_ANGRY_3, explore_relationship, EXAMPLE_OF_RELATIONSHIP, excuse_1, NO_EXCUSE_1, excuse_2, NO_EXCUSE_2, excuse_3, NO_EXCUSE_3, we_apologize, APOLOGY_ACCEPTED, so_we_can_attack, DECEITFUL_HUMAN, bye_melnorme_slightly_angry, MELNORME_SLIGHTLY_ANGRY_GOODBYE, HELLO_HATE_YOU_1, HELLO_HATE_YOU_2, HELLO_HATE_YOU_3, well_if_thats_the_way_you_feel, you_hate_us_so_we_go_away, HATE_YOU_GOODBYE, WE_FIGHT_AGAIN, RESCUE_EXPLANATION, RESCUE_AGAIN_1, RESCUE_AGAIN_2, RESCUE_AGAIN_3, RESCUE_AGAIN_4, RESCUE_AGAIN_5, CHANGED_MIND, no_changed_mind, yes_changed_mind, SHOULD_WE_HELP_YOU, yes_help, no_help, RESCUE_OFFER, RESCUE_TANKS, RESCUE_HOME, take_it, leave_it, HAPPY_TO_HAVE_RESCUED, MAYBE_SEE_YOU_LATER, GOODBYE_AND_GOODLUCK, GOODBYE_AND_GOODLUCK_AGAIN, HELLO_PISSED_OFF_1, HELLO_PISSED_OFF_2, HELLO_PISSED_OFF_3, beg_forgiveness, LOTS_TO_MAKE_UP_FOR, you_are_so_right, ONE_LAST_CHANCE, ok_strip_me, no_strip_now, NOT_WORTH_STRIPPING, FAIR_JUSTICE, bye_melnorme_pissed_off, MELNORME_PISSED_OFF_GOODBYE, fight_some_more, OK_FIGHT_SOME_MORE, why_blue_light, BLUE_IS_MAD, we_strong_1, YOU_NOT_STRONG_1, we_strong_2, YOU_NOT_STRONG_2, we_strong_3, YOU_NOT_STRONG_3, just_testing, REALLY_TESTING, yes_really_testing, TEST_RESULTS, youre_on, YOU_GIVE_US_NO_CHOICE, TRADING_INFO, BUY_OR_SELL, goodbye, why_turned_purple, buy, sell, TURNED_PURPLE_BECAUSE, NOTHING_TO_SELL, WHAT_TO_SELL, OK_DONE_SELLING, sell_life_data, SOLD_LIFE_DATA1, SOLD_LIFE_DATA2, SOLD_LIFE_DATA3, sell_rainbow_locations, SOLD_RAINBOW_LOCATIONS1, SOLD_RAINBOW_LOCATIONS2, SOLD_RAINBOW_LOCATIONS3, sell_precursor_find, SOLD_PRECURSOR_FIND, changed_mind_no_sell, done_selling, NEED_CREDIT, WHAT_TO_BUY, WHAT_MORE_TO_BUY, OK_DONE_BUYING, buy_fuel, done_buying, be_leaving_now, HOW_MUCH_FUEL, buy_1_fuel, GOT_FUEL, buy_5_fuel, buy_10_fuel, buy_25_fuel, done_buying_fuel, FRIENDLY_GOODBYE, CREDIT_IS0, CREDIT_IS1, NEED_MORE_CREDIT0, NEED_MORE_CREDIT1, BUY_FUEL_INTRO, NO_ROOM_FOR_FUEL, buy_info, buy_technology, buy_current_events, buy_alien_races, buy_history, done_buying_info, no_buy_info, BUY_INFO_INTRO, OK_BUY_INFO, OK_NO_BUY_INFO, OK_DONE_BUYING_INFO, OK_BUY_EVENT_1, OK_BUY_EVENT_2, OK_BUY_EVENT_3, OK_BUY_EVENT_4, OK_BUY_EVENT_5, OK_BUY_EVENT_6, OK_BUY_EVENT_7, OK_BUY_EVENT_8, OK_BUY_ALIEN_RACE_1, OK_BUY_ALIEN_RACE_2, OK_BUY_ALIEN_RACE_3, OK_BUY_ALIEN_RACE_4, OK_BUY_ALIEN_RACE_5, OK_BUY_ALIEN_RACE_6, OK_BUY_ALIEN_RACE_7, OK_BUY_ALIEN_RACE_8, OK_BUY_ALIEN_RACE_9, OK_BUY_ALIEN_RACE_10, OK_BUY_ALIEN_RACE_11, OK_BUY_ALIEN_RACE_12, OK_BUY_ALIEN_RACE_13, OK_BUY_ALIEN_RACE_14, OK_BUY_ALIEN_RACE_15, OK_BUY_ALIEN_RACE_16, OK_BUY_HISTORY_1, OK_BUY_HISTORY_2, OK_BUY_HISTORY_3, OK_BUY_HISTORY_4, OK_BUY_HISTORY_5, OK_BUY_HISTORY_6, OK_BUY_HISTORY_7, OK_BUY_HISTORY_8, OK_BUY_HISTORY_9, INFO_ALL_GONE, buy_new_tech, no_buy_new_tech, done_buying_new_tech, fill_me_up, OK_FILL_YOU_UP, BUY_NEW_TECH_INTRO, OK_BUY_NEW_TECH, OK_NO_BUY_NEW_TECH, OK_DONE_BUYING_NEW_TECH, OK_DONE_BUYING_FUEL, NEW_TECH_1, NEW_TECH_2, NEW_TECH_3, NEW_TECH_4, NEW_TECH_5, NEW_TECH_6, NEW_TECH_7, NEW_TECH_8, NEW_TECH_9, NEW_TECH_10, NEW_TECH_11, NEW_TECH_12, NEW_TECH_13, OK_BUY_NEW_TECH_1, OK_BUY_NEW_TECH_2, OK_BUY_NEW_TECH_3, OK_BUY_NEW_TECH_4, OK_BUY_NEW_TECH_5, OK_BUY_NEW_TECH_6, OK_BUY_NEW_TECH_7, OK_BUY_NEW_TECH_8, OK_BUY_NEW_TECH_9, OK_BUY_NEW_TECH_10, OK_BUY_NEW_TECH_11, OK_BUY_NEW_TECH_12, OK_BUY_NEW_TECH_13, CHARITY, NEW_TECH_ALL_GONE, we_are_from_alliance0, STRIP_HEAD, LANDERS, THRUSTERS, JETS, PODS, BAYS, DYNAMOS, FURNACES, GUNS, BLASTERS, CANNONS, TRACKERS, DEFENSES, name_1, name_2, name_3, name_40, name_41, ENUMERATE_ONE, ENUMERATE_TWO, ENUMERATE_THREE, ENUMERATE_FOUR, ENUMERATE_FIVE, ENUMERATE_SIX, ENUMERATE_SEVEN, ENUMERATE_EIGHT, ENUMERATE_NINE, ENUMERATE_TEN, ENUMERATE_ELEVEN, ENUMERATE_TWELVE, ENUMERATE_THIRTEEN, ENUMERATE_FOURTEEN, ENUMERATE_FIFTEEN, ENUMERATE_SIXTEEN, END_LIST_WITH_AND, ENUMERATE_ZERO, ENUMERATE_SEVENTEEN, ENUMERATE_EIGHTEEN, ENUMERATE_NINETEEN, ENUMERATE_TWENTY, ENUMERATE_THIRTY, ENUMERATE_FOURTY, ENUMERATE_FIFTY, ENUMERATE_SIXTY, ENUMERATE_SEVENTY, ENUMERATE_EIGHTY, ENUMERATE_NINETY, ENUMERATE_HUNDRED, ENUMERATE_THOUSAND }; #endif /* _STRINGS_H */ uqm-0.6.2/sc2/src/sc2code/comm/melnorm/igfxres.h0000600000175000017500000000005110543202031020015 0ustar joeyjoey#define MELNORME_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/comm/melnorm/istrtab.h0000600000175000017500000000013310543202031020017 0ustar joeyjoey#define MELNORME_CONVERSATION_PHRASES 0x00200004L #define MELNORME_COLOR_MAP 0x00200104L uqm-0.6.2/sc2/src/sc2code/comm/melnorm/imusicre.h0000600000175000017500000000004510543202031020171 0ustar joeyjoey#define MELNORME_MUSIC 0x00200006L uqm-0.6.2/sc2/src/sc2code/comm/melnorm/melnorm.c0000600000175000017500000012066710543202031020032 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "comm/commall.h" #include "comm/melnorm/resinst.h" #include "comm/melnorm/strings.h" #include "gameev.h" #include "setup.h" #include "shipcont.h" #include "libs/inplib.h" #include "libs/mathlib.h" #define NUM_HISTORY_ITEMS 9 #define NUM_EVENT_ITEMS 8 #define NUM_ALIEN_RACE_ITEMS 16 #define NUM_TECH_ITEMS 13 static NUMBER_SPEECH_DESC melnorme_numbers_english; static LOCDATA melnorme_desc = { NULL_PTR, /* init_encounter_func */ NULL_PTR, /* post_encounter_func */ NULL_PTR, /* uninit_encounter_func */ (FRAME)MELNORME_PMAP_ANIM, /* AlienFrame */ (FONT)MELNORME_FONT, /* AlienFont */ WHITE_COLOR, /* AlienTextFColor */ BLACK_COLOR, /* AlienTextBColor */ {0, 0}, /* AlienTextBaseline */ 0, /* SIS_TEXT_WIDTH - 16, */ /* AlienTextWidth */ ALIGN_CENTER, /* AlienTextAlign */ VALIGN_TOP, /* AlienTextValign */ MELNORME_COLOR_MAP, /* AlienColorMap */ MELNORME_MUSIC, /* AlienSong */ 0, /* AlienAltSong */ 0, /* AlienSongFlags */ MELNORME_CONVERSATION_PHRASES, /* PlayerPhrases */ 4, /* NumAnimations */ { /* AlienAmbientArray (ambient animations) */ { 6, /* StartIndex */ 5, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 12, 0, /* FrameRate */ ONE_SECOND * 4, ONE_SECOND * 4,/* RestartRate */ (1 << 1), /* BlockMask */ }, { 11, /* StartIndex */ 9, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 20, 0, /* FrameRate */ ONE_SECOND * 4, ONE_SECOND * 4,/* RestartRate */ (1 << 0), /* BlockMask */ }, { 20, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, { 22, /* StartIndex */ 2, /* NumFrames */ YOYO_ANIM, /* AnimFlags */ ONE_SECOND / 10, ONE_SECOND / 15, /* FrameRate */ ONE_SECOND, ONE_SECOND * 3, /* RestartRate */ 0, /* BlockMask */ }, }, { /* AlienTransitionDesc */ 0, /* StartIndex */ 0, /* NumFrames */ 0, /* AnimFlags */ 0, 0, /* FrameRate */ 0, 0, /* RestartRate */ 0, /* BlockMask */ }, { /* AlienTalkDesc */ 1, /* StartIndex */ 5, /* NumFrames */ 0, /* AnimFlags */ ONE_SECOND / 15, 0, /* FrameRate */ ONE_SECOND / 12, 0, /* RestartRate */ 0, /* BlockMask */ }, &melnorme_numbers_english, /* AlienNumberSpeech - default */ }; static COUNT melnorme_digit_names[] = { ENUMERATE_ZERO, ENUMERATE_ONE, ENUMERATE_TWO, ENUMERATE_THREE, ENUMERATE_FOUR, ENUMERATE_FIVE, ENUMERATE_SIX, ENUMERATE_SEVEN, ENUMERATE_EIGHT, ENUMERATE_NINE }; static COUNT melnorme_teen_names[] = { ENUMERATE_TEN, ENUMERATE_ELEVEN, ENUMERATE_TWELVE, ENUMERATE_THIRTEEN, ENUMERATE_FOURTEEN, ENUMERATE_FIFTEEN, ENUMERATE_SIXTEEN, ENUMERATE_SEVENTEEN, ENUMERATE_EIGHTEEN, ENUMERATE_NINETEEN }; static COUNT melnorme_tens_names[] = { 0, /* invalid */ 0, /* skip digit */ ENUMERATE_TWENTY, ENUMERATE_THIRTY, ENUMERATE_FOURTY, ENUMERATE_FIFTY, ENUMERATE_SIXTY, ENUMERATE_SEVENTY, ENUMERATE_EIGHTY, ENUMERATE_NINETY }; static NUMBER_SPEECH_DESC melnorme_numbers_english = { 5, /* NumDigits */ { { /* 1000-999999 */ 1000, /* Divider */ 0, /* Subtrahend */ NULL, /* StrDigits - recurse */ NULL, /* Names - not used */ ENUMERATE_THOUSAND /* CommonIndex */ }, { /* 100-999 */ 100, /* Divider */ 0, /* Subtrahend */ melnorme_digit_names, /* StrDigits */ NULL, /* Names - not used */ ENUMERATE_HUNDRED /* CommonIndex */ }, { /* 20-99 */ 10, /* Divider */ 0, /* Subtrahend */ melnorme_tens_names, /* StrDigits */ NULL, /* Names - not used */ 0 /* CommonIndex - not used */ }, { /* 10-19 */ 1, /* Divider */ 10, /* Subtrahend */ melnorme_teen_names, /* StrDigits */ NULL, /* Names - not used */ 0 /* CommonIndex - not used */ }, { /* 0-9 */ 1, /* Divider */ 0, /* Subtrahend */ melnorme_digit_names, /* StrDigits */ NULL, /* Names - not used */ 0 /* CommonIndex - not used */ } } }; static void DoFirstMeeting (RESPONSE_REF R); static COUNT ShipWorth (void) { BYTE i; SBYTE crew_pods; COUNT worth; worth = GLOBAL_SIS (NumLanders) * GLOBAL (ModuleCost[PLANET_LANDER]); for (i = 0; i < NUM_DRIVE_SLOTS; ++i) { if (GLOBAL_SIS (DriveSlots[i]) < EMPTY_SLOT) worth += GLOBAL (ModuleCost[FUSION_THRUSTER]); } for (i = 0; i < NUM_JET_SLOTS; ++i) { if (GLOBAL_SIS (JetSlots[i]) < EMPTY_SLOT) worth += GLOBAL (ModuleCost[TURNING_JETS]); } crew_pods = -(SBYTE)( (GLOBAL_SIS (CrewEnlisted) + CREW_POD_CAPACITY - 1) / CREW_POD_CAPACITY ); for (i = 0; i < NUM_MODULE_SLOTS; ++i) { BYTE which_module; which_module = GLOBAL_SIS (ModuleSlots[i]); if (which_module < BOMB_MODULE_0 && (which_module != CREW_POD || ++crew_pods > 0)) { worth += GLOBAL (ModuleCost[which_module]); } } return (worth); } static COUNT rescue_fuel; static SIS_STATE SIS_copy; static BOOLEAN StripShip (COUNT fuel_required) { BYTE i, which_module; SBYTE crew_pods; SET_GAME_STATE (MELNORME_RESCUE_REFUSED, 0); crew_pods = -(SBYTE)( (GLOBAL_SIS (CrewEnlisted) + CREW_POD_CAPACITY - 1) / CREW_POD_CAPACITY ); if (fuel_required == 0) { GlobData.SIS_state = SIS_copy; LockMutex (GraphicsLock); DeltaSISGauges (UNDEFINED_DELTA, rescue_fuel, UNDEFINED_DELTA); UnlockMutex (GraphicsLock); } else if (fuel_required == (COUNT)~0) { GLOBAL_SIS (NumLanders) = 0; for (i = 0; i < NUM_DRIVE_SLOTS; ++i) GLOBAL_SIS (DriveSlots[i]) = EMPTY_SLOT + 0; for (i = 0; i < NUM_JET_SLOTS; ++i) GLOBAL_SIS (JetSlots[i]) = EMPTY_SLOT + 1; if (GLOBAL_SIS (FuelOnBoard) > FUEL_RESERVE) GLOBAL_SIS (FuelOnBoard) = FUEL_RESERVE; GLOBAL_SIS (TotalBioMass) = 0; GLOBAL_SIS (TotalElementMass) = 0; for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) GLOBAL_SIS (ElementAmounts[i]) = 0; for (i = 0; i < NUM_MODULE_SLOTS; ++i) { which_module = GLOBAL_SIS (ModuleSlots[i]); if (which_module < BOMB_MODULE_0 && (which_module != CREW_POD || ++crew_pods > 0)) GLOBAL_SIS (ModuleSlots[i]) = EMPTY_SLOT + 2; } LockMutex (GraphicsLock); DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, UNDEFINED_DELTA); UnlockMutex (GraphicsLock); } else if (fuel_required) { SBYTE bays; BYTE num_searches, beg_mod, end_mod; COUNT worth, total; BYTE module_count[BOMB_MODULE_0]; BYTE slot; DWORD capacity; SIS_copy = GlobData.SIS_state; for (i = PLANET_LANDER; i < BOMB_MODULE_0; ++i) module_count[i] = 0; capacity = FUEL_RESERVE; slot = NUM_MODULE_SLOTS - 1; do { if (SIS_copy.ModuleSlots[slot] == FUEL_TANK || SIS_copy.ModuleSlots[slot] == HIGHEFF_FUELSYS) { COUNT volume; volume = SIS_copy.ModuleSlots[slot] == FUEL_TANK ? FUEL_TANK_CAPACITY : HEFUEL_TANK_CAPACITY; capacity += volume; } } while (slot--); if (fuel_required > capacity) fuel_required = capacity; bays = -(SBYTE)( (SIS_copy.TotalElementMass + STORAGE_BAY_CAPACITY - 1) / STORAGE_BAY_CAPACITY ); for (i = 0; i < NUM_MODULE_SLOTS; ++i) { which_module = SIS_copy.ModuleSlots[i]; if (which_module == CREW_POD) ++crew_pods; else if (which_module == STORAGE_BAY) ++bays; } worth = fuel_required / FUEL_TANK_SCALE; total = 0; num_searches = 0; beg_mod = end_mod = (BYTE)~0; while (total < worth && ShipWorth () && ++num_searches) { DWORD rand_val; rand_val = TFB_Random (); switch (which_module = LOBYTE (LOWORD (rand_val)) % (CREW_POD + 1)) { case PLANET_LANDER: if (SIS_copy.NumLanders == 0) continue; --SIS_copy.NumLanders; break; case FUSION_THRUSTER: for (i = 0; i < NUM_DRIVE_SLOTS; ++i) { if (SIS_copy.DriveSlots[i] < EMPTY_SLOT) break; } if (i == NUM_DRIVE_SLOTS) continue; SIS_copy.DriveSlots[i] = EMPTY_SLOT + 0; break; case TURNING_JETS: for (i = 0; i < NUM_JET_SLOTS; ++i) { if (SIS_copy.JetSlots[i] < EMPTY_SLOT) break; } if (i == NUM_JET_SLOTS) continue; SIS_copy.JetSlots[i] = EMPTY_SLOT + 1; break; case CREW_POD: i = HIBYTE (LOWORD (rand_val)) % NUM_MODULE_SLOTS; which_module = SIS_copy.ModuleSlots[i]; if (which_module >= BOMB_MODULE_0 || which_module == FUEL_TANK || which_module == HIGHEFF_FUELSYS || (which_module == STORAGE_BAY && module_count[STORAGE_BAY] >= bays) || (which_module == CREW_POD && module_count[CREW_POD] >= crew_pods)) continue; SIS_copy.ModuleSlots[i] = EMPTY_SLOT + 2; break; } if (beg_mod == (BYTE)~0) beg_mod = end_mod = which_module; else if (which_module > end_mod) end_mod = which_module; ++module_count[which_module]; total += GLOBAL (ModuleCost[which_module]); } if (total == 0) { NPCPhrase (CHARITY); LockMutex (GraphicsLock); DeltaSISGauges (0, fuel_required, 0); UnlockMutex (GraphicsLock); return (FALSE); } else { NPCPhrase (RESCUE_OFFER); rescue_fuel = fuel_required; if (rescue_fuel == capacity) NPCPhrase (RESCUE_TANKS); else NPCPhrase (RESCUE_HOME); for (i = PLANET_LANDER; i < BOMB_MODULE_0; ++i) { if (module_count[i]) { RESPONSE_REF pStr; switch (i) { case PLANET_LANDER: pStr = LANDERS; break; case FUSION_THRUSTER: pStr = THRUSTERS; break; case TURNING_JETS: pStr = JETS; break; case CREW_POD: pStr = PODS; break; case STORAGE_BAY: pStr = BAYS; break; case DYNAMO_UNIT: pStr = DYNAMOS; break; case SHIVA_FURNACE: pStr = FURNACES; break; case GUN_WEAPON: pStr = GUNS; break; case BLASTER_WEAPON: pStr = BLASTERS; break; case CANNON_WEAPON: pStr = CANNONS; break; case TRACKING_SYSTEM: pStr = TRACKERS; break; case ANTIMISSILE_DEFENSE: pStr = DEFENSES; break; } if (i == end_mod && i != beg_mod) NPCPhrase (END_LIST_WITH_AND); NPCPhrase (ENUMERATE_ONE + (module_count[i] - 1)); NPCPhrase (pStr); } } } } return (TRUE); } static void ExitConversation (RESPONSE_REF R) { if (PLAYER_SAID (R, no_trade_now)) NPCPhrase (OK_NO_TRADE_NOW_BYE); else if (PLAYER_SAID (R, youre_on)) { NPCPhrase (YOU_GIVE_US_NO_CHOICE); SET_GAME_STATE (MELNORME_ANGER, 1); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, so_we_can_attack)) { NPCPhrase (DECEITFUL_HUMAN); SET_GAME_STATE (MELNORME_ANGER, 2); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, bye_melnorme_slightly_angry)) NPCPhrase (MELNORME_SLIGHTLY_ANGRY_GOODBYE); else if (PLAYER_SAID (R, ok_strip_me)) { if (ShipWorth () < 4000 / MODULE_COST_SCALE) /* is ship worth stripping */ NPCPhrase (NOT_WORTH_STRIPPING); else { SET_GAME_STATE (MELNORME_ANGER, 0); StripShip ((COUNT)~0); NPCPhrase (FAIR_JUSTICE); } } else if (PLAYER_SAID (R, fight_some_more)) { NPCPhrase (OK_FIGHT_SOME_MORE); SET_GAME_STATE (MELNORME_ANGER, 3); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, bye_melnorme_pissed_off)) NPCPhrase (MELNORME_PISSED_OFF_GOODBYE); else if (PLAYER_SAID (R, well_if_thats_the_way_you_feel)) { NPCPhrase (WE_FIGHT_AGAIN); SET_GAME_STATE (BATTLE_SEGUE, 1); } else if (PLAYER_SAID (R, you_hate_us_so_we_go_away)) NPCPhrase (HATE_YOU_GOODBYE); else if (PLAYER_SAID (R, take_it)) { StripShip (0); NPCPhrase (HAPPY_TO_HAVE_RESCUED); } else if (PLAYER_SAID (R, leave_it)) { SET_GAME_STATE (MELNORME_RESCUE_REFUSED, 1); NPCPhrase (MAYBE_SEE_YOU_LATER); } else if (PLAYER_SAID (R, no_help)) { SET_GAME_STATE (MELNORME_RESCUE_REFUSED, 1); NPCPhrase (GOODBYE_AND_GOODLUCK); } else if (PLAYER_SAID (R, no_changed_mind)) { NPCPhrase (GOODBYE_AND_GOODLUCK_AGAIN); } else if (PLAYER_SAID (R, be_leaving_now) || PLAYER_SAID (R, goodbye)) { NPCPhrase (FRIENDLY_GOODBYE); } } static void DoRescue (RESPONSE_REF R) { SIZE dx, dy; COUNT fuel_required; (void) R; // ignored dx = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)) - SOL_X; dy = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)) - SOL_Y; fuel_required = square_root ( (DWORD)((long)dx * dx + (long)dy * dy) ) + (2 * FUEL_TANK_SCALE); if (StripShip (fuel_required)) { Response (take_it, ExitConversation); Response (leave_it, ExitConversation); } } static COUNT DeltaCredit (SIZE delta_credit) { COUNT Credit; Credit = MAKE_WORD ( GET_GAME_STATE (MELNORME_CREDIT0), GET_GAME_STATE (MELNORME_CREDIT1) ); if ((int)delta_credit >= 0 || ((int)(-delta_credit) <= (int)(Credit))) { Credit += delta_credit; SET_GAME_STATE (MELNORME_CREDIT0, LOBYTE (Credit)); SET_GAME_STATE (MELNORME_CREDIT1, HIBYTE (Credit)); LockMutex (GraphicsLock); DrawStatusMessage ((UNICODE *)~0); UnlockMutex (GraphicsLock); } else { NPCPhrase (NEED_MORE_CREDIT0); NPCPhrase (delta_credit + (int)Credit); NPCPhrase (NEED_MORE_CREDIT1); } return (Credit); } static void CurrentEvents (void) { BYTE stack; stack = GET_GAME_STATE (MELNORME_EVENTS_INFO_STACK); switch (stack++) { case 0: NPCPhrase (OK_BUY_EVENT_1); break; case 1: NPCPhrase (OK_BUY_EVENT_2); break; case 2: NPCPhrase (OK_BUY_EVENT_3); break; case 3: NPCPhrase (OK_BUY_EVENT_4); break; case 4: NPCPhrase (OK_BUY_EVENT_5); break; case 5: NPCPhrase (OK_BUY_EVENT_6); break; case 6: NPCPhrase (OK_BUY_EVENT_7); break; case 7: NPCPhrase (OK_BUY_EVENT_8); break; } SET_GAME_STATE (MELNORME_EVENTS_INFO_STACK, stack); } static void AlienRaces (void) { BYTE stack; stack = GET_GAME_STATE (MELNORME_ALIEN_INFO_STACK); switch (stack++) { case 0: NPCPhrase (OK_BUY_ALIEN_RACE_1); break; case 1: NPCPhrase (OK_BUY_ALIEN_RACE_2); break; case 2: NPCPhrase (OK_BUY_ALIEN_RACE_3); break; case 3: NPCPhrase (OK_BUY_ALIEN_RACE_4); break; case 4: NPCPhrase (OK_BUY_ALIEN_RACE_5); break; case 5: NPCPhrase (OK_BUY_ALIEN_RACE_6); break; case 6: NPCPhrase (OK_BUY_ALIEN_RACE_7); break; case 7: NPCPhrase (OK_BUY_ALIEN_RACE_8); break; case 8: NPCPhrase (OK_BUY_ALIEN_RACE_9); break; case 9: NPCPhrase (OK_BUY_ALIEN_RACE_10); break; case 10: NPCPhrase (OK_BUY_ALIEN_RACE_11); break; case 11: NPCPhrase (OK_BUY_ALIEN_RACE_12); break; case 12: NPCPhrase (OK_BUY_ALIEN_RACE_13); break; case 13: NPCPhrase (OK_BUY_ALIEN_RACE_14); if (!GET_GAME_STATE (FOUND_PLUTO_SPATHI)) { SET_GAME_STATE (KNOW_SPATHI_PASSWORD, 1); SET_GAME_STATE (SPATHI_HOME_VISITS, 7); } break; case 14: NPCPhrase (OK_BUY_ALIEN_RACE_15); if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) < 2) { SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 2); } SET_GAME_STATE (KNOW_SYREEN_WORLD_SHATTERED, 1); break; case 15: NPCPhrase (OK_BUY_ALIEN_RACE_16); break; } SET_GAME_STATE (MELNORME_ALIEN_INFO_STACK, stack); } static void History (void) { BYTE stack; stack = GET_GAME_STATE (MELNORME_HISTORY_INFO_STACK); switch (stack++) { case 0: NPCPhrase (OK_BUY_HISTORY_1); break; case 1: NPCPhrase (OK_BUY_HISTORY_2); break; case 2: NPCPhrase (OK_BUY_HISTORY_3); break; case 3: NPCPhrase (OK_BUY_HISTORY_4); break; case 4: NPCPhrase (OK_BUY_HISTORY_5); break; case 5: NPCPhrase (OK_BUY_HISTORY_6); break; case 6: NPCPhrase (OK_BUY_HISTORY_7); break; case 7: NPCPhrase (OK_BUY_HISTORY_8); break; case 8: NPCPhrase (OK_BUY_HISTORY_9); break; } SET_GAME_STATE (MELNORME_HISTORY_INFO_STACK, stack); } static void NatureOfConversation (RESPONSE_REF R); static BYTE AskedToBuy; static void DoBuy (RESPONSE_REF R) { COUNT credit; SIZE needed_credit; BYTE slot; DWORD capacity; credit = MAKE_WORD ( GET_GAME_STATE (MELNORME_CREDIT0), GET_GAME_STATE (MELNORME_CREDIT1) ); capacity = FUEL_RESERVE; slot = NUM_MODULE_SLOTS - 1; do { if (GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK || GLOBAL_SIS (ModuleSlots[slot]) == HIGHEFF_FUELSYS) { COUNT volume; volume = GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK ? FUEL_TANK_CAPACITY : HEFUEL_TANK_CAPACITY; capacity += volume; } } while (slot--); if (credit == 0) { AskedToBuy = TRUE; NPCPhrase (NEED_CREDIT); NatureOfConversation (R); } else if (PLAYER_SAID (R, buy_fuel) || PLAYER_SAID (R, buy_1_fuel) || PLAYER_SAID (R, buy_5_fuel) || PLAYER_SAID (R, buy_10_fuel) || PLAYER_SAID (R, buy_25_fuel) || PLAYER_SAID (R, fill_me_up)) { needed_credit = 0; if (PLAYER_SAID (R, buy_1_fuel)) needed_credit = 1; else if (PLAYER_SAID (R, buy_5_fuel)) needed_credit = 5; else if (PLAYER_SAID (R, buy_10_fuel)) needed_credit = 10; else if (PLAYER_SAID (R, buy_25_fuel)) needed_credit = 25; else if (PLAYER_SAID (R, fill_me_up)) needed_credit = (capacity - GLOBAL_SIS (FuelOnBoard) + FUEL_TANK_SCALE - 1) / FUEL_TANK_SCALE; if (needed_credit == 0) { if (!GET_GAME_STATE (MELNORME_FUEL_PROCEDURE)) { NPCPhrase (BUY_FUEL_INTRO); SET_GAME_STATE (MELNORME_FUEL_PROCEDURE, 1); } } else { if (GLOBAL_SIS (FuelOnBoard) / FUEL_TANK_SCALE + needed_credit > capacity / FUEL_TANK_SCALE) { NPCPhrase (NO_ROOM_FOR_FUEL); goto TryFuelAgain; } if ((int)(needed_credit * (BIO_CREDIT_VALUE / 2)) <= (int)credit) { DWORD f; NPCPhrase (GOT_FUEL); f = (DWORD)needed_credit * FUEL_TANK_SCALE; LockMutex (GraphicsLock); while (f > 0x3FFFL) { DeltaSISGauges (0, 0x3FFF, 0); f -= 0x3FFF; } DeltaSISGauges (0, (SIZE)f, 0); UnlockMutex (GraphicsLock); } needed_credit *= (BIO_CREDIT_VALUE / 2); } if (needed_credit) { DeltaCredit (-needed_credit); if (GLOBAL_SIS (FuelOnBoard) >= capacity) goto BuyBuyBuy; } TryFuelAgain: NPCPhrase (HOW_MUCH_FUEL); Response (buy_1_fuel, DoBuy); Response (buy_5_fuel, DoBuy); Response (buy_10_fuel, DoBuy); Response (buy_25_fuel, DoBuy); Response (fill_me_up, DoBuy); Response (done_buying_fuel, DoBuy); } else if (PLAYER_SAID (R, buy_technology) || PLAYER_SAID (R, buy_new_tech)) { BYTE stack; needed_credit = 0; if (PLAYER_SAID (R, buy_technology)) { if (!GET_GAME_STATE (MELNORME_TECH_PROCEDURE)) { NPCPhrase (BUY_NEW_TECH_INTRO); SET_GAME_STATE (MELNORME_TECH_PROCEDURE, 1); } stack = 0; } else { RESPONSE_REF pStr; stack = GET_GAME_STATE (MELNORME_TECH_STACK); switch (stack) { case 0: pStr = OK_BUY_NEW_TECH_1; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 1: pStr = OK_BUY_NEW_TECH_2; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 2: pStr = OK_BUY_NEW_TECH_3; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 3: pStr = OK_BUY_NEW_TECH_4; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 4: pStr = OK_BUY_NEW_TECH_5; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 5: pStr = OK_BUY_NEW_TECH_6; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 6: pStr = OK_BUY_NEW_TECH_7; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 7: pStr = OK_BUY_NEW_TECH_8; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 8: pStr = OK_BUY_NEW_TECH_9; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 9: pStr = OK_BUY_NEW_TECH_10; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 10: pStr = OK_BUY_NEW_TECH_11; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 11: pStr = OK_BUY_NEW_TECH_12; needed_credit = 75 * BIO_CREDIT_VALUE; break; case 12: pStr = OK_BUY_NEW_TECH_13; needed_credit = 75 * BIO_CREDIT_VALUE; break; } if ((int)needed_credit > (int)credit) { DeltaCredit (-needed_credit); goto BuyBuyBuy; } else { ++stack; NPCPhrase (pStr); DeltaCredit (-needed_credit); } } switch (stack) { case 0: if (GLOBAL (ModuleCost[BLASTER_WEAPON]) == 0) { NPCPhrase (NEW_TECH_1); break; } ++stack; case 1: GLOBAL (ModuleCost[BLASTER_WEAPON]) = 4000 / MODULE_COST_SCALE; if (!GET_GAME_STATE (IMPROVED_LANDER_SPEED)) { NPCPhrase (NEW_TECH_2); break; } ++stack; case 2: SET_GAME_STATE (IMPROVED_LANDER_SPEED, 1); if (GLOBAL (ModuleCost[ANTIMISSILE_DEFENSE]) == 0) { NPCPhrase (NEW_TECH_3); break; } ++stack; case 3: GLOBAL (ModuleCost[ANTIMISSILE_DEFENSE]) = 4000 / MODULE_COST_SCALE; if (!(GET_GAME_STATE (LANDER_SHIELDS) & (1 << BIOLOGICAL_DISASTER))) { NPCPhrase (NEW_TECH_4); break; } ++stack; case 4: credit = GET_GAME_STATE (LANDER_SHIELDS) | (1 << BIOLOGICAL_DISASTER); SET_GAME_STATE (LANDER_SHIELDS, credit); if (!GET_GAME_STATE (IMPROVED_LANDER_CARGO)) { NPCPhrase (NEW_TECH_5); break; } ++stack; case 5: SET_GAME_STATE (IMPROVED_LANDER_CARGO, 1); if (GLOBAL (ModuleCost[HIGHEFF_FUELSYS]) == 0) { NPCPhrase (NEW_TECH_6); break; } ++stack; case 6: GLOBAL (ModuleCost[HIGHEFF_FUELSYS]) = 1000 / MODULE_COST_SCALE; if (!GET_GAME_STATE (IMPROVED_LANDER_SHOT)) { NPCPhrase (NEW_TECH_7); break; } ++stack; case 7: SET_GAME_STATE (IMPROVED_LANDER_SHOT, 1); if (!(GET_GAME_STATE (LANDER_SHIELDS) & (1 << EARTHQUAKE_DISASTER))) { NPCPhrase (NEW_TECH_8); break; } ++stack; case 8: credit = GET_GAME_STATE (LANDER_SHIELDS) | (1 << EARTHQUAKE_DISASTER); SET_GAME_STATE (LANDER_SHIELDS, credit); if (GLOBAL (ModuleCost[TRACKING_SYSTEM]) == 0) { NPCPhrase (NEW_TECH_9); break; } ++stack; case 9: GLOBAL (ModuleCost[TRACKING_SYSTEM]) = 5000 / MODULE_COST_SCALE; if (!(GET_GAME_STATE (LANDER_SHIELDS) & (1 << LIGHTNING_DISASTER))) { NPCPhrase (NEW_TECH_10); break; } ++stack; case 10: credit = GET_GAME_STATE (LANDER_SHIELDS) | (1 << LIGHTNING_DISASTER); SET_GAME_STATE (LANDER_SHIELDS, credit); if (!(GET_GAME_STATE (LANDER_SHIELDS) & (1 << LAVASPOT_DISASTER))) { NPCPhrase (NEW_TECH_11); break; } ++stack; case 11: credit = GET_GAME_STATE (LANDER_SHIELDS) | (1 << LAVASPOT_DISASTER); SET_GAME_STATE (LANDER_SHIELDS, credit); if (GLOBAL (ModuleCost[CANNON_WEAPON]) == 0) { NPCPhrase (NEW_TECH_12); break; } ++stack; case 12: GLOBAL (ModuleCost[CANNON_WEAPON]) = 6000 / MODULE_COST_SCALE; if (GLOBAL (ModuleCost[SHIVA_FURNACE]) == 0) { NPCPhrase (NEW_TECH_13); break; } ++stack; case 13: GLOBAL (ModuleCost[SHIVA_FURNACE]) = 4000 / MODULE_COST_SCALE; NPCPhrase (NEW_TECH_ALL_GONE); SET_GAME_STATE (MELNORME_TECH_STACK, stack); goto BuyBuyBuy; } SET_GAME_STATE (MELNORME_TECH_STACK, stack); Response (buy_new_tech, DoBuy); Response (no_buy_new_tech, DoBuy); } else if (PLAYER_SAID (R, buy_info) || PLAYER_SAID (R, buy_current_events) || PLAYER_SAID (R, buy_alien_races) || PLAYER_SAID (R, buy_history)) { needed_credit = 0; if (PLAYER_SAID (R, buy_info)) { if (GET_GAME_STATE (MELNORME_INFO_PROCEDURE)) NPCPhrase (OK_BUY_INFO); else { NPCPhrase (BUY_INFO_INTRO); SET_GAME_STATE (MELNORME_INFO_PROCEDURE, 1); } } else { #define INFO_COST 75 needed_credit = INFO_COST; if ((int)credit >= (int)needed_credit) { if (PLAYER_SAID (R, buy_current_events)) CurrentEvents (); else if (PLAYER_SAID (R, buy_alien_races)) AlienRaces (); else /* if (R == buy_history) */ History (); } DeltaCredit (-needed_credit); if (GET_GAME_STATE (MELNORME_EVENTS_INFO_STACK) < NUM_EVENT_ITEMS || GET_GAME_STATE (MELNORME_ALIEN_INFO_STACK) < NUM_ALIEN_RACE_ITEMS || GET_GAME_STATE (MELNORME_HISTORY_INFO_STACK) < NUM_HISTORY_ITEMS) { } else { NPCPhrase (INFO_ALL_GONE); goto BuyBuyBuy; } } if (GET_GAME_STATE (MELNORME_EVENTS_INFO_STACK) < NUM_EVENT_ITEMS) Response (buy_current_events, DoBuy); if (GET_GAME_STATE (MELNORME_ALIEN_INFO_STACK) < NUM_ALIEN_RACE_ITEMS) Response (buy_alien_races, DoBuy); if (GET_GAME_STATE (MELNORME_HISTORY_INFO_STACK) < NUM_HISTORY_ITEMS) Response (buy_history, DoBuy); Response (done_buying_info, DoBuy); } else { if (PLAYER_SAID (R, done_buying_fuel)) NPCPhrase (OK_DONE_BUYING_FUEL); else if (PLAYER_SAID (R, no_buy_new_tech)) NPCPhrase (OK_NO_BUY_NEW_TECH); else if (PLAYER_SAID (R, done_buying_info)) NPCPhrase (OK_DONE_BUYING_INFO); else NPCPhrase (WHAT_TO_BUY); BuyBuyBuy: if (GLOBAL_SIS (FuelOnBoard) < capacity) Response (buy_fuel, DoBuy); if (GET_GAME_STATE (MELNORME_TECH_STACK) < NUM_TECH_ITEMS) Response (buy_technology, DoBuy); if (GET_GAME_STATE (MELNORME_ALIEN_INFO_STACK) < NUM_ALIEN_RACE_ITEMS || GET_GAME_STATE (MELNORME_HISTORY_INFO_STACK) < NUM_HISTORY_ITEMS || GET_GAME_STATE (MELNORME_EVENTS_INFO_STACK) < NUM_EVENT_ITEMS) Response (buy_info, DoBuy); Response (done_buying, NatureOfConversation); Response (be_leaving_now, ExitConversation); } } static void DoSell (RESPONSE_REF R) { BYTE num_new_rainbows; UWORD rainbow_mask; SIZE added_credit; int what_to_sell_queued = 0; rainbow_mask = MAKE_WORD ( GET_GAME_STATE (RAINBOW_WORLD0), GET_GAME_STATE (RAINBOW_WORLD1) ); num_new_rainbows = (BYTE)(-GET_GAME_STATE (MELNORME_RAINBOW_COUNT)); while (rainbow_mask) { if (rainbow_mask & 1) ++num_new_rainbows; rainbow_mask >>= 1; } if (!PLAYER_SAID (R, sell)) { if (PLAYER_SAID (R, sell_life_data)) { DWORD TimeIn; added_credit = GLOBAL_SIS (TotalBioMass) * BIO_CREDIT_VALUE; NPCPhrase (SOLD_LIFE_DATA1); NPCPhrase (-(int)GLOBAL_SIS (TotalBioMass)); NPCPhrase (SOLD_LIFE_DATA2); NPCPhrase (-(int)added_credit); NPCPhrase (SOLD_LIFE_DATA3); // queue WHAT_TO_SELL before talk-segue if (num_new_rainbows) { NPCPhrase (WHAT_TO_SELL); what_to_sell_queued = 1; } AlienTalkSegue (1); DrawCargoStrings ((BYTE)~0, (BYTE)~0); SleepThread (ONE_SECOND / 2); TimeIn = GetTimeCounter (); DrawCargoStrings ( (BYTE)NUM_ELEMENT_CATEGORIES, (BYTE)NUM_ELEMENT_CATEGORIES ); do { TimeIn = GetTimeCounter (); if (AnyButtonPress (TRUE)) { DeltaCredit (GLOBAL_SIS (TotalBioMass) * BIO_CREDIT_VALUE); GLOBAL_SIS (TotalBioMass) = 0; } else { --GLOBAL_SIS (TotalBioMass); DeltaCredit (BIO_CREDIT_VALUE); } DrawCargoStrings ( (BYTE)NUM_ELEMENT_CATEGORIES, (BYTE)NUM_ELEMENT_CATEGORIES ); } while (GLOBAL_SIS (TotalBioMass)); SleepThread (ONE_SECOND / 2); LockMutex (GraphicsLock); ClearSISRect (DRAW_SIS_DISPLAY); UnlockMutex (GraphicsLock); } else /* if (R == sell_rainbow_locations) */ { added_credit = num_new_rainbows * (250 * BIO_CREDIT_VALUE); NPCPhrase (SOLD_RAINBOW_LOCATIONS1); NPCPhrase (-(int)num_new_rainbows); NPCPhrase (SOLD_RAINBOW_LOCATIONS2); NPCPhrase (-(int)added_credit); NPCPhrase (SOLD_RAINBOW_LOCATIONS3); num_new_rainbows += GET_GAME_STATE (MELNORME_RAINBOW_COUNT); SET_GAME_STATE (MELNORME_RAINBOW_COUNT, num_new_rainbows); num_new_rainbows = 0; DeltaCredit (added_credit); } AskedToBuy = FALSE; } if (GLOBAL_SIS (TotalBioMass) || num_new_rainbows) { if (!what_to_sell_queued) NPCPhrase (WHAT_TO_SELL); if (GLOBAL_SIS (TotalBioMass)) Response (sell_life_data, DoSell); if (num_new_rainbows) Response (sell_rainbow_locations, DoSell); Response (done_selling, NatureOfConversation); } else { if (PLAYER_SAID (R, sell)) NPCPhrase (NOTHING_TO_SELL); DISABLE_PHRASE (sell); NatureOfConversation (R); } } static void NatureOfConversation (RESPONSE_REF R) { BYTE num_new_rainbows; UWORD rainbow_mask; COUNT Credit; if (PLAYER_SAID (R, get_on_with_business)) { SET_GAME_STATE (MELNORME_YACK_STACK2, 5); R = 0; } Credit = DeltaCredit (0); if (R == 0) { BYTE stack; stack = (BYTE)(GET_GAME_STATE (MELNORME_YACK_STACK2) - 5); switch (stack++) { case 0: NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_1); break; case 1: NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_2); break; case 2: NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_3); break; case 3: NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_4); break; case 4: NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_5); break; case 5: NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_6); break; case 6: NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_7); break; case 7: NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_8); break; case 8: NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_9); break; default: --stack; NPCPhrase (HELLO_AND_DOWN_TO_BUSINESS_10); break; } SET_GAME_STATE (MELNORME_YACK_STACK2, stack + 5); } rainbow_mask = MAKE_WORD ( GET_GAME_STATE (RAINBOW_WORLD0), GET_GAME_STATE (RAINBOW_WORLD1) ); num_new_rainbows = (BYTE)(-GET_GAME_STATE (MELNORME_RAINBOW_COUNT)); while (rainbow_mask) { if (rainbow_mask & 1) ++num_new_rainbows; rainbow_mask >>= 1; } if (GLOBAL_SIS (FuelOnBoard) > 0 || GLOBAL_SIS (TotalBioMass) || Credit || num_new_rainbows) { if (!GET_GAME_STATE (TRADED_WITH_MELNORME)) { SET_GAME_STATE (TRADED_WITH_MELNORME, 1); NPCPhrase (TRADING_INFO); } if (R == 0) { /* Melnorme reports any news and turns purple */ NPCPhrase (BUY_OR_SELL); AlienTalkSegue(1); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 1) ), ONE_SECOND / 2); AlienTalkSegue((COUNT)~0); } else if (PLAYER_SAID (R, why_turned_purple)) { SET_GAME_STATE (WHY_MELNORME_PURPLE, 1); NPCPhrase (TURNED_PURPLE_BECAUSE); } else if (PLAYER_SAID (R, done_selling)) { NPCPhrase (OK_DONE_SELLING); } else if (PLAYER_SAID (R, done_buying)) { NPCPhrase (OK_DONE_BUYING); } if (!GET_GAME_STATE (WHY_MELNORME_PURPLE)) { Response (why_turned_purple, NatureOfConversation); } if (!AskedToBuy) Response (buy, DoBuy); if (PHRASE_ENABLED (sell)) Response (sell, DoSell); Response (goodbye, ExitConversation); } else /* needs to be rescued */ { if (GET_GAME_STATE (MELNORME_RESCUE_REFUSED)) { NPCPhrase (CHANGED_MIND); Response (yes_changed_mind, DoRescue); Response (no_changed_mind, ExitConversation); } else { BYTE num_rescues; num_rescues = GET_GAME_STATE (MELNORME_RESCUE_COUNT); switch (num_rescues) { case 0: NPCPhrase (RESCUE_EXPLANATION); break; case 1: NPCPhrase (RESCUE_AGAIN_1); break; case 2: NPCPhrase (RESCUE_AGAIN_2); break; case 3: NPCPhrase (RESCUE_AGAIN_3); break; case 4: NPCPhrase (RESCUE_AGAIN_4); break; case 5: NPCPhrase (RESCUE_AGAIN_5); break; } if (num_rescues < 5) { ++num_rescues; SET_GAME_STATE (MELNORME_RESCUE_COUNT, num_rescues); } NPCPhrase (SHOULD_WE_HELP_YOU); Response (yes_help, DoRescue); Response (no_help, ExitConversation); } } } static BYTE local_stack0, local_stack1; static void DoBluster (RESPONSE_REF R) { if (PLAYER_SAID (R, trade_is_for_the_weak)) { XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 2) ), ONE_SECOND / 2); SET_GAME_STATE (MELNORME_YACK_STACK2, 4); NPCPhrase (WERE_NOT_AFRAID); } else if (PLAYER_SAID (R, why_blue_light)) { SET_GAME_STATE (WHY_MELNORME_BLUE, 1); NPCPhrase (BLUE_IS_MAD); } else if (PLAYER_SAID (R, we_strong_1)) { local_stack0 = 1; NPCPhrase (YOU_NOT_STRONG_1); } else if (PLAYER_SAID (R, we_strong_2)) { local_stack0 = 2; NPCPhrase (YOU_NOT_STRONG_2); } else if (PLAYER_SAID (R, we_strong_3)) { local_stack0 = 3; NPCPhrase (YOU_NOT_STRONG_3); } else if (PLAYER_SAID (R, just_testing)) { local_stack1 = 1; NPCPhrase (REALLY_TESTING); } if (!GET_GAME_STATE (WHY_MELNORME_BLUE)) Response (why_blue_light, DoBluster); switch (local_stack0) { case 0: Response (we_strong_1, DoBluster); break; case 1: Response (we_strong_2, DoBluster); break; case 2: Response (we_strong_3, DoBluster); break; } switch (local_stack1) { case 0: Response (just_testing, DoBluster); break; case 1: { Response (yes_really_testing, DoFirstMeeting); break; } } Response (youre_on, ExitConversation); } static void yack0_respond (void) { switch (GET_GAME_STATE (MELNORME_YACK_STACK0)) { case 0: { UNICODE buf[ALLIANCE_NAME_BUFSIZE]; GetAllianceName (buf, name_1); construct_response ( shared_phrase_buf, we_are_from_alliance0, buf, (RESPONSE_REF)-1 ); DoResponsePhrase (we_are_from_alliance0, DoFirstMeeting, shared_phrase_buf); break; } case 1: Response (how_know, DoFirstMeeting); break; } } static void yack1_respond (void) { switch (GET_GAME_STATE (MELNORME_YACK_STACK1)) { case 0: Response (what_about_yourselves, DoFirstMeeting); break; case 1: Response (what_factors, DoFirstMeeting); case 2: Response (get_on_with_business, NatureOfConversation); break; } } static void yack2_respond (void) { switch (GET_GAME_STATE (MELNORME_YACK_STACK2)) { case 0: Response (what_about_universe, DoFirstMeeting); break; case 1: Response (giving_is_good_1, DoFirstMeeting); break; case 2: Response (giving_is_good_2, DoFirstMeeting); break; case 3: Response (trade_is_for_the_weak, DoBluster); break; } } static void DoFirstMeeting (RESPONSE_REF R) { BYTE last_stack = 0; PVOIDFUNC temp_func, stack_func[] = { yack0_respond, yack1_respond, yack2_respond, }; if (R == 0) { BYTE business_count; business_count = GET_GAME_STATE (MELNORME_BUSINESS_COUNT); switch (business_count++) { case 0: NPCPhrase (HELLO_NOW_DOWN_TO_BUSINESS_1); break; case 1: NPCPhrase (HELLO_NOW_DOWN_TO_BUSINESS_2); break; case 2: NPCPhrase (HELLO_NOW_DOWN_TO_BUSINESS_3); --business_count; break; } SET_GAME_STATE (MELNORME_BUSINESS_COUNT, business_count); } else if (PLAYER_SAID (R, we_are_from_alliance0)) { SET_GAME_STATE (MELNORME_YACK_STACK0, 1); NPCPhrase (KNOW_OF_YOU); } else if (PLAYER_SAID (R, how_know)) { SET_GAME_STATE (MELNORME_YACK_STACK0, 2); NPCPhrase (KNOW_BECAUSE); } else if (PLAYER_SAID (R, what_about_yourselves)) { last_stack = 1; SET_GAME_STATE (MELNORME_YACK_STACK1, 1); NPCPhrase (NO_TALK_ABOUT_OURSELVES); } else if (PLAYER_SAID (R, what_factors)) { last_stack = 1; SET_GAME_STATE (MELNORME_YACK_STACK1, 2); NPCPhrase (FACTORS_ARE); } else if (PLAYER_SAID (R, what_about_universe)) { last_stack = 2; SET_GAME_STATE (MELNORME_YACK_STACK2, 1); NPCPhrase (NO_FREE_LUNCH); } else if (PLAYER_SAID (R, giving_is_good_1)) { last_stack = 2; SET_GAME_STATE (MELNORME_YACK_STACK2, 2); NPCPhrase (GIVING_IS_BAD_1); } else if (PLAYER_SAID (R, giving_is_good_2)) { last_stack = 2; SET_GAME_STATE (MELNORME_YACK_STACK2, 3); NPCPhrase (GIVING_IS_BAD_2); } else if (PLAYER_SAID (R, yes_really_testing)) { XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 0) ), ONE_SECOND / 2); NPCPhrase (TEST_RESULTS); } else if (PLAYER_SAID (R, we_apologize)) { SET_GAME_STATE (MELNORME_ANGER, 0); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 0) ), ONE_SECOND / 2); NPCPhrase (APOLOGY_ACCEPTED); } temp_func = stack_func[0]; stack_func[0] = stack_func[last_stack]; stack_func[last_stack] = temp_func; (*stack_func[0]) (); (*stack_func[1]) (); (*stack_func[2]) (); Response (no_trade_now, ExitConversation); } static void DoMelnormeMiffed (RESPONSE_REF R) { if (R == 0) { BYTE miffed_count; miffed_count = GET_GAME_STATE (MELNORME_MIFFED_COUNT); switch (miffed_count++) { case 0: NPCPhrase (HELLO_SLIGHTLY_ANGRY_1); break; case 1: NPCPhrase (HELLO_SLIGHTLY_ANGRY_2); break; default: --miffed_count; NPCPhrase (HELLO_SLIGHTLY_ANGRY_3); break; } SET_GAME_STATE (MELNORME_MIFFED_COUNT, miffed_count); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 2) ), ONE_SECOND / 2); } else if (PLAYER_SAID (R, explore_relationship)) { SET_GAME_STATE (MELNORME_YACK_STACK3, 1); NPCPhrase (EXAMPLE_OF_RELATIONSHIP); } else if (PLAYER_SAID (R, excuse_1)) { SET_GAME_STATE (MELNORME_YACK_STACK3, 2); NPCPhrase (NO_EXCUSE_1); } else if (PLAYER_SAID (R, excuse_2)) { SET_GAME_STATE (MELNORME_YACK_STACK3, 3); NPCPhrase (NO_EXCUSE_2); } else if (PLAYER_SAID (R, excuse_3)) { SET_GAME_STATE (MELNORME_YACK_STACK3, 4); NPCPhrase (NO_EXCUSE_3); } switch (GET_GAME_STATE (MELNORME_YACK_STACK3)) { case 0: Response (explore_relationship, DoMelnormeMiffed); break; case 1: Response (excuse_1, DoMelnormeMiffed); break; case 2: Response (excuse_2, DoMelnormeMiffed); break; case 3: Response (excuse_3, DoMelnormeMiffed); break; } Response (we_apologize, DoFirstMeeting); Response (so_we_can_attack, ExitConversation); Response (bye_melnorme_slightly_angry, ExitConversation); } static void DoMelnormePissed (RESPONSE_REF R) { if (R == 0) { BYTE pissed_count; pissed_count = GET_GAME_STATE (MELNORME_PISSED_COUNT); switch (pissed_count++) { case 0: NPCPhrase (HELLO_PISSED_OFF_1); break; case 1: NPCPhrase (HELLO_PISSED_OFF_2); break; default: --pissed_count; NPCPhrase (HELLO_PISSED_OFF_3); break; } SET_GAME_STATE (MELNORME_PISSED_COUNT, pissed_count); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 2) ), ONE_SECOND / 2); } else if (PLAYER_SAID (R, beg_forgiveness)) { SET_GAME_STATE (MELNORME_YACK_STACK4, 1); NPCPhrase (LOTS_TO_MAKE_UP_FOR); } else if (PLAYER_SAID (R, you_are_so_right)) { SET_GAME_STATE (MELNORME_YACK_STACK4, 2); NPCPhrase (ONE_LAST_CHANCE); } switch (GET_GAME_STATE (MELNORME_YACK_STACK4)) { case 0: Response (beg_forgiveness, DoMelnormePissed); break; case 1: Response (you_are_so_right, DoMelnormePissed); break; case 2: Response (ok_strip_me, ExitConversation); break; } Response (fight_some_more, ExitConversation); Response (bye_melnorme_pissed_off, ExitConversation); } static void DoMelnormeHate (RESPONSE_REF R) { BYTE hate_count; (void) R; // ignored hate_count = GET_GAME_STATE (MELNORME_HATE_COUNT); switch (hate_count++) { case 0: NPCPhrase (HELLO_HATE_YOU_1); break; case 1: NPCPhrase (HELLO_HATE_YOU_2); break; default: --hate_count; NPCPhrase (HELLO_HATE_YOU_3); break; } SET_GAME_STATE (MELNORME_HATE_COUNT, hate_count); XFormColorMap (GetColorMapAddress ( SetAbsColorMapIndex (CommData.AlienColorMap, 2) ), ONE_SECOND / 2); Response (well_if_thats_the_way_you_feel, ExitConversation); Response (you_hate_us_so_we_go_away, ExitConversation); } static void Intro (void) { if (GET_GAME_STATE (MET_MELNORME) == 0) { SET_GAME_STATE (MET_MELNORME, 1); DoFirstMeeting (0); } else { switch (GET_GAME_STATE (MELNORME_ANGER)) { case 0: if (GET_GAME_STATE (MELNORME_YACK_STACK2) <= 5) DoFirstMeeting (0); else NatureOfConversation (0); break; case 1: DoMelnormeMiffed (0); break; case 2: DoMelnormePissed (0); break; default: DoMelnormeHate (0); break; } } } static COUNT uninit_melnorme (void) { return (0); } static void post_melnorme_enc (void) { LockMutex (GraphicsLock); DrawStatusMessage (0); UnlockMutex (GraphicsLock); } LOCDATAPTR init_melnorme_comm (void) { LOCDATAPTR retval; melnorme_desc.init_encounter_func = Intro; melnorme_desc.post_encounter_func = post_melnorme_enc; melnorme_desc.uninit_encounter_func = uninit_melnorme; melnorme_desc.AlienTextBaseline.x = TEXT_X_OFFS + (SIS_TEXT_WIDTH >> 1); melnorme_desc.AlienTextBaseline.y = 0; melnorme_desc.AlienTextWidth = SIS_TEXT_WIDTH - 16; local_stack0 = 0; local_stack1 = 0; SET_GAME_STATE (BATTLE_SEGUE, 0); AskedToBuy = FALSE; retval = &melnorme_desc; return (retval); } uqm-0.6.2/sc2/src/sc2code/comm/melnorm/Makeinfo0000600000175000017500000000002710543202031017654 0ustar joeyjoeyuqm_CFILES="melnorm.c" uqm-0.6.2/sc2/src/sc2code/comm/melnorm/respkg.h0000600000175000017500000000004110543202031017640 0ustar joeyjoeyenum { MELNORME_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/comm/melnorm/resinst.h0000600000175000017500000000012610543202031020040 0ustar joeyjoey#include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "imusicre.h" uqm-0.6.2/sc2/src/sc2code/ships/0000755000175000017500000000000010552600274014746 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/probe/0000755000175000017500000000000010552600274016055 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/probe/restypes.h0000600000175000017500000000024110543202071020062 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/probe/igfxres.h0000600000175000017500000000006110543202071017653 0ustar joeyjoey#define PROBE_MICON_MASK_PMAP_ANIM 0x00200002L uqm-0.6.2/sc2/src/sc2code/ships/probe/probe.c0000600000175000017500000000404110543202071017310 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/probe/resinst.h" #define MAX_CREW 1 #define MAX_ENERGY 1 #define ENERGY_REGENERATION 0 #define WEAPON_ENERGY_COST 0 #define SPECIAL_ENERGY_COST 0 #define ENERGY_WAIT 0 #define MAX_THRUST 0 #define THRUST_INCREMENT 0 #define TURN_WAIT 0 #define THRUST_WAIT 0 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 0 #define SHIP_MASS 0 static RACE_DESC probe_desc = { { 0, 0, /* Super Melee cost */ 0, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 0, 0, }, 0, 0, (FRAME)PROBE_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)0, (SOUND)0, }, { 0, 0, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; RACE_DESCPTR init_probe (void) { RACE_DESCPTR RaceDescPtr; RaceDescPtr = &probe_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/probe/istrtab.h0000600000175000017500000000033210543202071017655 0ustar joeyjoey#ifndef _ISTRTAB_H #define _ISTRTAB_H #define ARILOU_RACE_STRINGS 0x00200004L #define ARILOU_SHIP_SOUNDS 0x00400104L #define ARILOU_VICTORY_SONG 0x00600204L typedef RESOURCE STRTAB_INSTANCE; #endif /* _ISTRTAB_H */ uqm-0.6.2/sc2/src/sc2code/ships/probe/icode.h0000600000175000017500000000004110543202071017265 0ustar joeyjoey#define PROBE_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/probe/probe.res0000600000175000017500000000023110543202071017654 0ustar joeyjoeyINCLUDE ../star3do.typ PATH probe PACKAGE PROBE_CODE_PACKAGE probe.sc2 CODE PROBE_CODE probe.cod GFXRES PROBE_MICON_MASK_PMAP_ANIM promicon.ani uqm-0.6.2/sc2/src/sc2code/ships/probe/Makeinfo0000600000175000017500000000002510543202071017507 0ustar joeyjoeyuqm_CFILES="probe.c" uqm-0.6.2/sc2/src/sc2code/ships/probe/respkg.h0000600000175000017500000000004310543202071017477 0ustar joeyjoeyenum { PROBE_CODE_PACKAGE = 1 }; uqm-0.6.2/sc2/src/sc2code/ships/probe/resinst.h0000600000175000017500000000005010543202071017671 0ustar joeyjoey#include "igfxres.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/syreen/0000755000175000017500000000000010552600274016253 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/syreen/syreen.res0000600000175000017500000000127510543202070020260 0ustar joeyjoeyINCLUDE ../star3do.typ PATH syreen PACKAGE SYREEN_CODE_PACKAGE syreen.shp CODE SYREEN_CODE syreen.cod GFXRES SYREEN_ICON_MASK_PMAP_ANIM syricons.ani GFXRES SYREEN_MICON_MASK_PMAP_ANIM syrmicon.ani STRTAB SYREEN_RACE_STRINGS syrtext.txt PACKAGE SYREEN_PACKAGE syreen.shp GFXRES SYREEN_BIG_MASK_PMAP_ANIM syreen.big GFXRES SYREEN_MED_MASK_PMAP_ANIM syreen.med GFXRES SYREEN_SML_MASK_PMAP_ANIM syreen.sml GFXRES DAGGER_BIG_MASK_PMAP_ANIM dagger.big GFXRES DAGGER_MED_MASK_PMAP_ANIM dagger.med GFXRES DAGGER_SML_MASK_PMAP_ANIM dagger.sml GFXRES SYREEN_CAPTAIN_MASK_PMAP_ANIM syrcap.ani SNDRES SYREEN_SHIP_SOUNDS syrsound.snd MUSICRES SYREEN_VICTORY_SONG syrditty.mod uqm-0.6.2/sc2/src/sc2code/ships/syreen/restypes.h0000600000175000017500000000024110543202067020265 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/syreen/igfxres.h0000600000175000017500000000064710543202070020062 0ustar joeyjoey#define SYREEN_ICON_MASK_PMAP_ANIM 0x00200002L #define SYREEN_MICON_MASK_PMAP_ANIM 0x00200102L #define SYREEN_BIG_MASK_PMAP_ANIM 0x00400202L #define SYREEN_MED_MASK_PMAP_ANIM 0x00400302L #define SYREEN_SML_MASK_PMAP_ANIM 0x00400402L #define DAGGER_BIG_MASK_PMAP_ANIM 0x00400502L #define DAGGER_MED_MASK_PMAP_ANIM 0x00400602L #define DAGGER_SML_MASK_PMAP_ANIM 0x00400702L #define SYREEN_CAPTAIN_MASK_PMAP_ANIM 0x00400802L uqm-0.6.2/sc2/src/sc2code/ships/syreen/isndres.h0000600000175000017500000000005110543202070020047 0ustar joeyjoey#define SYREEN_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/syreen/istrtab.h0000600000175000017500000000005210543202070020051 0ustar joeyjoey#define SYREEN_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/syreen/imusicre.h0000600000175000017500000000005210543202067020227 0ustar joeyjoey#define SYREEN_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/syreen/icode.h0000600000175000017500000000004210543202070017463 0ustar joeyjoey#define SYREEN_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/syreen/syreen.c0000600000175000017500000001560210543202067017716 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/syreen/resinst.h" #include "libs/mathlib.h" #define SYREEN_MAX_CREW_SIZE MAX_CREW_SIZE #define MAX_CREW 12 #define MAX_ENERGY 16 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 1 #define SPECIAL_ENERGY_COST 5 #define ENERGY_WAIT 6 #define MAX_THRUST /* DISPLAY_TO_WORLD (8) */ 36 #define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 9 #define TURN_WAIT 1 #define THRUST_WAIT 1 #define WEAPON_WAIT 8 #define SPECIAL_WAIT 20 #define SHIP_MASS 2 #define MISSILE_SPEED DISPLAY_TO_WORLD (30) #define MISSILE_LIFE 10 static RACE_DESC syreen_desc = { { FIRES_FORE, 13, /* Super Melee cost */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, SYREEN_MAX_CREW_SIZE, MAX_ENERGY, MAX_ENERGY, { 0, 0, }, (STRING)SYREEN_RACE_STRINGS, (FRAME)SYREEN_ICON_MASK_PMAP_ANIM, (FRAME)SYREEN_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)SYREEN_BIG_MASK_PMAP_ANIM, (FRAME)SYREEN_MED_MASK_PMAP_ANIM, (FRAME)SYREEN_SML_MASK_PMAP_ANIM, }, { (FRAME)DAGGER_BIG_MASK_PMAP_ANIM, (FRAME)DAGGER_MED_MASK_PMAP_ANIM, (FRAME)DAGGER_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)SYREEN_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)SYREEN_VICTORY_SONG, (SOUND)SYREEN_SHIP_SOUNDS, }, { 0, (MISSILE_SPEED * MISSILE_LIFE * 2 / 3), NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static COUNT initialize_dagger (PELEMENT ShipPtr, HELEMENT DaggerArray[]) { #define SYREEN_OFFSET 30 #define MISSILE_HITS 1 #define MISSILE_DAMAGE 2 #define MISSILE_OFFSET 3 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = SYREEN_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; DaggerArray[0] = initialize_missile (&MissileBlock); return (1); } static void spawn_crew (PELEMENT ElementPtr) { if (ElementPtr->state_flags & PLAYER_SHIP) { HELEMENT hCrew; hCrew = AllocElement (); if (hCrew != 0) { ELEMENTPTR CrewPtr; LockElement (hCrew, &CrewPtr); CrewPtr->next.location = ElementPtr->next.location; CrewPtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); CrewPtr->life_span = 0; CrewPtr->death_func = spawn_crew; CrewPtr->pParent = ElementPtr->pParent; CrewPtr->hTarget = 0; UnlockElement (hCrew); PutElement (hCrew); } } else { HELEMENT hElement, hNextElement; for (hElement = GetHeadElement (); hElement != 0; hElement = hNextElement) { ELEMENTPTR ObjPtr; LockElement (hElement, &ObjPtr); hNextElement = GetSuccElement (ObjPtr); if ((ObjPtr->state_flags & PLAYER_SHIP) && (ObjPtr->state_flags & (GOOD_GUY | BAD_GUY)) != (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) && ObjPtr->crew_level > 1) { SIZE dx, dy; DWORD d_squared; dx = ObjPtr->next.location.x - ElementPtr->next.location.x; if (dx < 0) dx = -dx; dy = ObjPtr->next.location.y - ElementPtr->next.location.y; if (dy < 0) dy = -dy; dx = WORLD_TO_DISPLAY (dx); dy = WORLD_TO_DISPLAY (dy); #define ABANDONER_RANGE 208 /* originally SPACE_HEIGHT */ if (dx <= ABANDONER_RANGE && dy <= ABANDONER_RANGE && (d_squared = (DWORD)((UWORD)dx * (UWORD)dx) + (DWORD)((UWORD)dy * (UWORD)dy)) <= (DWORD)((UWORD)ABANDONER_RANGE * (UWORD)ABANDONER_RANGE)) { #define MAX_ABANDONERS 8 COUNT crew_loss; crew_loss = ((MAX_ABANDONERS * (ABANDONER_RANGE - square_root (d_squared))) / ABANDONER_RANGE) + 1; if (crew_loss >= ObjPtr->crew_level) crew_loss = ObjPtr->crew_level - 1; AbandonShip (ObjPtr, ElementPtr, crew_loss); } } UnlockElement (hElement); } } } static void syreen_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { PEVALUATE_DESC lpEvalDesc; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr != NULL_PTR) { STARSHIPPTR StarShipPtr, EnemyStarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if (!(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & CREW_IMMUNE) && StarShipPtr->special_counter == 0 && lpEvalDesc->ObjectPtr->crew_level > 1 && lpEvalDesc->which_turn <= 14) StarShipPtr->ship_input_state |= SPECIAL; else StarShipPtr->ship_input_state &= ~SPECIAL; } } static void syreen_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { ProcessSound (SetAbsSoundIndex ( /* SYREEN_SONG */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); spawn_crew (ElementPtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } RACE_DESCPTR init_syreen (void) { RACE_DESCPTR RaceDescPtr; syreen_desc.postprocess_func = syreen_postprocess; syreen_desc.init_weapon_func = initialize_dagger; syreen_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) syreen_intelligence; RaceDescPtr = &syreen_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/syreen/Makeinfo0000600000175000017500000000002610543202070017705 0ustar joeyjoeyuqm_CFILES="syreen.c" uqm-0.6.2/sc2/src/sc2code/ships/syreen/respkg.h0000600000175000017500000000006510543202067017706 0ustar joeyjoeyenum { SYREEN_CODE_PACKAGE = 1, SYREEN_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/syreen/resinst.h0000600000175000017500000000015010543202070020067 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/0000755000175000017500000000000010552600274016552 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/chenjesu/restypes.h0000600000175000017500000000024110543202067020564 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/igfxres.h0000600000175000017500000000106710543202067020364 0ustar joeyjoey#define CHENJESU_ICON_MASK_PMAP_ANIM 0x00200002L #define CHENJESU_MICON_MASK_PMAP_ANIM 0x00200102L #define CHENJESU_BIG_MASK_PMAP_ANIM 0x00400202L #define CHENJESU_MED_MASK_PMAP_ANIM 0x00400302L #define CHENJESU_SML_MASK_PMAP_ANIM 0x00400402L #define SPARK_BIG_MASK_PMAP_ANIM 0x00400502L #define SPARK_MED_MASK_PMAP_ANIM 0x00400602L #define SPARK_SML_MASK_PMAP_ANIM 0x00400702L #define DOGGY_BIG_MASK_PMAP_ANIM 0x00400802L #define DOGGY_MED_MASK_PMAP_ANIM 0x00400902L #define DOGGY_SML_MASK_PMAP_ANIM 0x00400a02L #define CHENJESU_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/isndres.h0000600000175000017500000000005310543202067020356 0ustar joeyjoey#define CHENJESU_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/istrtab.h0000600000175000017500000000005410543202067020360 0ustar joeyjoey#define CHENJESU_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/imusicre.h0000600000175000017500000000005410543202067020530 0ustar joeyjoey#define CHENJESU_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/icode.h0000600000175000017500000000004410543202067017772 0ustar joeyjoey#define CHENJESU_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/chenjesu.c0000600000175000017500000003727410543202067020525 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/chenjesu/resinst.h" #include "globdata.h" #include "libs/mathlib.h" #define MAX_CREW 36 #define MAX_ENERGY 30 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 5 #define SPECIAL_ENERGY_COST MAX_ENERGY #define ENERGY_WAIT 4 #define MAX_THRUST /* DISPLAY_TO_WORLD (7) */ 27 #define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 3 #define TURN_WAIT 6 #define THRUST_WAIT 4 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 0 #define MAX_DOGGIES 4 #define SHIP_MASS 10 #define MISSILE_SPEED DISPLAY_TO_WORLD (16) #define MISSILE_LIFE 90 /* actually, it's as long as you * hold the button down. */ static RACE_DESC chenjesu_desc = { { FIRES_FORE | SEEKING_SPECIAL | SEEKING_WEAPON, 28, /* Super Melee cost */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 0, 0, }, (STRING)CHENJESU_RACE_STRINGS, (FRAME)CHENJESU_ICON_MASK_PMAP_ANIM, (FRAME)CHENJESU_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)CHENJESU_BIG_MASK_PMAP_ANIM, (FRAME)CHENJESU_MED_MASK_PMAP_ANIM, (FRAME)CHENJESU_SML_MASK_PMAP_ANIM, }, { (FRAME)SPARK_BIG_MASK_PMAP_ANIM, (FRAME)SPARK_MED_MASK_PMAP_ANIM, (FRAME)SPARK_SML_MASK_PMAP_ANIM, }, { (FRAME)DOGGY_BIG_MASK_PMAP_ANIM, (FRAME)DOGGY_MED_MASK_PMAP_ANIM, (FRAME)DOGGY_SML_MASK_PMAP_ANIM, }, { (FRAME)CHENJESU_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)CHENJESU_VICTORY_SONG, (SOUND)CHENJESU_SHIP_SOUNDS, }, { 0, LONG_RANGE_WEAPON, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define FRAGMENT_LIFE 10 #define FRAGMENT_SPEED MISSILE_SPEED #define FRAGMENT_RANGE (FRAGMENT_LIFE * FRAGMENT_SPEED) static void crystal_postprocess (PELEMENT ElementPtr) { #define FRAGMENT_HITS 1 #define FRAGMENT_DAMAGE 2 #define FRAGMENT_OFFSET 2 #define NUM_FRAGMENTS 8 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ElementPtr, &StarShipPtr); MissileBlock.cx = ElementPtr->next.location.x; MissileBlock.cy = ElementPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.index = 1; MissileBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = 0; MissileBlock.speed = FRAGMENT_SPEED; MissileBlock.hit_points = FRAGMENT_HITS; MissileBlock.damage = FRAGMENT_DAMAGE; MissileBlock.life = FRAGMENT_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = FRAGMENT_OFFSET; for (MissileBlock.face = 0; MissileBlock.face < ANGLE_TO_FACING (FULL_CIRCLE); MissileBlock.face += (ANGLE_TO_FACING (FULL_CIRCLE) / NUM_FRAGMENTS)) { HELEMENT hFragment; hFragment = initialize_missile (&MissileBlock); if (hFragment) { ELEMENTPTR FragPtr; LockElement (hFragment, &FragPtr); SetElementStarShip (FragPtr, StarShipPtr); UnlockElement (hFragment); PutElement (hFragment); } } ProcessSound (SetAbsSoundIndex ( /* CRYSTAL_FRAGMENTS */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); } static void crystal_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->cur_status_flags & WEAPON) ++ElementPtr->life_span; /* keep it going while key pressed */ else { ElementPtr->life_span = 1; ElementPtr->postprocess_func = crystal_postprocess; } } static void animate (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = ElementPtr->next_turn; } } static void crystal_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { HELEMENT hBlastElement; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if (hBlastElement) { ELEMENTPTR BlastElementPtr; #define NUM_SPARKLES 8 LockElement (hBlastElement, &BlastElementPtr); BlastElementPtr->current.location = ElementPtr1->current.location; BlastElementPtr->life_span = NUM_SPARKLES; BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; { BlastElementPtr->preprocess_func = animate; } BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; BlastElementPtr->current.image.frame = SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], 2); /* skip stones */ UnlockElement (hBlastElement); } } #define DOGGY_OFFSET 18 #define DOGGY_SPEED DISPLAY_TO_WORLD (8) static void doggy_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); ++StarShipPtr->special_counter; if (ElementPtr->thrust_wait > 0) /* could be non-zero after a collision */ --ElementPtr->thrust_wait; else { COUNT facing, orig_facing; SIZE delta_facing; facing = orig_facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity) )); if ((delta_facing = TrackShip (ElementPtr, &facing)) < 0) facing = NORMALIZE_FACING (TFB_Random ()); else { ELEMENTPTR ShipPtr; LockElement (ElementPtr->hTarget, &ShipPtr); facing = NORMALIZE_FACING (ANGLE_TO_FACING ( ARCTAN (ShipPtr->current.location.x - ElementPtr->current.location.x, ShipPtr->current.location.y - ElementPtr->current.location.y) )); delta_facing = NORMALIZE_FACING (facing - GetFrameIndex (ShipPtr->current.image.frame)); UnlockElement (ElementPtr->hTarget); if (delta_facing > ANGLE_TO_FACING (HALF_CIRCLE - OCTANT) && delta_facing < ANGLE_TO_FACING (HALF_CIRCLE + OCTANT)) { if (delta_facing >= ANGLE_TO_FACING (HALF_CIRCLE)) facing -= ANGLE_TO_FACING (QUADRANT); else facing += ANGLE_TO_FACING (QUADRANT); } facing = NORMALIZE_FACING (facing); } if (facing != orig_facing) SetVelocityVector (&ElementPtr->velocity, DOGGY_SPEED, facing); } } static void doggy_death (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); ProcessSound (SetAbsSoundIndex ( /* DOGGY_DIES */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3), ElementPtr); ElementPtr->state_flags &= ~DISAPPEARING; ElementPtr->state_flags |= NONSOLID | FINITE_LIFE; ElementPtr->life_span = 6; { ElementPtr->preprocess_func = animate; } ElementPtr->death_func = NULL_PTR; ElementPtr->collision_func = NULL_PTR; ZeroVelocityComponents (&ElementPtr->velocity); ElementPtr->turn_wait = ElementPtr->next_turn = 0; } static void doggy_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { #define ENERGY_DRAIN 10 collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if ((ElementPtr1->state_flags & PLAYER_SHIP) && (ElementPtr0->state_flags & (GOOD_GUY | BAD_GUY)) != (ElementPtr1->state_flags & (GOOD_GUY | BAD_GUY))) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr0, &StarShipPtr); ProcessSound (SetAbsSoundIndex ( /* DOGGY_STEALS_ENERGY */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), ElementPtr0); GetElementStarShip (ElementPtr1, &StarShipPtr); if (StarShipPtr->RaceDescPtr->ship_info.energy_level < ENERGY_DRAIN) DeltaEnergy (ElementPtr1, -StarShipPtr->RaceDescPtr->ship_info.energy_level); else DeltaEnergy (ElementPtr1, -ENERGY_DRAIN); } if (ElementPtr0->thrust_wait <= COLLISION_THRUST_WAIT) ElementPtr0->thrust_wait += COLLISION_THRUST_WAIT << 1; } #define CHENJESU_OFFSET 16 static void spawn_doggy (PELEMENT ElementPtr) { HELEMENT hDoggyElement; if ((hDoggyElement = AllocElement ()) != 0) { COUNT angle; ELEMENTPTR DoggyElementPtr; STARSHIPPTR StarShipPtr; ElementPtr->state_flags |= DEFY_PHYSICS; PutElement (hDoggyElement); LockElement (hDoggyElement, &DoggyElementPtr); DoggyElementPtr->hit_points = 3; DoggyElementPtr->mass_points = 4; DoggyElementPtr->thrust_wait = 0; DoggyElementPtr->state_flags = APPEARING | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); DoggyElementPtr->life_span = NORMAL_LIFE; SetPrimType (&(GLOBAL (DisplayArray))[DoggyElementPtr->PrimIndex], STAMP_PRIM); { DoggyElementPtr->preprocess_func = doggy_preprocess; DoggyElementPtr->postprocess_func = NULL_PTR; DoggyElementPtr->collision_func = doggy_collision; DoggyElementPtr->death_func = doggy_death; } GetElementStarShip (ElementPtr, &StarShipPtr); angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; DoggyElementPtr->current.location.x = ElementPtr->next.location.x + COSINE (angle, DISPLAY_TO_WORLD (CHENJESU_OFFSET + DOGGY_OFFSET)); DoggyElementPtr->current.location.y = ElementPtr->next.location.y + SINE (angle, DISPLAY_TO_WORLD (CHENJESU_OFFSET + DOGGY_OFFSET)); DoggyElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; DoggyElementPtr->current.image.frame = StarShipPtr->RaceDescPtr->ship_data.special[0]; SetVelocityVector (&DoggyElementPtr->velocity, DOGGY_SPEED, NORMALIZE_FACING (ANGLE_TO_FACING (angle))); SetElementStarShip (DoggyElementPtr, StarShipPtr); ProcessSound (SetAbsSoundIndex ( /* RELEASE_DOGGY */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 4), DoggyElementPtr); UnlockElement (hDoggyElement); } } static void chenjesu_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { PEVALUATE_DESC lpEvalDesc; STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->ship_input_state &= ~SPECIAL; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { STARSHIPPTR EnemyStarShipPtr; GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if ((lpEvalDesc->which_turn <= 16 && MANEUVERABILITY ( &EnemyStarShipPtr->RaceDescPtr->cyborg_control ) >= MEDIUM_SHIP) || (MANEUVERABILITY ( &EnemyStarShipPtr->RaceDescPtr->cyborg_control ) <= SLOW_SHIP && WEAPON_RANGE ( &EnemyStarShipPtr->RaceDescPtr->cyborg_control ) >= LONG_RANGE_WEAPON * 3 / 4 && (EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_WEAPON))) lpEvalDesc->MoveState = PURSUE; } if (StarShipPtr->special_counter == 1 && ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr && ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState == ENTICE && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 8) { lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (lpEvalDesc->ObjectPtr) { HELEMENT h, hNext; ELEMENTPTR CrystalPtr; h = (StarShipPtr->old_status_flags & WEAPON) ? GetTailElement () : (HELEMENT)0; for (; h; h = hNext) { LockElement (h, &CrystalPtr); hNext = GetPredElement (CrystalPtr); if (!(CrystalPtr->state_flags & NONSOLID) && CrystalPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.weapon && CrystalPtr->preprocess_func && CrystalPtr->life_span > 0 && (CrystalPtr->state_flags & (GOOD_GUY | BAD_GUY)) == (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY))) { if (ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr) { COUNT which_turn; if ((which_turn = PlotIntercept (CrystalPtr, ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr, CrystalPtr->life_span, FRAGMENT_RANGE / 2)) == 0 || (which_turn == 1 && PlotIntercept (CrystalPtr, ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr, CrystalPtr->life_span, 0) == 0)) StarShipPtr->ship_input_state &= ~WEAPON; else if (StarShipPtr->weapon_counter == 0) { StarShipPtr->ship_input_state |= WEAPON; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; } UnlockElement (h); break; } hNext = 0; } UnlockElement (h); } if (h == 0) { if (StarShipPtr->old_status_flags & WEAPON) { StarShipPtr->ship_input_state &= ~WEAPON; if (lpEvalDesc == &ObjectsOfConcern[ENEMY_WEAPON_INDEX]) StarShipPtr->weapon_counter = 3; } else if (StarShipPtr->weapon_counter == 0 && ship_weapons (ShipPtr, lpEvalDesc->ObjectPtr, FRAGMENT_RANGE / 2)) StarShipPtr->ship_input_state |= WEAPON; } } if (StarShipPtr->special_counter < MAX_DOGGIES) { if (lpEvalDesc->ObjectPtr && StarShipPtr->RaceDescPtr->ship_info.energy_level <= SPECIAL_ENERGY_COST && !(StarShipPtr->ship_input_state & WEAPON)) StarShipPtr->ship_input_state |= SPECIAL; } } static COUNT initialize_crystal (PELEMENT ShipPtr, HELEMENT CrystalArray[]) { #define MISSILE_HITS 10 #define MISSILE_DAMAGE 6 #define MISSILE_OFFSET 0 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = CHENJESU_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = crystal_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; CrystalArray[0] = initialize_missile (&MissileBlock); if (CrystalArray[0]) { ELEMENTPTR CrystalPtr; LockElement (CrystalArray[0], &CrystalPtr); CrystalPtr->collision_func = crystal_collision; UnlockElement (CrystalArray[0]); } return (1); } static void chenjesu_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter < MAX_DOGGIES && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { spawn_doggy (ElementPtr); } StarShipPtr->special_counter = 1; /* say there is one doggy, because ship_postprocess will * decrement special_counter */ } static void chenjesu_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->special_counter > 1) /* only when STANDARD * computer opponent */ StarShipPtr->special_counter += MAX_DOGGIES; if (StarShipPtr->cur_status_flags & StarShipPtr->old_status_flags & WEAPON) ++StarShipPtr->weapon_counter; } RACE_DESCPTR init_chenjesu (void) { RACE_DESCPTR RaceDescPtr; chenjesu_desc.preprocess_func = chenjesu_preprocess; chenjesu_desc.postprocess_func = chenjesu_postprocess; chenjesu_desc.init_weapon_func = initialize_crystal; chenjesu_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) chenjesu_intelligence; RaceDescPtr = &chenjesu_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/Makeinfo0000600000175000017500000000003010543202067020205 0ustar joeyjoeyuqm_CFILES="chenjesu.c" uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/respkg.h0000600000175000017500000000007110543202067020202 0ustar joeyjoeyenum { CHENJESU_CODE_PACKAGE = 1, CHENJESU_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/resinst.h0000600000175000017500000000015010543202067020374 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/chenjesu/chenjesu.res0000600000175000017500000000154010543202067021057 0ustar joeyjoeyINCLUDE ../star3do.typ PATH chenjesu PACKAGE CHENJESU_CODE_PACKAGE chenjesu.shp CODE CHENJESU_CODE chenjesu.cod GFXRES CHENJESU_ICON_MASK_PMAP_ANIM cheicons.ani GFXRES CHENJESU_MICON_MASK_PMAP_ANIM chemicon.ani STRTAB CHENJESU_RACE_STRINGS chetext.txt PACKAGE CHENJESU_PACKAGE chenjesu.shp GFXRES CHENJESU_BIG_MASK_PMAP_ANIM chenjesu.big GFXRES CHENJESU_MED_MASK_PMAP_ANIM chenjesu.med GFXRES CHENJESU_SML_MASK_PMAP_ANIM chenjesu.sml GFXRES SPARK_BIG_MASK_PMAP_ANIM spark.big GFXRES SPARK_MED_MASK_PMAP_ANIM spark.med GFXRES SPARK_SML_MASK_PMAP_ANIM spark.sml GFXRES DOGGY_BIG_MASK_PMAP_ANIM doggy.big GFXRES DOGGY_MED_MASK_PMAP_ANIM doggy.med GFXRES DOGGY_SML_MASK_PMAP_ANIM doggy.sml GFXRES CHENJESU_CAPTAIN_MASK_PMAP_ANIM checap.ani SNDRES CHENJESU_SHIP_SOUNDS chesound.snd MUSICRES CHENJESU_VICTORY_SONG cheditty.mod uqm-0.6.2/sc2/src/sc2code/ships/melnorme/0000755000175000017500000000000010552600274016564 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/melnorme/melnorme.c0000600000175000017500000004226010543202074020536 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/melnorme/resinst.h" #include "globdata.h" #include "libs/mathlib.h" #define MAX_CREW 20 #define MAX_ENERGY MAX_ENERGY_SIZE #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 5 #define SPECIAL_ENERGY_COST 20 #define ENERGY_WAIT 4 #define MAX_THRUST 36 #define THRUST_INCREMENT 6 #define TURN_WAIT 4 #define THRUST_WAIT 4 #define WEAPON_WAIT 1 #define SPECIAL_WAIT 20 #define SHIP_MASS 7 #define PUMPUP_SPEED DISPLAY_TO_WORLD (45) #define PUMPUP_LIFE 10 static RACE_DESC melnorme_desc = { { FIRES_FORE, 18, /* Super Melee cost */ ~0, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { MAX_X_UNIVERSE >> 1, MAX_Y_UNIVERSE >> 1, }, (STRING)MELNORME_RACE_STRINGS, (FRAME)MELNORME_ICON_MASK_PMAP_ANIM, (FRAME)MELNORME_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)MELNORME_BIG_MASK_PMAP_ANIM, (FRAME)MELNORME_MED_MASK_PMAP_ANIM, (FRAME)MELNORME_SML_MASK_PMAP_ANIM, }, { (FRAME)PUMPUP_BIG_MASK_PMAP_ANIM, (FRAME)PUMPUP_MED_MASK_PMAP_ANIM, (FRAME)PUMPUP_SML_MASK_PMAP_ANIM, }, { (FRAME)CONFUSE_BIG_MASK_PMAP_ANIM, (FRAME)CONFUSE_MED_MASK_PMAP_ANIM, (FRAME)CONFUSE_SML_MASK_PMAP_ANIM, }, { (FRAME)MELNORME_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)MELNORME_VICTORY_SONG, (SOUND)MELNORME_SHIP_SOUNDS, }, { 0, PUMPUP_SPEED * PUMPUP_LIFE, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define NUM_PUMP_ANIMS 5 #define REVERSE_DIR (BYTE)(1 << 7) static void pump_up_preprocess (PELEMENT ElementPtr) { if (--ElementPtr->thrust_wait & 1) { COUNT frame_index; frame_index = GetFrameIndex (ElementPtr->current.image.frame); if (((ElementPtr->turn_wait & REVERSE_DIR) && (frame_index % NUM_PUMP_ANIMS) != 0) || (!(ElementPtr->turn_wait & REVERSE_DIR) && ((frame_index + 1) % NUM_PUMP_ANIMS) == 0)) { --frame_index; ElementPtr->turn_wait |= REVERSE_DIR; } else { ++frame_index; ElementPtr->turn_wait &= ~REVERSE_DIR; } ElementPtr->next.image.frame = SetAbsFrameIndex ( ElementPtr->current.image.frame, frame_index); ElementPtr->state_flags |= CHANGING; } } static COUNT initialize_pump_up (PELEMENT ShipPtr, HELEMENT PumpUpArray[]); #define MELNORME_OFFSET 24 #define LEVEL_COUNTER 72 #define MAX_PUMP 4 #define PUMPUP_DAMAGE 2 static void pump_up_postprocess (PELEMENT ElementPtr) { if (ElementPtr->state_flags & APPEARING) { ZeroVelocityComponents (&ElementPtr->velocity); } else { HELEMENT hPumpUp; ELEMENTPTR EPtr, ShipPtr; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ShipPtr); initialize_pump_up (ShipPtr, &hPumpUp); DeltaEnergy (ShipPtr, 0); UnlockElement (StarShipPtr->hShip); LockElement (hPumpUp, &EPtr); EPtr->current.image.frame = ElementPtr->current.image.frame; EPtr->turn_wait = ElementPtr->turn_wait; EPtr->thrust_wait = ElementPtr->thrust_wait; if (--EPtr->thrust_wait == 0) { if ((EPtr->turn_wait & ~REVERSE_DIR) < MAX_PUMP - 1) { ++EPtr->turn_wait; EPtr->current.image.frame = SetRelFrameIndex ( EPtr->current.image.frame, NUM_PUMP_ANIMS); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), EPtr); } EPtr->thrust_wait = LEVEL_COUNTER; } EPtr->mass_points = EPtr->hit_points = (PUMPUP_DAMAGE << (ElementPtr->turn_wait & ~REVERSE_DIR)); SetElementStarShip (EPtr, StarShipPtr); if (EPtr->thrust_wait & 1) { COUNT frame_index; frame_index = GetFrameIndex (EPtr->current.image.frame); if (((EPtr->turn_wait & REVERSE_DIR) && (frame_index % NUM_PUMP_ANIMS) != 0) || (!(EPtr->turn_wait & REVERSE_DIR) && ((frame_index + 1) % NUM_PUMP_ANIMS) == 0)) { --frame_index; EPtr->turn_wait |= REVERSE_DIR; } else { ++frame_index; EPtr->turn_wait &= ~REVERSE_DIR; } EPtr->current.image.frame = SetAbsFrameIndex ( EPtr->current.image.frame, frame_index); } if (StarShipPtr->cur_status_flags & StarShipPtr->old_status_flags & WEAPON) { StarShipPtr->weapon_counter = WEAPON_WAIT; } else { COUNT angle; EPtr->life_span = PUMPUP_LIFE; EPtr->preprocess_func = pump_up_preprocess; EPtr->postprocess_func = 0; angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); SetVelocityComponents (&EPtr->velocity, COSINE (angle, WORLD_TO_VELOCITY (PUMPUP_SPEED)), SINE (angle, WORLD_TO_VELOCITY (PUMPUP_SPEED))); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3), EPtr); } UnlockElement (hPumpUp); PutElement (hPumpUp); SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->state_flags |= NONSOLID; } } static void animate (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = ElementPtr->next_turn; } } static void pump_up_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { RECT r; BYTE old_thrust_wait; HELEMENT hBlastElement; GetFrameRect (ElementPtr0->next.image.frame, &r); old_thrust_wait = ElementPtr0->thrust_wait; ElementPtr0->blast_offset = r.extent.width >> 1; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); ElementPtr0->thrust_wait = old_thrust_wait; if (hBlastElement) { ELEMENTPTR BlastElementPtr; #define MIN_PUMPITUDE_ANIMS 3 LockElement (hBlastElement, &BlastElementPtr); BlastElementPtr->life_span = MIN_PUMPITUDE_ANIMS + (ElementPtr0->turn_wait & ~REVERSE_DIR); BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; { BlastElementPtr->preprocess_func = animate; } BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; BlastElementPtr->current.image.frame = SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], MAX_PUMP * NUM_PUMP_ANIMS); UnlockElement (hBlastElement); } } static COUNT initialize_pump_up (PELEMENT ShipPtr, HELEMENT PumpUpArray[]) { STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = MELNORME_OFFSET; MissileBlock.speed = DISPLAY_TO_WORLD (MELNORME_OFFSET); MissileBlock.hit_points = PUMPUP_DAMAGE; MissileBlock.damage = PUMPUP_DAMAGE; MissileBlock.life = 2; MissileBlock.preprocess_func = 0; MissileBlock.blast_offs = 0; PumpUpArray[0] = initialize_missile (&MissileBlock); if (PumpUpArray[0]) { ELEMENTPTR PumpUpPtr; LockElement (PumpUpArray[0], &PumpUpPtr); PumpUpPtr->postprocess_func = pump_up_postprocess; PumpUpPtr->collision_func = pump_up_collision; PumpUpPtr->thrust_wait = LEVEL_COUNTER; UnlockElement (PumpUpArray[0]); } return (1); } static void confuse_preprocess (PELEMENT ElementPtr) { if (!(ElementPtr->state_flags & NONSOLID)) { ElementPtr->next.image.frame = SetAbsFrameIndex ( ElementPtr->current.image.frame, (GetFrameIndex (ElementPtr->current.image.frame) + 1) & 7); ElementPtr->state_flags |= CHANGING; } else if (ElementPtr->hTarget == 0) { ElementPtr->life_span = 0; ElementPtr->state_flags |= DISAPPEARING; } else { ELEMENTPTR eptr; LockElement (ElementPtr->hTarget, &eptr); ElementPtr->next.location = eptr->next.location; if (ElementPtr->turn_wait) { HELEMENT hEffect; STARSHIPPTR StarShipPtr; if (GetFrameIndex (ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame)) == 0) ElementPtr->next.image.frame = SetRelFrameIndex (ElementPtr->next.image.frame, -8); GetElementStarShip (eptr, &StarShipPtr); StarShipPtr->ship_input_state = (StarShipPtr->ship_input_state & ~(LEFT | RIGHT | SPECIAL)) | ElementPtr->turn_wait; hEffect = AllocElement (); if (hEffect) { LockElement (hEffect, &eptr); eptr->state_flags = FINITE_LIFE | NONSOLID | CHANGING | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); eptr->life_span = 1; eptr->current = eptr->next = ElementPtr->next; eptr->preprocess_func = confuse_preprocess; SetPrimType (&(GLOBAL (DisplayArray))[eptr->PrimIndex], STAMP_PRIM); GetElementStarShip (ElementPtr, &StarShipPtr); SetElementStarShip (eptr, StarShipPtr); eptr->hTarget = ElementPtr->hTarget; UnlockElement (hEffect); PutElement (hEffect); } } UnlockElement (ElementPtr->hTarget); } } static void confusion_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if (ElementPtr1->state_flags & PLAYER_SHIP) { HELEMENT hConfusionElement, hNextElement; ELEMENTPTR ConfusionPtr; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr0, &StarShipPtr); for (hConfusionElement = GetHeadElement (); hConfusionElement; hConfusionElement = hNextElement) { LockElement (hConfusionElement, &ConfusionPtr); if ((ConfusionPtr->state_flags & (GOOD_GUY | BAD_GUY)) == (ElementPtr0->state_flags & (GOOD_GUY | BAD_GUY)) && ConfusionPtr->current.image.farray == StarShipPtr->RaceDescPtr->ship_data.special && (ConfusionPtr->state_flags & NONSOLID)) { UnlockElement (hConfusionElement); break; } hNextElement = GetSuccElement (ConfusionPtr); UnlockElement (hConfusionElement); } if (hConfusionElement || (hConfusionElement = AllocElement ())) { LockElement (hConfusionElement, &ConfusionPtr); if (ConfusionPtr->state_flags == 0) /* not allocated before */ { InsertElement (hConfusionElement, GetHeadElement ()); ConfusionPtr->current = ElementPtr0->next; ConfusionPtr->current.image.frame = SetAbsFrameIndex ( ConfusionPtr->current.image.frame, 8 ); ConfusionPtr->next = ConfusionPtr->current; ConfusionPtr->state_flags = FINITE_LIFE | NONSOLID | CHANGING | (ElementPtr0->state_flags & (GOOD_GUY | BAD_GUY)); ConfusionPtr->preprocess_func = confuse_preprocess; SetPrimType ( &(GLOBAL (DisplayArray))[ConfusionPtr->PrimIndex], NO_PRIM ); SetElementStarShip (ConfusionPtr, StarShipPtr); GetElementStarShip (ElementPtr1, &StarShipPtr); ConfusionPtr->hTarget = StarShipPtr->hShip; } ConfusionPtr->life_span = 400; ConfusionPtr->turn_wait = (BYTE)(1 << ((BYTE)TFB_Random () & 1)); /* LEFT or RIGHT */ UnlockElement (hConfusionElement); } ElementPtr0->hit_points = 0; ElementPtr0->life_span = 0; ElementPtr0->state_flags |= DISAPPEARING | COLLISION | NONSOLID; } (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } static COUNT initialize_confusion (PELEMENT ShipPtr, HELEMENT ConfusionArray[]) { #define CMISSILE_SPEED DISPLAY_TO_WORLD (30) #define CMISSILE_HITS 200 #define CMISSILE_DAMAGE 0 #define CMISSILE_LIFE 20 #define CMISSILE_OFFSET 4 STARSHIPPTR StarShipPtr; MISSILE_BLOCK ConfusionBlock; GetElementStarShip (ShipPtr, &StarShipPtr); ConfusionBlock.cx = ShipPtr->next.location.x; ConfusionBlock.cy = ShipPtr->next.location.y; ConfusionBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; ConfusionBlock.index = 0; ConfusionBlock.face = StarShipPtr->ShipFacing; ConfusionBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; ConfusionBlock.pixoffs = MELNORME_OFFSET; ConfusionBlock.speed = CMISSILE_SPEED; ConfusionBlock.hit_points = CMISSILE_HITS; ConfusionBlock.damage = CMISSILE_DAMAGE; ConfusionBlock.life = CMISSILE_LIFE; ConfusionBlock.preprocess_func = confuse_preprocess; ConfusionBlock.blast_offs = CMISSILE_OFFSET; ConfusionArray[0] = initialize_missile (&ConfusionBlock); if (ConfusionArray[0]) { ELEMENTPTR CMissilePtr; LockElement (ConfusionArray[0], &CMissilePtr); CMissilePtr->collision_func = confusion_collision; SetElementStarShip (CMissilePtr, StarShipPtr); UnlockElement (ConfusionArray[0]); } return (1); } static COUNT initialize_test_pump_up (PELEMENT ShipPtr, HELEMENT PumpUpArray[]) { STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; //ELEMENTPTR PumpUpPtr; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = MELNORME_OFFSET; MissileBlock.speed = PUMPUP_SPEED; MissileBlock.hit_points = PUMPUP_DAMAGE; MissileBlock.damage = PUMPUP_DAMAGE; MissileBlock.life = PUMPUP_LIFE; MissileBlock.preprocess_func = 0; MissileBlock.blast_offs = 0; PumpUpArray[0] = initialize_missile (&MissileBlock); return (1); } static void melnorme_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { BYTE old_count; STARSHIPPTR StarShipPtr; PEVALUATE_DESC lpEvalDesc; GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->RaceDescPtr->init_weapon_func = initialize_test_pump_up; old_count = StarShipPtr->weapon_counter; if (StarShipPtr->weapon_counter == WEAPON_WAIT) StarShipPtr->weapon_counter = 0; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { if (StarShipPtr->RaceDescPtr->ship_info.energy_level < SPECIAL_ENERGY_COST + WEAPON_ENERGY_COST && !(StarShipPtr->old_status_flags & WEAPON)) lpEvalDesc->MoveState = ENTICE; else { STARSHIPPTR EnemyStarShipPtr; GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if (!(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & IMMEDIATE_WEAPON)) lpEvalDesc->MoveState = PURSUE; } } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (StarShipPtr->weapon_counter == 0 && (old_count != 0 || ((StarShipPtr->special_counter || StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST + WEAPON_ENERGY_COST) && !(StarShipPtr->ship_input_state & WEAPON)))) StarShipPtr->ship_input_state ^= WEAPON; StarShipPtr->ship_input_state &= ~SPECIAL; if (StarShipPtr->special_counter == 0 && StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST) { BYTE old_input_state; old_input_state = StarShipPtr->ship_input_state; StarShipPtr->RaceDescPtr->init_weapon_func = initialize_confusion; ++ShipPtr->turn_wait; ++ShipPtr->thrust_wait; ship_intelligence (ShipPtr, ObjectsOfConcern, ENEMY_SHIP_INDEX + 1); --ShipPtr->thrust_wait; --ShipPtr->turn_wait; if (StarShipPtr->ship_input_state & WEAPON) { StarShipPtr->ship_input_state &= ~WEAPON; StarShipPtr->ship_input_state |= SPECIAL; } StarShipPtr->ship_input_state = (unsigned char)(old_input_state | (StarShipPtr->ship_input_state & SPECIAL)); } StarShipPtr->weapon_counter = old_count; StarShipPtr->RaceDescPtr->init_weapon_func = initialize_pump_up; } static void melnorme_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { HELEMENT Confusion; initialize_confusion (ElementPtr, &Confusion); if (Confusion) { ELEMENTPTR CMissilePtr; LockElement (Confusion, &CMissilePtr); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), CMissilePtr); UnlockElement (Confusion); PutElement (Confusion); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } } RACE_DESCPTR init_melnorme (void) { RACE_DESCPTR RaceDescPtr; melnorme_desc.postprocess_func = melnorme_postprocess; melnorme_desc.init_weapon_func = initialize_pump_up; melnorme_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) melnorme_intelligence; RaceDescPtr = &melnorme_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/melnorme/restypes.h0000600000175000017500000000024110543202074020574 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/melnorme/igfxres.h0000600000175000017500000000110010543202074020360 0ustar joeyjoey#define MELNORME_ICON_MASK_PMAP_ANIM 0x00200002L #define MELNORME_MICON_MASK_PMAP_ANIM 0x00200102L #define MELNORME_BIG_MASK_PMAP_ANIM 0x00400202L #define MELNORME_MED_MASK_PMAP_ANIM 0x00400302L #define MELNORME_SML_MASK_PMAP_ANIM 0x00400402L #define PUMPUP_BIG_MASK_PMAP_ANIM 0x00400502L #define PUMPUP_MED_MASK_PMAP_ANIM 0x00400602L #define PUMPUP_SML_MASK_PMAP_ANIM 0x00400702L #define CONFUSE_BIG_MASK_PMAP_ANIM 0x00400802L #define CONFUSE_MED_MASK_PMAP_ANIM 0x00400902L #define CONFUSE_SML_MASK_PMAP_ANIM 0x00400a02L #define MELNORME_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/melnorme/isndres.h0000600000175000017500000000005310543202074020366 0ustar joeyjoey#define MELNORME_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/melnorme/istrtab.h0000600000175000017500000000005410543202074020370 0ustar joeyjoey#define MELNORME_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/melnorme/imusicre.h0000600000175000017500000000005410543202074020540 0ustar joeyjoey#define MELNORME_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/melnorme/icode.h0000600000175000017500000000004410543202074020002 0ustar joeyjoey#define MELNORME_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/melnorme/Makeinfo0000600000175000017500000000003010543202074020215 0ustar joeyjoeyuqm_CFILES="melnorme.c" uqm-0.6.2/sc2/src/sc2code/ships/melnorme/respkg.h0000600000175000017500000000007110543202074020212 0ustar joeyjoeyenum { MELNORME_CODE_PACKAGE = 1, MELNORME_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/melnorme/resinst.h0000600000175000017500000000015010543202074020404 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/melnorme/melnorme.res0000600000175000017500000000156710543202074021112 0ustar joeyjoeyINCLUDE ../star3do.typ PATH melnorme PACKAGE MELNORME_CODE_PACKAGE melnorme.shp CODE MELNORME_CODE melnorme.cod GFXRES MELNORME_ICON_MASK_PMAP_ANIM melicons.ani GFXRES MELNORME_MICON_MASK_PMAP_ANIM melmicon.ani STRTAB MELNORME_RACE_STRINGS meltext.txt PACKAGE MELNORME_PACKAGE melnorme.shp GFXRES MELNORME_BIG_MASK_PMAP_ANIM melnorme.big GFXRES MELNORME_MED_MASK_PMAP_ANIM melnorme.med GFXRES MELNORME_SML_MASK_PMAP_ANIM melnorme.sml GFXRES PUMPUP_BIG_MASK_PMAP_ANIM pumpbig.ani GFXRES PUMPUP_MED_MASK_PMAP_ANIM pumpmed.ani GFXRES PUMPUP_SML_MASK_PMAP_ANIM pumpsml.ani GFXRES CONFUSE_BIG_MASK_PMAP_ANIM confubig.ani GFXRES CONFUSE_MED_MASK_PMAP_ANIM confumed.ani GFXRES CONFUSE_SML_MASK_PMAP_ANIM confusml.ani GFXRES MELNORME_CAPTAIN_MASK_PMAP_ANIM melcap.ani SNDRES MELNORME_SHIP_SOUNDS melsound.snd MUSICRES MELNORME_VICTORY_SONG melditty.mod uqm-0.6.2/sc2/src/sc2code/ships/sis_ship/0000755000175000017500000000000010552600274016567 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/sis_ship/restypes.h0000600000175000017500000000024110543202057020600 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/sis_ship/igfxres.h0000600000175000017500000000063010543202060020365 0ustar joeyjoey#define SIS_ICON_MASK_PMAP_ANIM 0x00400002L #define SIS_BIG_MASK_PMAP_ANIM 0x00400102L #define SIS_MED_MASK_PMAP_ANIM 0x00400202L #define SIS_SML_MASK_PMAP_ANIM 0x00400302L #define BLASTER_BIG_MASK_PMAP_ANIM 0x00400402L #define BLASTER_MED_MASK_PMAP_ANIM 0x00400502L #define BLASTER_SML_MASK_PMAP_ANIM 0x00400602L #define SIS_CAPTAIN_MASK_PMAP_ANIM 0x00400702L #define SIS_HYPER_MASK_PMAP_ANIM 0x00600802L uqm-0.6.2/sc2/src/sc2code/ships/sis_ship/sis.res0000600000175000017500000000122510543202057020065 0ustar joeyjoeyINCLUDE ../star3do.typ PATH sis_ship PACKAGE SIS_CODE_PACKAGE sis.dat CODE SIS_CODE sis.cod PACKAGE SIS_BATTLE_PACKAGE sis.dat GFXRES SIS_ICON_MASK_PMAP_ANIM sisicons.ani GFXRES SIS_BIG_MASK_PMAP_ANIM sis.big GFXRES SIS_MED_MASK_PMAP_ANIM sis.med GFXRES SIS_SML_MASK_PMAP_ANIM sis.sml GFXRES BLASTER_BIG_MASK_PMAP_ANIM blasbig.ani GFXRES BLASTER_MED_MASK_PMAP_ANIM blasmed.ani GFXRES BLASTER_SML_MASK_PMAP_ANIM blassml.ani GFXRES SIS_CAPTAIN_MASK_PMAP_ANIM siscap.ani SNDRES SIS_SHIP_SOUNDS sissound.snd MUSICRES SIS_VICTORY_SONG sisditty.mod PACKAGE SIS_HYPER_PACKAGE sis.dat GFXRES SIS_HYPER_MASK_PMAP_ANIM sishyper.ani uqm-0.6.2/sc2/src/sc2code/ships/sis_ship/isndres.h0000600000175000017500000000004610543202060020366 0ustar joeyjoey#define SIS_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/sis_ship/imusicre.h0000600000175000017500000000004710543202057020546 0ustar joeyjoey#define SIS_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/sis_ship/icode.h0000600000175000017500000000003710543202057020010 0ustar joeyjoey#define SIS_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/sis_ship/sis_ship.c0000644000175000017500000005626110550331705020564 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/sis_ship/resinst.h" #include "colors.h" #include "controls.h" #include "globdata.h" #include "libs/mathlib.h" #define MAX_TRACKING 3 #define MAX_DEFENSE 8 #define MAX_CREW MAX_CREW_SIZE #define MAX_ENERGY MAX_ENERGY_SIZE #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 1 #define SPECIAL_ENERGY_COST 0 #define ENERGY_WAIT 10 #define MAX_THRUST 10 #define THRUST_INCREMENT 4 #define TURN_WAIT 17 #define THRUST_WAIT 6 #define WEAPON_WAIT 6 #define SPECIAL_WAIT 9 #define SHIP_MASS MAX_SHIP_MASS #define BLASTER_SPEED DISPLAY_TO_WORLD (24) #define BLASTER_LIFE 12 static RACE_DESC sis_desc = { { 0, 16, /* Super Melee cost */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 0, 0, }, 0, (FRAME)SIS_ICON_MASK_PMAP_ANIM, 0, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)SIS_BIG_MASK_PMAP_ANIM, (FRAME)SIS_MED_MASK_PMAP_ANIM, (FRAME)SIS_SML_MASK_PMAP_ANIM, }, { (FRAME)BLASTER_BIG_MASK_PMAP_ANIM, (FRAME)BLASTER_MED_MASK_PMAP_ANIM, (FRAME)BLASTER_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)SIS_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)SIS_VICTORY_SONG, (SOUND)SIS_SHIP_SOUNDS, }, { 0, BLASTER_SPEED * BLASTER_LIFE, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static void InitModuleSlots (RACE_DESCPTR RaceDescPtr, const BYTE *ModuleSlots); static void InitDriveSlots (RACE_DESCPTR RaceDescPtr, const BYTE *DriveSlots); static void InitJetSlots (RACE_DESCPTR RaceDescPtr, const BYTE *JetSlots); void uninit_sis (RACE_DESCPTR pRaceDesc); static BYTE num_trackers = 0; static void sis_hyper_preprocess (PELEMENT ElementPtr) { SIZE udx, udy, dx, dy; SIZE AccelerateDirection; STARSHIPPTR StarShipPtr; if (ElementPtr->state_flags & APPEARING) ElementPtr->velocity = GLOBAL (velocity); AccelerateDirection = 0; GetElementStarShip (ElementPtr, &StarShipPtr); ++StarShipPtr->weapon_counter; /* no shooting in hyperspace! */ if ((GLOBAL (autopilot)).x == ~0 || (GLOBAL (autopilot)).y == ~0 || (StarShipPtr->cur_status_flags & (LEFT | RIGHT | THRUST))) { LeaveAutoPilot: (GLOBAL (autopilot)).x = (GLOBAL (autopilot)).y = ~0; if (!(StarShipPtr->cur_status_flags & THRUST) || (GLOBAL_SIS (FuelOnBoard) == 0 && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1)) { AccelerateDirection = -1; GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); udx = dx << 4; udy = dy << 4; StarShipPtr->cur_status_flags &= ~THRUST; } } else { SIZE facing; POINT universe; universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); udx = (GLOBAL (autopilot)).x - universe.x; udy = -((GLOBAL (autopilot)).y - universe.y); if ((dx = udx) < 0) dx = -dx; if ((dy = udy) < 0) dy = -dy; if (dx <= 1 && dy <= 1) goto LeaveAutoPilot; facing = NORMALIZE_FACING (ANGLE_TO_FACING (ARCTAN (udx, udy))); /* This prevents ship from flying backwards on auto-pilot. * It could also theoretically abort autopilot in a bad savegame */ if ((StarShipPtr->cur_status_flags & SHIP_AT_MAX_SPEED) /*|| (ElementPtr->state_flags & APPEARING)*/ ) { if (NORMALIZE_FACING (StarShipPtr->ShipFacing + ANGLE_TO_FACING (QUADRANT) - facing) > ANGLE_TO_FACING (HALF_CIRCLE)) goto LeaveAutoPilot; facing = StarShipPtr->ShipFacing; } else if ((int)facing != (int)StarShipPtr->ShipFacing && ElementPtr->turn_wait == 0) { if (NORMALIZE_FACING ( StarShipPtr->ShipFacing - facing ) >= ANGLE_TO_FACING (HALF_CIRCLE)) { facing = NORMALIZE_FACING (facing - 1); StarShipPtr->cur_status_flags |= RIGHT; } else if ((int)StarShipPtr->ShipFacing != (int)facing) { facing = NORMALIZE_FACING (facing + 1); StarShipPtr->cur_status_flags |= LEFT; } if ((int)facing == (int)StarShipPtr->ShipFacing) { ZeroVelocityComponents (&ElementPtr->velocity); } } GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); if ((GLOBAL_SIS (FuelOnBoard) || GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1) && (int)facing == (int)StarShipPtr->ShipFacing) { StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; AccelerateDirection = 1; } else { AccelerateDirection = -1; udx = dx << 4; udy = dy << 4; } } if (ElementPtr->thrust_wait == 0 && AccelerateDirection) { COUNT dist; SIZE speed, velocity_increment; velocity_increment = WORLD_TO_VELOCITY ( StarShipPtr->RaceDescPtr->characteristics.thrust_increment); if ((dist = square_root ((long)udx * udx + (long)udy * udy)) == 0) dist = 1; /* prevent divide by zero */ speed = square_root ((long)dx * dx + (long)dy * dy); if (AccelerateDirection < 0) { dy = (speed / velocity_increment - 1) * velocity_increment; if (dy < speed - velocity_increment) dy = speed - velocity_increment; if ((speed = dy) < 0) speed = 0; StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; } else { SIZE max_velocity; AccelerateDirection = 0; max_velocity = WORLD_TO_VELOCITY ( StarShipPtr->RaceDescPtr->characteristics.max_thrust); dy = (speed / velocity_increment + 1) * velocity_increment; if (dy < speed + velocity_increment) dy = speed + velocity_increment; if ((speed = dy) > max_velocity) { speed = max_velocity; StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; } } dx = (SIZE)((long)udx * speed / (long)dist); dy = (SIZE)((long)udy * speed / (long)dist); SetVelocityComponents (&ElementPtr->velocity, dx, dy); ElementPtr->thrust_wait = StarShipPtr->RaceDescPtr->characteristics.thrust_wait; } } static void sis_hyper_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GLOBAL (velocity) = ElementPtr->velocity; GetElementStarShip (ElementPtr, &StarShipPtr); if (((StarShipPtr->cur_status_flags & WEAPON) || PulsedInputState.menu[KEY_MENU_CANCEL]) && StarShipPtr->special_counter == 0) { #define MENU_DELAY 10 DoMenuOptions (); StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; StarShipPtr->special_counter = MENU_DELAY; } } static void spawn_point_defense (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (ElementPtr->state_flags & PLAYER_SHIP) { HELEMENT hDefense; hDefense = AllocElement (); if (hDefense) { ELEMENTPTR DefensePtr; LockElement (hDefense, &DefensePtr); DefensePtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); { DefensePtr->death_func = spawn_point_defense; } GetElementStarShip (ElementPtr, &StarShipPtr); SetElementStarShip (DefensePtr, StarShipPtr); UnlockElement (hDefense); PutElement (hDefense); } } else { BOOLEAN PaidFor; HELEMENT hObject, hNextObject; ELEMENTPTR ShipPtr; COLOR LaserColor; static const COLOR ColorRange[] = { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7F), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7E), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7D), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7C), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x18, 0x00), 0x79), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78), }; PaidFor = FALSE; LaserColor = ColorRange[ StarShipPtr->RaceDescPtr->characteristics.special_energy_cost ]; LockElement (StarShipPtr->hShip, &ShipPtr); for (hObject = GetTailElement (); hObject; hObject = hNextObject) { ELEMENTPTR ObjectPtr; LockElement (hObject, &ObjectPtr); hNextObject = GetPredElement (ObjectPtr); if (ObjectPtr != ShipPtr && CollidingElement (ObjectPtr) && !OBJECT_CLOAKED (ObjectPtr)) { #define LASER_RANGE (UWORD)100 SIZE delta_x, delta_y; delta_x = ObjectPtr->next.location.x - ShipPtr->next.location.x; delta_y = ObjectPtr->next.location.y - ShipPtr->next.location.y; if (delta_x < 0) delta_x = -delta_x; if (delta_y < 0) delta_y = -delta_y; delta_x = WORLD_TO_DISPLAY (delta_x); delta_y = WORLD_TO_DISPLAY (delta_y); if ((UWORD)delta_x <= LASER_RANGE && (UWORD)delta_y <= LASER_RANGE && (UWORD)delta_x * (UWORD)delta_x + (UWORD)delta_y * (UWORD)delta_y <= LASER_RANGE * LASER_RANGE) { HELEMENT hPointDefense; LASER_BLOCK LaserBlock; if (!PaidFor) { if (!DeltaEnergy (ShipPtr, -(StarShipPtr->RaceDescPtr->characteristics.special_energy_cost << 2))) break; ProcessSound (SetAbsSoundIndex ( /* POINT_DEFENSE_LASER */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; PaidFor = TRUE; } LaserBlock.cx = ShipPtr->next.location.x; LaserBlock.cy = ShipPtr->next.location.y; LaserBlock.face = 0; LaserBlock.ex = ObjectPtr->next.location.x - ShipPtr->next.location.x; LaserBlock.ey = ObjectPtr->next.location.y - ShipPtr->next.location.y; LaserBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; LaserBlock.pixoffs = 0; LaserBlock.color = LaserColor; hPointDefense = initialize_laser (&LaserBlock); if (hPointDefense) { ELEMENTPTR PDPtr; LockElement (hPointDefense, &PDPtr); PDPtr->mass_points = StarShipPtr->RaceDescPtr->characteristics.special_energy_cost; SetElementStarShip (PDPtr, StarShipPtr); PDPtr->hTarget = 0; UnlockElement (hPointDefense); PutElement (hPointDefense); } } } UnlockElement (hObject); } UnlockElement (StarShipPtr->hShip); } } static void sis_battle_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->RaceDescPtr->characteristics.special_energy_cost == 0) { StarShipPtr->cur_status_flags &= ~SPECIAL; StarShipPtr->special_counter = 2; } if (!(StarShipPtr->RaceDescPtr->ship_info.ship_flags & (FIRES_FORE | FIRES_RIGHT | FIRES_AFT | FIRES_LEFT))) { StarShipPtr->cur_status_flags &= ~WEAPON; StarShipPtr->weapon_counter = 2; } } static void sis_battle_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && StarShipPtr->RaceDescPtr->characteristics.special_energy_cost) { spawn_point_defense (ElementPtr); } } #define BLASTER_DAMAGE 2 static void blaster_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { HELEMENT hBlastElement; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if (hBlastElement) { ELEMENTPTR BlastElementPtr; LockElement (hBlastElement, &BlastElementPtr); switch (ElementPtr0->mass_points) { case BLASTER_DAMAGE * 1: BlastElementPtr->life_span = 2; BlastElementPtr->current.image.frame = SetAbsFrameIndex (ElementPtr0->current.image.frame, 0); BlastElementPtr->preprocess_func = NULL_PTR; break; case BLASTER_DAMAGE * 2: BlastElementPtr->life_span = 6; BlastElementPtr->current.image.frame = IncFrameIndex (ElementPtr0->current.image.frame); break; case BLASTER_DAMAGE * 3: BlastElementPtr->life_span = 7; BlastElementPtr->current.image.frame = SetAbsFrameIndex (ElementPtr0->current.image.frame, 20); break; } UnlockElement (hBlastElement); } } static void blaster_preprocess (PELEMENT ElementPtr) { BYTE wait; switch (ElementPtr->mass_points) { case BLASTER_DAMAGE * 1: if (GetFrameIndex (ElementPtr->current.image.frame) < 8) { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; } break; case BLASTER_DAMAGE * 3: if (GetFrameIndex (ElementPtr->current.image.frame) < 19) ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); else ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, 16); ElementPtr->state_flags |= CHANGING; break; } if (LONIBBLE (ElementPtr->turn_wait)) --ElementPtr->turn_wait; else if ((wait = HINIBBLE (ElementPtr->turn_wait))) { COUNT facing; facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity))); if (TrackShip (ElementPtr, &facing) > 0) SetVelocityVector (&ElementPtr->velocity, BLASTER_SPEED, facing); ElementPtr->turn_wait = MAKE_BYTE (wait, wait); } } static COUNT initialize_blasters (PELEMENT ShipPtr, HELEMENT BlasterArray[]) { #define SIS_VERT_OFFSET 28 #define SIS_HORZ_OFFSET 20 #define BLASTER_HITS 2 #define BLASTER_OFFSET 8 COUNT num_blasters; BYTE nt; COUNT i; STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock[6]; PMISSILE_BLOCK lpMB; GetElementStarShip (ShipPtr, &StarShipPtr); num_blasters = 0; for (i = 0, lpMB = &MissileBlock[0]; i < NUM_MODULE_SLOTS; ++i) { BYTE which_gun; if (i == 3) i = NUM_MODULE_SLOTS - 1; which_gun = GLOBAL_SIS (ModuleSlots[(NUM_MODULE_SLOTS - 1) - i]); if (which_gun >= GUN_WEAPON && which_gun <= CANNON_WEAPON) { which_gun -= GUN_WEAPON - 1; lpMB->cx = ShipPtr->next.location.x; lpMB->cy = ShipPtr->next.location.y; lpMB->farray = StarShipPtr->RaceDescPtr->ship_data.weapon; lpMB->sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; lpMB->blast_offs = BLASTER_OFFSET; lpMB->speed = BLASTER_SPEED; lpMB->preprocess_func = blaster_preprocess; lpMB->hit_points = BLASTER_HITS * which_gun; lpMB->damage = BLASTER_DAMAGE * which_gun; lpMB->life = BLASTER_LIFE + ((BLASTER_LIFE >> 2) * (which_gun - 1)); if (which_gun == 1) lpMB->index = 0; else if (which_gun == 2) lpMB->index = 9; else lpMB->index = 16; switch (i) { case 0: /* NOSE WEAPON */ lpMB->pixoffs = SIS_VERT_OFFSET; lpMB->face = StarShipPtr->ShipFacing; break; case 1: /* SPREAD WEAPON */ lpMB->pixoffs = SIS_VERT_OFFSET; lpMB->face = NORMALIZE_FACING ( StarShipPtr->ShipFacing + 1); lpMB[1] = lpMB[0]; ++lpMB; lpMB->face = NORMALIZE_FACING ( StarShipPtr->ShipFacing - 1); break; case 2: /* SIDE WEAPON */ lpMB->pixoffs = SIS_HORZ_OFFSET; lpMB->face = NORMALIZE_FACING ( StarShipPtr->ShipFacing + ANGLE_TO_FACING (QUADRANT)); lpMB[1] = lpMB[0]; ++lpMB; lpMB->face = NORMALIZE_FACING ( StarShipPtr->ShipFacing - ANGLE_TO_FACING (QUADRANT)); break; case NUM_MODULE_SLOTS - 1: /* TAIL WEAPON */ lpMB->pixoffs = SIS_VERT_OFFSET; lpMB->face = NORMALIZE_FACING ( StarShipPtr->ShipFacing + ANGLE_TO_FACING (HALF_CIRCLE)); break; } ++lpMB; } } nt = (BYTE)((4 - num_trackers) & 3); num_blasters = lpMB - &MissileBlock[0]; for (i = 0, lpMB = &MissileBlock[0]; i < num_blasters; ++i, ++lpMB) { if ((BlasterArray[i] = initialize_missile (lpMB))) { ELEMENTPTR BlasterPtr; LockElement (BlasterArray[i], &BlasterPtr); BlasterPtr->collision_func = blaster_collision; BlasterPtr->turn_wait = MAKE_BYTE (nt, nt); UnlockElement (BlasterArray[i]); } } return (num_blasters); } static void sis_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { PEVALUATE_DESC lpEvalDesc; STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (lpEvalDesc->ObjectPtr) { if (StarShipPtr->RaceDescPtr->characteristics.special_energy_cost) { if (StarShipPtr->special_counter == 0 && ((lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 2) || (ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr != NULL_PTR && ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn <= 4))) StarShipPtr->ship_input_state |= SPECIAL; else StarShipPtr->ship_input_state &= ~SPECIAL; lpEvalDesc->ObjectPtr = NULL_PTR; } else if (MANEUVERABILITY (&StarShipPtr->RaceDescPtr->cyborg_control) < MEDIUM_SHIP && lpEvalDesc->MoveState == ENTICE && (!(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT) || lpEvalDesc->which_turn <= 8) && (!(lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) || (lpEvalDesc->ObjectPtr->mass_points >= 4 && lpEvalDesc->which_turn == 2 && ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn > 16))) lpEvalDesc->MoveState = PURSUE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (num_trackers && StarShipPtr->weapon_counter == 0 && !(StarShipPtr->ship_input_state & WEAPON) && lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 16) { COUNT direction_facing; SIZE delta_x, delta_y; UWORD fire_flags, ship_flags; COUNT facing; delta_x = lpEvalDesc->ObjectPtr->current.location.x - ShipPtr->current.location.x; delta_y = lpEvalDesc->ObjectPtr->current.location.y - ShipPtr->current.location.y; direction_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y))); ship_flags = StarShipPtr->RaceDescPtr->ship_info.ship_flags; for (fire_flags = FIRES_FORE, facing = StarShipPtr->ShipFacing; fire_flags <= FIRES_LEFT; fire_flags <<= 1, facing += QUADRANT) { if ((ship_flags & fire_flags) && NORMALIZE_FACING ( direction_facing - facing + ANGLE_TO_FACING (OCTANT) ) <= ANGLE_TO_FACING (QUADRANT)) { StarShipPtr->ship_input_state |= WEAPON; break; } } } } static void InitModuleSlots (RACE_DESCPTR RaceDescPtr, const BYTE *ModuleSlots) { COUNT i; RaceDescPtr->ship_info.max_crew = 0; num_trackers = 0; for (i = 0; i < NUM_MODULE_SLOTS; ++i) { BYTE which_mod; which_mod = ModuleSlots[(NUM_MODULE_SLOTS - 1) - i]; switch (which_mod) { case CREW_POD: RaceDescPtr->ship_info.max_crew += CREW_POD_CAPACITY; break; case GUN_WEAPON: case BLASTER_WEAPON: case CANNON_WEAPON: RaceDescPtr->characteristics.weapon_energy_cost += (which_mod - GUN_WEAPON + 1) * 2; if (i <= 1) RaceDescPtr->ship_info.ship_flags |= FIRES_FORE; else if (i == 2) RaceDescPtr->ship_info.ship_flags |= FIRES_LEFT | FIRES_RIGHT; else RaceDescPtr->ship_info.ship_flags |= FIRES_AFT; break; case TRACKING_SYSTEM: ++num_trackers; break; case ANTIMISSILE_DEFENSE: ++RaceDescPtr->characteristics.special_energy_cost; break; case SHIVA_FURNACE: ++RaceDescPtr->characteristics.energy_regeneration; break; case DYNAMO_UNIT: RaceDescPtr->characteristics.energy_wait -= 2; if (RaceDescPtr->characteristics.energy_wait < 4) RaceDescPtr->characteristics.energy_wait = 4; break; } } if (num_trackers > MAX_TRACKING) num_trackers = MAX_TRACKING; RaceDescPtr->characteristics.weapon_energy_cost += num_trackers * 3; if (RaceDescPtr->characteristics.special_energy_cost) { RaceDescPtr->ship_info.ship_flags |= POINT_DEFENSE; if (RaceDescPtr->characteristics.special_energy_cost > MAX_DEFENSE) RaceDescPtr->characteristics.special_energy_cost = MAX_DEFENSE; } } static void InitDriveSlots (RACE_DESCPTR RaceDescPtr, const BYTE *DriveSlots) { COUNT i; // NB. RaceDescPtr->characteristics.max_thrust is already initialised. RaceDescPtr->characteristics.thrust_wait = 0; for (i = 0; i < NUM_DRIVE_SLOTS; ++i) { switch (DriveSlots[i]) { case FUSION_THRUSTER: RaceDescPtr->characteristics.max_thrust += 2; ++RaceDescPtr->characteristics.thrust_wait; break; } } RaceDescPtr->characteristics.thrust_wait = (BYTE)( THRUST_WAIT - (RaceDescPtr->characteristics.thrust_wait >> 1)); RaceDescPtr->characteristics.max_thrust = ((RaceDescPtr->characteristics.max_thrust / RaceDescPtr->characteristics.thrust_increment) + 1) * RaceDescPtr->characteristics.thrust_increment; } static void InitJetSlots (RACE_DESCPTR RaceDescPtr, const BYTE *JetSlots) { COUNT i; for (i = 0; i < NUM_JET_SLOTS; ++i) { switch (JetSlots[i]) { case TURNING_JETS: RaceDescPtr->characteristics.turn_wait -= 2; break; } } } RACE_DESCPTR init_sis (void) { RACE_DESCPTR RaceDescPtr; COUNT i; static RACE_DESC new_sis_desc; /* copy initial ship settings to new_sis_desc */ new_sis_desc = sis_desc; new_sis_desc.uninit_func = uninit_sis; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { for (i = 0; i < NUM_VIEWS; ++i) { new_sis_desc.ship_data.ship[i] = 0; new_sis_desc.ship_data.weapon[i] = 0; new_sis_desc.ship_data.special[i] = 0; } new_sis_desc.ship_info.icons = 0; new_sis_desc.ship_data.captain_control.background = 0; new_sis_desc.ship_data.victory_ditty = 0; new_sis_desc.ship_data.ship_sounds = 0; new_sis_desc.ship_data.ship[0] = (FRAME)SIS_HYPER_MASK_PMAP_ANIM; new_sis_desc.preprocess_func = sis_hyper_preprocess; new_sis_desc.postprocess_func = sis_hyper_postprocess; new_sis_desc.characteristics.max_thrust -= 4; } else { new_sis_desc.preprocess_func = sis_battle_preprocess; new_sis_desc.postprocess_func = sis_battle_postprocess; new_sis_desc.init_weapon_func = initialize_blasters; new_sis_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) sis_intelligence; if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 3) SET_GAME_STATE (BOMB_CARRIER, 1); } InitModuleSlots(&new_sis_desc, GLOBAL_SIS (ModuleSlots)); InitDriveSlots(&new_sis_desc, GLOBAL_SIS (DriveSlots)); InitJetSlots(&new_sis_desc, GLOBAL_SIS (JetSlots)); if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE) { new_sis_desc.ship_info.crew_level = new_sis_desc.ship_info.max_crew; } else { // Count the captain too. new_sis_desc.ship_info.max_crew++; new_sis_desc.ship_info.crew_level = GLOBAL_SIS (CrewEnlisted) + 1; new_sis_desc.ship_info.ship_flags |= PLAYER_CAPTAIN; } new_sis_desc.ship_info.energy_level = new_sis_desc.ship_info.max_energy; RaceDescPtr = &new_sis_desc; return (RaceDescPtr); } void uninit_sis (RACE_DESCPTR pRaceDesc) { if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) { GLOBAL_SIS (CrewEnlisted) = pRaceDesc->ship_info.crew_level; if (pRaceDesc->ship_info.ship_flags & PLAYER_CAPTAIN) GLOBAL_SIS (CrewEnlisted)--; } } uqm-0.6.2/sc2/src/sc2code/ships/sis_ship/Makeinfo0000600000175000017500000000003010543202057020221 0ustar joeyjoeyuqm_CFILES="sis_ship.c" uqm-0.6.2/sc2/src/sc2code/ships/sis_ship/respkg.h0000600000175000017500000000011210543202057020212 0ustar joeyjoeyenum { SIS_CODE_PACKAGE = 1, SIS_BATTLE_PACKAGE, SIS_HYPER_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/sis_ship/resinst.h0000600000175000017500000000012310543202060020402 0ustar joeyjoey#include "igfxres.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/orz/0000755000175000017500000000000010552600274015560 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/orz/restypes.h0000600000175000017500000000024110543202073017567 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/orz/igfxres.h0000600000175000017500000000104510543202073017363 0ustar joeyjoey#define ORZ_ICON_MASK_PMAP_ANIM 0x00200002L #define ORZ_MICON_MASK_PMAP_ANIM 0x00200102L #define ORZ_BIG_MASK_PMAP_ANIM 0x00400202L #define ORZ_MED_MASK_PMAP_ANIM 0x00400302L #define ORZ_SML_MASK_PMAP_ANIM 0x00400402L #define HOWITZER_BIG_MASK_PMAP_ANIM 0x00400502L #define HOWITZER_MED_MASK_PMAP_ANIM 0x00400602L #define HOWITZER_SML_MASK_PMAP_ANIM 0x00400702L #define TURRET_BIG_MASK_PMAP_ANIM 0x00400802L #define TURRET_MED_MASK_PMAP_ANIM 0x00400902L #define TURRET_SML_MASK_PMAP_ANIM 0x00400a02L #define ORZ_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/orz/isndres.h0000600000175000017500000000004610543202073017363 0ustar joeyjoey#define ORZ_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/orz/istrtab.h0000600000175000017500000000004710543202073017365 0ustar joeyjoey#define ORZ_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/orz/imusicre.h0000600000175000017500000000004710543202073017535 0ustar joeyjoey#define ORZ_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/orz/icode.h0000600000175000017500000000003710543202073016777 0ustar joeyjoey#define ORZ_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/orz/orz.res0000600000175000017500000000143010543202072017065 0ustar joeyjoeyINCLUDE ../star3do.typ PATH orz PACKAGE ORZ_CODE_PACKAGE orz.shp CODE ORZ_CODE orz.cod GFXRES ORZ_ICON_MASK_PMAP_ANIM orzicons.ani GFXRES ORZ_MICON_MASK_PMAP_ANIM orzmicon.ani STRTAB ORZ_RACE_STRINGS orztext.txt PACKAGE ORZ_PACKAGE orz.shp GFXRES ORZ_BIG_MASK_PMAP_ANIM orz.big GFXRES ORZ_MED_MASK_PMAP_ANIM orz.med GFXRES ORZ_SML_MASK_PMAP_ANIM orz.sml GFXRES HOWITZER_BIG_MASK_PMAP_ANIM howbig.ani GFXRES HOWITZER_MED_MASK_PMAP_ANIM howmed.ani GFXRES HOWITZER_SML_MASK_PMAP_ANIM howsml.ani GFXRES TURRET_BIG_MASK_PMAP_ANIM turbig.ani GFXRES TURRET_MED_MASK_PMAP_ANIM turmed.ani GFXRES TURRET_SML_MASK_PMAP_ANIM tursml.ani GFXRES ORZ_CAPTAIN_MASK_PMAP_ANIM orzcap.ani SNDRES ORZ_SHIP_SOUNDS orzsound.snd MUSICRES ORZ_VICTORY_SONG orzditty.mod uqm-0.6.2/sc2/src/sc2code/ships/orz/Makeinfo0000600000175000017500000000002310543202073017212 0ustar joeyjoeyuqm_CFILES="orz.c" uqm-0.6.2/sc2/src/sc2code/ships/orz/orz.c0000644000175000017500000007374310546776503016570 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/orz/resinst.h" #include "colors.h" #include "globdata.h" #include "libs/mathlib.h" #define MAX_CREW 16 #define MAX_ENERGY 20 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST (MAX_ENERGY / 3) #define SPECIAL_ENERGY_COST 0 #define ENERGY_WAIT 6 #define MAX_THRUST 35 #define THRUST_INCREMENT 5 #define TURN_WAIT 1 #define THRUST_WAIT 0 #define WEAPON_WAIT 4 #define SPECIAL_WAIT 12 #define SHIP_MASS 4 #define ORZ_OFFSET 9 #define MISSILE_SPEED DISPLAY_TO_WORLD (30) #define MISSILE_LIFE 12 static RACE_DESC orz_desc = { { FIRES_FORE | SEEKING_SPECIAL, 23, /* Super Melee cost */ 333 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 3608, 2637, }, (STRING)ORZ_RACE_STRINGS, (FRAME)ORZ_ICON_MASK_PMAP_ANIM, (FRAME)ORZ_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)ORZ_BIG_MASK_PMAP_ANIM, (FRAME)ORZ_MED_MASK_PMAP_ANIM, (FRAME)ORZ_SML_MASK_PMAP_ANIM, }, { (FRAME)HOWITZER_BIG_MASK_PMAP_ANIM, (FRAME)HOWITZER_MED_MASK_PMAP_ANIM, (FRAME)HOWITZER_SML_MASK_PMAP_ANIM, }, { (FRAME)TURRET_BIG_MASK_PMAP_ANIM, (FRAME)TURRET_MED_MASK_PMAP_ANIM, (FRAME)TURRET_SML_MASK_PMAP_ANIM, }, { (FRAME)ORZ_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)ORZ_VICTORY_SONG, (SOUND)ORZ_SHIP_SOUNDS, }, { 0, MISSILE_SPEED * MISSILE_LIFE, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static void howitzer_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if ((ElementPtr0->state_flags & (GOOD_GUY | BAD_GUY)) != (ElementPtr1->state_flags & (GOOD_GUY | BAD_GUY))) weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); } #define TURRET_OFFSET 14 #define TURRET_WAIT 3 static COUNT initialize_turret_missile (PELEMENT ShipPtr, HELEMENT MissileArray[]) { #define MISSILE_HITS 2 #define MISSILE_DAMAGE 3 #define MISSILE_OFFSET 1 ELEMENTPTR TurretPtr; STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; LockElement (GetSuccElement (ShipPtr), &TurretPtr); if (TurretPtr->turn_wait == 0 && (StarShipPtr->cur_status_flags & SPECIAL) && (StarShipPtr->cur_status_flags & (LEFT | RIGHT))) { if (StarShipPtr->cur_status_flags & RIGHT) ++TurretPtr->thrust_wait; else --TurretPtr->thrust_wait; TurretPtr->turn_wait = TURRET_WAIT + 1; } MissileBlock.face = MissileBlock.index = NORMALIZE_FACING (StarShipPtr->ShipFacing + TurretPtr->thrust_wait); UnlockElement (GetSuccElement (ShipPtr)); MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = TURRET_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; MissileArray[0] = initialize_missile (&MissileBlock); if (MissileArray[0]) { ELEMENTPTR HowitzerPtr; LockElement (MissileArray[0], &HowitzerPtr); HowitzerPtr->collision_func = howitzer_collision; UnlockElement (MissileArray[0]); } return (1); } #define MAX_MARINES 8 static BYTE count_marines (STARSHIPPTR StarShipPtr, BOOLEAN FindSpot) { BYTE num_marines, id_use[MAX_MARINES]; HELEMENT hElement, hNextElement; num_marines = MAX_MARINES; while (num_marines--) id_use[num_marines] = 0; num_marines = 0; for (hElement = GetTailElement (); hElement; hElement = hNextElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); hNextElement = GetPredElement (ElementPtr); if (ElementPtr->current.image.farray == StarShipPtr->RaceDescPtr->ship_data.special && ElementPtr->life_span && !(ElementPtr->state_flags & (FINITE_LIFE | DISAPPEARING))) { if (ElementPtr->state_flags & NONSOLID) { id_use[ElementPtr->turn_wait] = 1; } if (++num_marines == MAX_MARINES) { UnlockElement (hElement); hNextElement = 0; } } UnlockElement (hElement); } if (FindSpot) { num_marines = 0; while (id_use[num_marines]) ++num_marines; } return (num_marines); } static void orz_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { ELEMENTPTR TurretPtr; STARSHIPPTR StarShipPtr; PEVALUATE_DESC lpEvalDesc; LockElement (GetSuccElement (ShipPtr), &TurretPtr); ++TurretPtr->turn_wait; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); --TurretPtr->turn_wait; GetElementStarShip (ShipPtr, &StarShipPtr); lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr == 0) StarShipPtr->ship_input_state &= ~SPECIAL; else if (StarShipPtr->special_counter != 1) { STARSHIPPTR EnemyStarShipPtr; if (ShipPtr->turn_wait == 0 && lpEvalDesc->MoveState == ENTICE && lpEvalDesc->which_turn < 24 && (StarShipPtr->cur_status_flags & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) && !(StarShipPtr->ship_input_state & THRUST) && NORMALIZE_ANGLE ( GetVelocityTravelAngle (&ShipPtr->velocity) - ARCTAN ( lpEvalDesc->ObjectPtr->next.location.x - ShipPtr->next.location.x, lpEvalDesc->ObjectPtr->next.location.y - ShipPtr->next.location.y ) + (QUADRANT - (OCTANT >> 1))) >= ((QUADRANT - (OCTANT >> 1)) << 1)) StarShipPtr->ship_input_state &= ~(LEFT | RIGHT); StarShipPtr->ship_input_state &= ~SPECIAL; if (ShipPtr->turn_wait == 0 && !(StarShipPtr->ship_input_state & (LEFT | RIGHT | WEAPON)) && TurretPtr->turn_wait == 0) { SIZE delta_facing; COUNT facing;//, orig_facing; facing = NORMALIZE_FACING (StarShipPtr->ShipFacing + TurretPtr->thrust_wait); if ((delta_facing = TrackShip (TurretPtr, &facing)) > 0) { StarShipPtr->ship_input_state |= SPECIAL; if (delta_facing == ANGLE_TO_FACING (HALF_CIRCLE)) delta_facing += (((BYTE)TFB_Random () & 1) << 1) - 1; if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) StarShipPtr->ship_input_state |= RIGHT; else StarShipPtr->ship_input_state |= LEFT; } } GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if (StarShipPtr->special_counter == 0 && !(StarShipPtr->ship_input_state & WEAPON) && StarShipPtr->RaceDescPtr->ship_info.crew_level > (BYTE)(StarShipPtr->RaceDescPtr->ship_info.max_crew >> 2) && !(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & POINT_DEFENSE) && (MANEUVERABILITY ( &EnemyStarShipPtr->RaceDescPtr->cyborg_control ) < SLOW_SHIP || lpEvalDesc->which_turn <= 12 || count_marines (StarShipPtr, FALSE) < 2)) { StarShipPtr->ship_input_state |= WEAPON | SPECIAL; } } UnlockElement (GetSuccElement (ShipPtr)); } #define START_ION_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A) void ion_preprocess (PELEMENT ElementPtr) { static const COLOR color_tab[] = { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x2a), BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2b), BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2c), BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2d), BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2e), BUILD_COLOR (MAKE_RGB15 (0x0B, 0x00, 0x00), 0x2f), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7a), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7b), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7c), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7d), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7e), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7f), }; #define NUM_TAB_COLORS (sizeof (color_tab) / sizeof (color_tab[0])) COUNT color_index = 0; COLOR Color; Color = COLOR_256 (GetPrimColor (&(GLOBAL (DisplayArray))[ ElementPtr->PrimIndex])); if (Color != 0x2D) { ElementPtr->life_span = ElementPtr->thrust_wait; Color += 2; if (Color > 0x7F) Color = 0x2B; else if (Color == 0x7E) Color = 0x7F; if (Color <= 0x2f && Color >= 0x2a) color_index = (COUNT)Color - 0x2a; else /* color is between 0x7a and 0x7f */ color_index = (COUNT)(Color - 0x7a) + (NUM_TAB_COLORS >> 1); SetPrimColor (&(GLOBAL (DisplayArray))[ ElementPtr->PrimIndex], color_tab[color_index]); ElementPtr->state_flags &= ~DISAPPEARING; ElementPtr->state_flags |= CHANGING; } } static void marine_preprocess (PELEMENT ElementPtr); #define MARINE_WAIT 12 void intruder_preprocess (PELEMENT ElementPtr) { HELEMENT hElement, hNextElement; ELEMENTPTR ShipPtr; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ShipPtr); if (ShipPtr->crew_level == 0 && ShipPtr->life_span == 1 && (ShipPtr->state_flags & (FINITE_LIFE | NONSOLID)) == (FINITE_LIFE | NONSOLID)) { ElementPtr->life_span = 0; ElementPtr->state_flags |= DISAPPEARING; } UnlockElement (StarShipPtr->hShip); if (ElementPtr->thrust_wait) --ElementPtr->thrust_wait; for (hElement = GetHeadElement (); hElement; hElement = hNextElement) { LockElement (hElement, &ShipPtr); if ((ShipPtr->state_flags & PLAYER_SHIP) && (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) != (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY))) { STAMP s; if (ElementPtr->thrust_wait == MARINE_WAIT) { --ElementPtr->thrust_wait; s.origin.x = 16 + (ElementPtr->turn_wait & 3) * 9; s.origin.y = 14 + (ElementPtr->turn_wait >> 2) * 11; s.frame = SetAbsFrameIndex (ElementPtr->next.image.farray[0], GetFrameCount (ElementPtr->next.image.farray[0]) - 2); ModifySilhouette (ShipPtr, &s, 0); } ElementPtr->next.location = ShipPtr->next.location; if (ShipPtr->crew_level == 0 || ElementPtr->life_span == 0) { UnlockElement (hElement); hElement = 0; LeftShip: s.origin.x = 16 + (ElementPtr->turn_wait & 3) * 9; s.origin.y = 14 + (ElementPtr->turn_wait >> 2) * 11; s.frame = ElementPtr->next.image.frame; ModifySilhouette (ShipPtr, &s, MODIFY_SWAP); } else if (ElementPtr->thrust_wait == 0) { BYTE randval; ElementPtr->thrust_wait = MARINE_WAIT; randval = (BYTE)TFB_Random (); if (randval < (0x0100 / 16)) { ElementPtr->life_span = 0; ElementPtr->state_flags |= DISAPPEARING; ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 4), ElementPtr); goto LeftShip; } else if (randval < (0x0100 / 2 + 0x0100 / 16)) { if (!DeltaCrew (ShipPtr, -1)) ShipPtr->life_span = 0; ++ElementPtr->thrust_wait; s.origin.x = 16 + (ElementPtr->turn_wait & 3) * 9; s.origin.y = 14 + (ElementPtr->turn_wait >> 2) * 11; s.frame = SetAbsFrameIndex (ElementPtr->next.image.farray[0], GetFrameCount (ElementPtr->next.image.farray[0]) - 1); ModifySilhouette (ShipPtr, &s, 0); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3), ElementPtr); } } UnlockElement (hElement); break; } hNextElement = GetSuccElement (ShipPtr); UnlockElement (hElement); } if (hElement == 0 && ElementPtr->life_span) { ElementPtr->state_flags &= ~NONSOLID; ElementPtr->state_flags |= CHANGING | CREW_OBJECT; SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], STAMP_PRIM); ElementPtr->current.image.frame = ElementPtr->next.image.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.special[0], 21); ElementPtr->thrust_wait = 0; ElementPtr->turn_wait = MAKE_BYTE (0, NORMALIZE_FACING ((BYTE)TFB_Random ())); ElementPtr->preprocess_func = marine_preprocess; } } static void marine_preprocess (ElementPtr) PELEMENT ElementPtr; { ELEMENTPTR ShipPtr; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ShipPtr); if (ShipPtr->crew_level == 0 && ShipPtr->life_span == 1 && (ShipPtr->state_flags & (FINITE_LIFE | NONSOLID)) == (FINITE_LIFE | NONSOLID)) { ElementPtr->life_span = 0; ElementPtr->state_flags |= DISAPPEARING | NONSOLID; ElementPtr->turn_wait = 1; } UnlockElement (StarShipPtr->hShip); if (LONIBBLE (ElementPtr->turn_wait)) --ElementPtr->turn_wait; else { COUNT facing, pfacing; SIZE delta_x, delta_y, delta_facing; HELEMENT hObject, hNextObject, hTarget; ELEMENTPTR ObjectPtr; ElementPtr->thrust_wait &= ~(SHIP_IN_GRAVITY_WELL >> 6); hTarget = 0; for (hObject = GetHeadElement (); hObject; hObject = hNextObject) { LockElement (hObject, &ObjectPtr); hNextObject = GetSuccElement (ObjectPtr); if (GRAVITY_MASS (ObjectPtr->mass_points)) { delta_x = ObjectPtr->current.location.x - ElementPtr->current.location.x; delta_x = WRAP_DELTA_X (delta_x); delta_y = ObjectPtr->current.location.y - ElementPtr->current.location.y; delta_y = WRAP_DELTA_Y (delta_y); if ((long)delta_x * delta_x + (long)delta_y * delta_y <= (long)(DISPLAY_TO_WORLD (GRAVITY_THRESHOLD) * DISPLAY_TO_WORLD (GRAVITY_THRESHOLD))) { pfacing = ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)); delta_facing = NORMALIZE_FACING ( pfacing - ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity)) + ANGLE_TO_FACING (OCTANT)); if (delta_facing <= ANGLE_TO_FACING (QUADRANT)) { hTarget = hObject; hNextObject = 0; } ElementPtr->thrust_wait |= (SHIP_IN_GRAVITY_WELL >> 6); } } else if ((ObjectPtr->state_flags & PLAYER_SHIP) && ObjectPtr->crew_level && !OBJECT_CLOAKED (ObjectPtr)) { if ((ObjectPtr->state_flags & (GOOD_GUY | BAD_GUY)) != (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY))) { if (ElementPtr->state_flags & IGNORE_SIMILAR) hTarget = hObject; } else if (hTarget == 0) hTarget = hObject; } UnlockElement (hObject); } facing = HINIBBLE (ElementPtr->turn_wait); if (hTarget == 0) delta_facing = -1; else { LockElement (hTarget, &ObjectPtr); delta_x = ObjectPtr->current.location.x - ElementPtr->current.location.x; delta_x = WRAP_DELTA_X (delta_x); delta_y = ObjectPtr->current.location.y - ElementPtr->current.location.y; delta_y = WRAP_DELTA_Y (delta_y); if (GRAVITY_MASS (ObjectPtr->mass_points)) { delta_facing = NORMALIZE_FACING (pfacing - facing + ANGLE_TO_FACING (OCTANT)); if (delta_facing > ANGLE_TO_FACING (QUADRANT)) delta_facing = 0; else { if (delta_facing == ANGLE_TO_FACING (OCTANT)) facing += (((SIZE)TFB_Random () & 1) << 1) - 1; else if (delta_facing < ANGLE_TO_FACING (OCTANT)) ++facing; else --facing; } } else { COUNT num_frames; VELOCITY_DESC ShipVelocity; if ((ObjectPtr->state_flags & (GOOD_GUY | BAD_GUY)) == (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) && (ElementPtr->state_flags & IGNORE_SIMILAR)) { ElementPtr->next.image.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.special[0], 21); ElementPtr->state_flags &= ~IGNORE_SIMILAR; ElementPtr->state_flags |= CHANGING; } num_frames = WORLD_TO_TURN ( square_root ((long)delta_x * delta_x + (long)delta_y * delta_y)); if (num_frames == 0) num_frames = 1; ShipVelocity = ObjectPtr->velocity; GetNextVelocityComponents (&ShipVelocity, &delta_x, &delta_y, num_frames); delta_x = (ObjectPtr->current.location.x + delta_x) - ElementPtr->current.location.x; delta_y = (ObjectPtr->current.location.y + delta_y) - ElementPtr->current.location.y; delta_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) - facing); if (delta_facing > 0) { if (delta_facing == ANGLE_TO_FACING (HALF_CIRCLE)) facing += (((BYTE)TFB_Random () & 1) << 1) - 1; else if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) ++facing; else --facing; } } UnlockElement (hTarget); } ElementPtr->turn_wait = MAKE_BYTE (0, NORMALIZE_FACING (facing)); if (delta_facing == 0 || ((ElementPtr->thrust_wait & (SHIP_BEYOND_MAX_SPEED >> 6)) && !(ElementPtr->thrust_wait & (SHIP_IN_GRAVITY_WELL >> 6)))) { UWORD thrust_status; COUNT OldFacing; UWORD OldStatus; COUNT OldIncrement, OldThrust; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); OldFacing = StarShipPtr->ShipFacing; OldStatus = StarShipPtr->cur_status_flags; OldIncrement = StarShipPtr->RaceDescPtr->characteristics. thrust_increment; OldThrust = StarShipPtr->RaceDescPtr->characteristics.max_thrust; StarShipPtr->ShipFacing = facing; StarShipPtr->cur_status_flags = ElementPtr->thrust_wait << 6; StarShipPtr->RaceDescPtr->characteristics.thrust_increment = 8; StarShipPtr->RaceDescPtr->characteristics.max_thrust = 32; thrust_status = inertial_thrust (ElementPtr); StarShipPtr->RaceDescPtr->characteristics.max_thrust = OldThrust; StarShipPtr->RaceDescPtr->characteristics.thrust_increment = OldIncrement; StarShipPtr->cur_status_flags = OldStatus; StarShipPtr->ShipFacing = OldFacing; if ((ElementPtr->thrust_wait & (SHIP_IN_GRAVITY_WELL >> 6)) || delta_facing || !(thrust_status & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED))) { HELEMENT hIonElement; hIonElement = AllocElement (); if (hIonElement) { #define ION_LIFE 1 COUNT angle; ELEMENTPTR IonElementPtr; angle = FACING_TO_ANGLE (facing) + HALF_CIRCLE; InsertElement (hIonElement, GetHeadElement ()); LockElement (hIonElement, &IonElementPtr); IonElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; IonElementPtr->life_span = IonElementPtr->thrust_wait = ION_LIFE; SetPrimType (&(GLOBAL (DisplayArray))[ IonElementPtr->PrimIndex], POINT_PRIM); SetPrimColor (&(GLOBAL (DisplayArray))[ IonElementPtr->PrimIndex], START_ION_COLOR); IonElementPtr->current.location = ElementPtr->current.location; IonElementPtr->current.location.x += (COORD)COSINE (angle, DISPLAY_TO_WORLD (2)); IonElementPtr->current.location.y += (COORD)SINE (angle, DISPLAY_TO_WORLD (2)); IonElementPtr->death_func = ion_preprocess; SetElementStarShip (IonElementPtr, StarShipPtr); { /* normally done during preprocess, but because * object is being inserted at head rather than * appended after tail it may never get preprocessed. */ IonElementPtr->next = IonElementPtr->current; --IonElementPtr->life_span; IonElementPtr->state_flags |= PRE_PROCESS; } UnlockElement (hIonElement); } } ElementPtr->thrust_wait = (BYTE)(thrust_status >> 6); } } } void marine_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if (ElementPtr0->life_span && !(ElementPtr0->state_flags & (NONSOLID | COLLISION)) && !(ElementPtr1->state_flags & FINITE_LIFE)) { if ((ElementPtr0->state_flags & (GOOD_GUY | BAD_GUY)) != (ElementPtr1->state_flags & (GOOD_GUY | BAD_GUY))) { ElementPtr0->turn_wait = MAKE_BYTE (5, HINIBBLE (ElementPtr0->turn_wait)); ElementPtr0->thrust_wait &= ~((SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED) >> 6); ElementPtr0->state_flags |= COLLISION; } if (GRAVITY_MASS (ElementPtr1->mass_points)) { ElementPtr0->state_flags |= NONSOLID | FINITE_LIFE; ElementPtr0->hit_points = 0; ElementPtr0->life_span = 0; } else if ((ElementPtr1->state_flags & PLAYER_SHIP) && ((ElementPtr1->state_flags & FINITE_LIFE) || ElementPtr1->life_span == NORMAL_LIFE)) { ElementPtr1->state_flags &= ~COLLISION; if (!(ElementPtr0->state_flags & COLLISION)) { DeltaCrew (ElementPtr1, 1); ElementPtr0->state_flags |= DISAPPEARING | NONSOLID | FINITE_LIFE; ElementPtr0->hit_points = 0; ElementPtr0->life_span = 0; } else if ((ElementPtr0->state_flags & IGNORE_SIMILAR) && ElementPtr1->crew_level #ifdef NEVER && (BYTE)TFB_Random () <= (0x0100 / 3) #endif /* NEVER */ ) { STAMP s; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr0, &StarShipPtr); if (!DeltaCrew (ElementPtr1, -1)) ElementPtr1->life_span = 0; else { ElementPtr0->turn_wait = count_marines (StarShipPtr, TRUE); ElementPtr0->thrust_wait = MARINE_WAIT; ElementPtr0->next.image.frame = SetAbsFrameIndex ( ElementPtr0->next.image.farray[0], 22 + ElementPtr0->turn_wait ); ElementPtr0->state_flags |= NONSOLID; ElementPtr0->state_flags &= ~CREW_OBJECT; SetPrimType (&(GLOBAL (DisplayArray))[ ElementPtr0->PrimIndex ], NO_PRIM); ElementPtr0->preprocess_func = intruder_preprocess; s.origin.x = 16 + (ElementPtr0->turn_wait & 3) * 9; s.origin.y = 14 + (ElementPtr0->turn_wait >> 2) * 11; s.frame = ElementPtr0->next.image.frame; ModifySilhouette (ElementPtr1, &s, 0); } ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), ElementPtr1); } ElementPtr0->state_flags &= ~COLLISION; } } (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } static void animate (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = ElementPtr->next_turn; } } static void turret_postprocess (PELEMENT ElementPtr) { if (ElementPtr->life_span == 0) { STARSHIPPTR StarShipPtr; SetPrimType (&(GLOBAL (DisplayArray))[ ElementPtr->PrimIndex], NO_PRIM); GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->hShip) { COUNT facing; HELEMENT hTurret, hSpaceMarine; ELEMENTPTR ShipPtr; LockElement (StarShipPtr->hShip, &ShipPtr); hTurret = AllocElement (); if (hTurret) { ELEMENTPTR TurretPtr; LockElement (hTurret, &TurretPtr); TurretPtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | CHANGING | PRE_PROCESS | POST_PROCESS | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); TurretPtr->life_span = 1; TurretPtr->current.image = ElementPtr->current.image; TurretPtr->current.location = ShipPtr->next.location; TurretPtr->turn_wait = ElementPtr->turn_wait; TurretPtr->thrust_wait = ElementPtr->thrust_wait; if (TurretPtr->turn_wait) --TurretPtr->turn_wait; else if ((StarShipPtr->cur_status_flags & SPECIAL) && (StarShipPtr->cur_status_flags & (LEFT | RIGHT))) { if (StarShipPtr->cur_status_flags & RIGHT) ++TurretPtr->thrust_wait; else --TurretPtr->thrust_wait; TurretPtr->turn_wait = TURRET_WAIT; } facing = NORMALIZE_FACING (StarShipPtr->ShipFacing + TurretPtr->thrust_wait); StarShipPtr->RaceDescPtr->ship_info.ship_flags &= ~(FIRES_FORE | FIRES_RIGHT | FIRES_AFT | FIRES_LEFT); StarShipPtr->RaceDescPtr->ship_info.ship_flags |= FIRES_FORE << (NORMALIZE_FACING (facing + ANGLE_TO_FACING (OCTANT)) / ANGLE_TO_FACING (QUADRANT)); TurretPtr->current.image.frame = SetAbsFrameIndex ( TurretPtr->current.image.frame, facing); facing = FACING_TO_ANGLE (facing); if (StarShipPtr->cur_status_flags & WEAPON) { HELEMENT hTurretEffect; ELEMENTPTR TurretEffectPtr; LockElement (GetTailElement (), &TurretEffectPtr); if ((PELEMENT)TurretEffectPtr != ElementPtr && (TurretEffectPtr->state_flags & (GOOD_GUY | BAD_GUY)) == (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) && (TurretEffectPtr->state_flags & APPEARING) && GetPrimType (&(GLOBAL (DisplayArray))[ TurretEffectPtr->PrimIndex ]) == STAMP_PRIM && (hTurretEffect = AllocElement ())) { TurretPtr->current.location.x -= COSINE (facing, DISPLAY_TO_WORLD (2)); TurretPtr->current.location.y -= SINE (facing, DISPLAY_TO_WORLD (2)); LockElement (hTurretEffect, &TurretEffectPtr); TurretEffectPtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | APPEARING | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); TurretEffectPtr->life_span = 4; TurretEffectPtr->current.location.x = TurretPtr->current.location.x + COSINE (facing, DISPLAY_TO_WORLD (TURRET_OFFSET)); TurretEffectPtr->current.location.y = TurretPtr->current.location.y + SINE (facing, DISPLAY_TO_WORLD (TURRET_OFFSET)); TurretEffectPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; TurretEffectPtr->current.image.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.special[0], ANGLE_TO_FACING (FULL_CIRCLE)); TurretEffectPtr->preprocess_func = animate; SetElementStarShip (TurretEffectPtr, StarShipPtr); SetPrimType (&(GLOBAL (DisplayArray))[ TurretEffectPtr->PrimIndex], STAMP_PRIM); UnlockElement (hTurretEffect); PutElement (hTurretEffect); } UnlockElement (GetTailElement ()); } TurretPtr->next = TurretPtr->current; SetPrimType (&(GLOBAL (DisplayArray))[ TurretPtr->PrimIndex], GetPrimType (&(GLOBAL (DisplayArray))[ ShipPtr->PrimIndex])); SetPrimColor (&(GLOBAL (DisplayArray))[ TurretPtr->PrimIndex], GetPrimColor (&(GLOBAL (DisplayArray))[ ShipPtr->PrimIndex])); TurretPtr->postprocess_func = ElementPtr->postprocess_func; SetElementStarShip (TurretPtr, StarShipPtr); UnlockElement (hTurret); InsertElement (hTurret, GetSuccElement (ElementPtr)); } if (StarShipPtr->special_counter == 0 && (StarShipPtr->cur_status_flags & SPECIAL) && (StarShipPtr->cur_status_flags & WEAPON) && ShipPtr->crew_level > 1 && count_marines (StarShipPtr, FALSE) < MAX_MARINES && TrackShip (ShipPtr, &facing) >= 0 && (hSpaceMarine = AllocElement ())) { ELEMENTPTR SpaceMarinePtr; LockElement (hSpaceMarine, &SpaceMarinePtr); SpaceMarinePtr->state_flags = IGNORE_SIMILAR | APPEARING | CREW_OBJECT | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); SpaceMarinePtr->life_span = NORMAL_LIFE; SpaceMarinePtr->hit_points = 3; SpaceMarinePtr->mass_points = 1; facing = FACING_TO_ANGLE (StarShipPtr->ShipFacing); SpaceMarinePtr->current.location.x = ShipPtr->current.location.x - COSINE (facing, DISPLAY_TO_WORLD (TURRET_OFFSET)); SpaceMarinePtr->current.location.y = ShipPtr->current.location.y - SINE (facing, DISPLAY_TO_WORLD (TURRET_OFFSET)); SpaceMarinePtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; SpaceMarinePtr->current.image.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.special[0], 20); SpaceMarinePtr->turn_wait = MAKE_BYTE (0, NORMALIZE_FACING ( ANGLE_TO_FACING (facing + HALF_CIRCLE))); SpaceMarinePtr->preprocess_func = marine_preprocess; SpaceMarinePtr->collision_func = marine_collision; SetElementStarShip (SpaceMarinePtr, StarShipPtr); SetPrimType (&(GLOBAL (DisplayArray))[ SpaceMarinePtr->PrimIndex], STAMP_PRIM); UnlockElement (hSpaceMarine); PutElement (hSpaceMarine); DeltaCrew (ShipPtr, -1); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), SpaceMarinePtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } UnlockElement (StarShipPtr->hShip); } } } static void orz_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (!(ElementPtr->state_flags & APPEARING)) { if (((StarShipPtr->cur_status_flags | StarShipPtr->old_status_flags) & SPECIAL) && (StarShipPtr->cur_status_flags & (LEFT | RIGHT)) && ElementPtr->turn_wait == 0) { ++ElementPtr->turn_wait; } if ((StarShipPtr->cur_status_flags & SPECIAL) && (StarShipPtr->cur_status_flags & WEAPON) && StarShipPtr->weapon_counter == 0) { ++StarShipPtr->weapon_counter; } } else { HELEMENT hTurret; hTurret = AllocElement (); if (hTurret) { ELEMENTPTR TurretPtr; LockElement (hTurret, &TurretPtr); TurretPtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); TurretPtr->life_span = 1; TurretPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; TurretPtr->current.image.frame = SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], StarShipPtr->ShipFacing); TurretPtr->postprocess_func = turret_postprocess; SetElementStarShip (TurretPtr, StarShipPtr); UnlockElement (hTurret); InsertElement (hTurret, GetSuccElement (ElementPtr)); } } } RACE_DESCPTR init_orz (void) { RACE_DESCPTR RaceDescPtr; orz_desc.preprocess_func = orz_preprocess; orz_desc.init_weapon_func = initialize_turret_missile; orz_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) orz_intelligence; RaceDescPtr = &orz_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/orz/respkg.h0000600000175000017500000000005710543202072017210 0ustar joeyjoeyenum { ORZ_CODE_PACKAGE = 1, ORZ_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/orz/resinst.h0000600000175000017500000000015010543202073017377 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/chmmr/0000755000175000017500000000000010552600274016054 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/chmmr/restypes.h0000600000175000017500000000024110543202070020060 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/chmmr/igfxres.h0000600000175000017500000000106410543202070017655 0ustar joeyjoey#define CHMMR_ICON_MASK_PMAP_ANIM 0x00200002L #define CHMMR_MICON_MASK_PMAP_ANIM 0x00200102L #define CHMMR_BIG_MASK_PMAP_ANIM 0x00400202L #define CHMMR_MED_MASK_PMAP_ANIM 0x00400302L #define CHMMR_SML_MASK_PMAP_ANIM 0x00400402L #define MUZZLE_BIG_MASK_PMAP_ANIM 0x00400502L #define MUZZLE_MED_MASK_PMAP_ANIM 0x00400602L #define MUZZLE_SML_MASK_PMAP_ANIM 0x00400702L #define SATELLITE_BIG_MASK_PMAP_ANIM 0x00400802L #define SATELLITE_MED_MASK_PMAP_ANIM 0x00400902L #define SATELLITE_SML_MASK_PMAP_ANIM 0x00400a02L #define CHMMR_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/chmmr/isndres.h0000600000175000017500000000005010543202070017647 0ustar joeyjoey#define CHMMR_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/chmmr/chmmr.c0000600000175000017500000005140710543202070017315 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/chmmr/resinst.h" #include "colors.h" #include "globdata.h" #include "libs/mathlib.h" #define MAX_CREW MAX_CREW_SIZE #define MAX_ENERGY MAX_ENERGY_SIZE #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 2 #define SPECIAL_ENERGY_COST 1 #define ENERGY_WAIT 1 #define MAX_THRUST 35 #define THRUST_INCREMENT 7 #define TURN_WAIT 3 #define THRUST_WAIT 5 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 0 #define SHIP_MASS 10 #define CHMMR_OFFSET 18 #define LASER_RANGE DISPLAY_TO_WORLD (150) static RACE_DESC chmmr_desc = { { FIRES_FORE | IMMEDIATE_WEAPON | SEEKING_SPECIAL | POINT_DEFENSE, 30, /* Super Melee cost */ 0, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 0, 0, }, (STRING)CHMMR_RACE_STRINGS, (FRAME)CHMMR_ICON_MASK_PMAP_ANIM, (FRAME)CHMMR_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)CHMMR_BIG_MASK_PMAP_ANIM, (FRAME)CHMMR_MED_MASK_PMAP_ANIM, (FRAME)CHMMR_SML_MASK_PMAP_ANIM, }, { (FRAME)MUZZLE_BIG_MASK_PMAP_ANIM, (FRAME)MUZZLE_MED_MASK_PMAP_ANIM, (FRAME)MUZZLE_SML_MASK_PMAP_ANIM, }, { (FRAME)SATELLITE_BIG_MASK_PMAP_ANIM, (FRAME)SATELLITE_MED_MASK_PMAP_ANIM, (FRAME)SATELLITE_SML_MASK_PMAP_ANIM, }, { (FRAME)CHMMR_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)CHMMR_VICTORY_SONG, (SOUND)CHMMR_SHIP_SOUNDS, }, { 0, CLOSE_RANGE_WEAPON, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static void animate (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = ElementPtr->next_turn; } } static void laser_death (ELEMENTPTR ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); StarShipPtr->special_counter = ElementPtr->turn_wait; if (StarShipPtr->hShip) { SIZE dx, dy; long dist; HELEMENT hIonSpots; ELEMENTPTR ShipPtr; LockElement (StarShipPtr->hShip, &ShipPtr); dx = ElementPtr->current.location.x - ShipPtr->current.location.x; dy = ElementPtr->current.location.y - ShipPtr->current.location.y; if (((BYTE)TFB_Random () & 0x07) && (dist = (long)dx * dx + (long)dy * dy) >= (long)DISPLAY_TO_WORLD (CHMMR_OFFSET + 10) * DISPLAY_TO_WORLD (CHMMR_OFFSET + 10) && (hIonSpots = AllocElement ())) { COUNT angle, magnitude; ELEMENTPTR IonSpotsPtr; LockElement (hIonSpots, &IonSpotsPtr); IonSpotsPtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | APPEARING | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); IonSpotsPtr->turn_wait = IonSpotsPtr->next_turn = 0; IonSpotsPtr->life_span = 9; angle = ARCTAN (dx, dy); magnitude = ((COUNT)TFB_Random () % ((square_root (dist) + 1) - DISPLAY_TO_WORLD (CHMMR_OFFSET + 10))) + DISPLAY_TO_WORLD (CHMMR_OFFSET + 10); IonSpotsPtr->current.location.x = ShipPtr->current.location.x + COSINE (angle, magnitude); IonSpotsPtr->current.location.y = ShipPtr->current.location.y + SINE (angle, magnitude); IonSpotsPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; IonSpotsPtr->current.image.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.weapon[0], ANGLE_TO_FACING (FULL_CIRCLE) << 1 ); IonSpotsPtr->preprocess_func = animate; SetElementStarShip (IonSpotsPtr, StarShipPtr); SetPrimType (&(GLOBAL (DisplayArray))[ IonSpotsPtr->PrimIndex ], STAMP_PRIM); UnlockElement (hIonSpots); PutElement (hIonSpots); } UnlockElement (StarShipPtr->hShip); } } static COUNT initialize_megawatt_laser (PELEMENT ShipPtr, HELEMENT LaserArray[]) { #define NUM_CYCLES 4 RECT r; STARSHIPPTR StarShipPtr; LASER_BLOCK LaserBlock; static const COLOR cycle_array[] = { BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7F), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7F), }; GetElementStarShip (ShipPtr, &StarShipPtr); LaserBlock.face = StarShipPtr->ShipFacing; GetFrameRect (SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.weapon[0], LaserBlock.face ), &r); LaserBlock.cx = DISPLAY_ALIGN (ShipPtr->next.location.x) + DISPLAY_TO_WORLD (r.corner.x); LaserBlock.cy = DISPLAY_ALIGN (ShipPtr->next.location.y) + DISPLAY_TO_WORLD (r.corner.y); LaserBlock.ex = COSINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); LaserBlock.ey = SINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); LaserBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; LaserBlock.pixoffs = 0; LaserBlock.color = cycle_array[StarShipPtr->special_counter]; LaserArray[0] = initialize_laser (&LaserBlock); if (LaserArray[0]) { ELEMENTPTR LaserPtr; LockElement (LaserArray[0], &LaserPtr); LaserPtr->mass_points = 2; LaserPtr->death_func = laser_death; LaserPtr->turn_wait = (BYTE)((StarShipPtr->special_counter + 1) % NUM_CYCLES); UnlockElement (LaserArray[0]); } return (1); } static void chmmr_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { STARSHIPPTR StarShipPtr; PEVALUATE_DESC lpEvalDesc; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->ship_input_state &= ~SPECIAL; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->special_counter == 0 && lpEvalDesc->ObjectPtr && !(StarShipPtr->ship_input_state & WEAPON) && lpEvalDesc->which_turn > 12 && NORMALIZE_ANGLE ( GetVelocityTravelAngle (&ShipPtr->velocity) - (GetVelocityTravelAngle (&lpEvalDesc->ObjectPtr->velocity) + HALF_CIRCLE) + QUADRANT ) > HALF_CIRCLE) StarShipPtr->ship_input_state |= SPECIAL; } static void chmmr_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->cur_status_flags & WEAPON) { HELEMENT hMuzzleFlash; ELEMENTPTR MuzzleFlashPtr; LockElement (GetTailElement (), &MuzzleFlashPtr); if ((PELEMENT)MuzzleFlashPtr != ElementPtr && (MuzzleFlashPtr->state_flags & (GOOD_GUY | BAD_GUY)) == (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) && (MuzzleFlashPtr->state_flags & APPEARING) && GetPrimType (&(GLOBAL (DisplayArray))[ MuzzleFlashPtr->PrimIndex ]) == LINE_PRIM && !(StarShipPtr->special_counter & 1) && (hMuzzleFlash = AllocElement ())) { LockElement (hMuzzleFlash, &MuzzleFlashPtr); MuzzleFlashPtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | APPEARING | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); MuzzleFlashPtr->life_span = 1; MuzzleFlashPtr->current = ElementPtr->next; MuzzleFlashPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MuzzleFlashPtr->current.image.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.weapon[0], StarShipPtr->ShipFacing + ANGLE_TO_FACING (FULL_CIRCLE) ); SetElementStarShip (MuzzleFlashPtr, StarShipPtr); SetPrimType (&(GLOBAL (DisplayArray))[ MuzzleFlashPtr->PrimIndex ], STAMP_PRIM); UnlockElement (hMuzzleFlash); PutElement (hMuzzleFlash); } UnlockElement (GetTailElement ()); } if ((StarShipPtr->cur_status_flags & SPECIAL) && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { COUNT facing; ELEMENTPTR ShipElementPtr; LockElement (ElementPtr->hTarget, &ShipElementPtr); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ShipElementPtr); UnlockElement (ElementPtr->hTarget); facing = 0; if (TrackShip (ElementPtr, &facing) >= 0) { #define NUM_SHADOWS 5 ELEMENTPTR ShipElementPtr; LockElement (ElementPtr->hTarget, &ShipElementPtr); if (!GRAVITY_MASS (ShipElementPtr->mass_points + 1)) { SIZE i, dx, dy; COUNT angle, magnitude; STARSHIPPTR EnemyStarShipPtr; static const SIZE shadow_offs[] = { DISPLAY_TO_WORLD (8), DISPLAY_TO_WORLD (8 + 9), DISPLAY_TO_WORLD (8 + 9 + 11), DISPLAY_TO_WORLD (8 + 9 + 11 + 14), DISPLAY_TO_WORLD (8 + 9 + 11 + 14 + 18), }; static const COLOR color_tab[] = { BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x10), 0x53), BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x0E), 0x54), BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x0C), 0x55), BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x09), 0x56), BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x07), 0x57), }; DWORD current_speed, max_speed; // calculate tractor beam effect angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); dx = (ElementPtr->next.location.x + COSINE (angle, (LASER_RANGE / 3) + DISPLAY_TO_WORLD (CHMMR_OFFSET))) - ShipElementPtr->next.location.x; dy = (ElementPtr->next.location.y + SINE (angle, (LASER_RANGE / 3) + DISPLAY_TO_WORLD (CHMMR_OFFSET))) - ShipElementPtr->next.location.y; angle = ARCTAN (dx, dy); magnitude = WORLD_TO_VELOCITY (12) / ShipElementPtr->mass_points; DeltaVelocityComponents (&ShipElementPtr->velocity, COSINE (angle, magnitude), SINE (angle, magnitude)); GetCurrentVelocityComponents (&ShipElementPtr->velocity, &dx, &dy); GetElementStarShip (ShipElementPtr, &EnemyStarShipPtr); // set the effected ship's speed flags current_speed = VelocitySquared (dx, dy); max_speed = VelocitySquared (WORLD_TO_VELOCITY ( EnemyStarShipPtr->RaceDescPtr->characteristics.max_thrust), 0); EnemyStarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); if (current_speed > max_speed) EnemyStarShipPtr->cur_status_flags |= (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); else if (current_speed == max_speed) EnemyStarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; // add tractor beam graphical effects for (i = 0; i < NUM_SHADOWS; ++i) { HELEMENT hShadow; hShadow = AllocElement (); if (hShadow) { ELEMENTPTR ShadowElementPtr; LockElement (hShadow, &ShadowElementPtr); ShadowElementPtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | POST_PROCESS | (ShipElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); ShadowElementPtr->life_span = 1; ShadowElementPtr->current = ShipElementPtr->next; ShadowElementPtr->current.location.x += COSINE (angle, shadow_offs[i]); ShadowElementPtr->current.location.y += SINE (angle, shadow_offs[i]); ShadowElementPtr->next = ShadowElementPtr->current; SetElementStarShip (ShadowElementPtr, EnemyStarShipPtr); SetVelocityComponents (&ShadowElementPtr->velocity, dx, dy); SetPrimType (&(GLOBAL (DisplayArray))[ ShadowElementPtr->PrimIndex ], STAMPFILL_PRIM); SetPrimColor (&(GLOBAL (DisplayArray))[ ShadowElementPtr->PrimIndex ], color_tab[i]); UnlockElement (hShadow); InsertElement (hShadow, GetHeadElement ()); } } } UnlockElement (ElementPtr->hTarget); } } StarShipPtr->special_counter = 0; } #define SATELLITE_OFFSET DISPLAY_TO_WORLD (64) static void satellite_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; ++ElementPtr->life_span; ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, (GetFrameIndex (ElementPtr->current.image.frame) + 1) & 7); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = (BYTE)NORMALIZE_ANGLE ( ElementPtr->turn_wait + 1 ); GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->hShip) { SIZE dx, dy; ELEMENTPTR ShipPtr; StarShipPtr->RaceDescPtr->ship_info.ship_flags |= POINT_DEFENSE; LockElement (StarShipPtr->hShip, &ShipPtr); dx = (ShipPtr->next.location.x + COSINE (ElementPtr->turn_wait, SATELLITE_OFFSET)) - ElementPtr->current.location.x; dy = (ShipPtr->next.location.y + SINE (ElementPtr->turn_wait, SATELLITE_OFFSET)) - ElementPtr->current.location.y; dx = WRAP_DELTA_X (dx); dy = WRAP_DELTA_Y (dy); if ((long)dx * dx + (long)dy * dy <= DISPLAY_TO_WORLD (20L) * DISPLAY_TO_WORLD (20L)) SetVelocityComponents (&ElementPtr->velocity, WORLD_TO_VELOCITY (dx), WORLD_TO_VELOCITY (dy)); else { COUNT angle; angle = ARCTAN (dx, dy); SetVelocityComponents (&ElementPtr->velocity, COSINE (angle, WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (20))), SINE (angle, WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (20)))); } UnlockElement (StarShipPtr->hShip); } } static void spawn_point_defense (PELEMENT ElementPtr) { #define DEFENSE_RANGE (UWORD)64 #define DEFENSE_WAIT 2 BYTE weakest; UWORD best_dist; STARSHIPPTR StarShipPtr; HELEMENT hObject, hNextObject, hBestObject; ELEMENTPTR ShipPtr, SattPtr, ObjectPtr; GetElementStarShip (ElementPtr, &StarShipPtr); hBestObject = 0; best_dist = DEFENSE_RANGE + 1; weakest = 255; LockElement (StarShipPtr->hShip, &ShipPtr); LockElement (ElementPtr->hTarget, &SattPtr); for (hObject = GetPredElement (ElementPtr); hObject; hObject = hNextObject) { LockElement (hObject, &ObjectPtr); hNextObject = GetPredElement (ObjectPtr); if (((ObjectPtr->state_flags | ShipPtr->state_flags) & (GOOD_GUY | BAD_GUY)) == (GOOD_GUY | BAD_GUY) && CollisionPossible (ObjectPtr, ShipPtr) && !OBJECT_CLOAKED (ObjectPtr)) { SIZE delta_x, delta_y; UWORD dist; delta_x = ObjectPtr->next.location.x - SattPtr->next.location.x; delta_y = ObjectPtr->next.location.y - SattPtr->next.location.y; if (delta_x < 0) delta_x = -delta_x; if (delta_y < 0) delta_y = -delta_y; delta_x = WORLD_TO_DISPLAY (delta_x); delta_y = WORLD_TO_DISPLAY (delta_y); if ((UWORD)delta_x <= DEFENSE_RANGE && (UWORD)delta_y <= DEFENSE_RANGE && (dist = (UWORD)delta_x * (UWORD)delta_x + (UWORD)delta_y * (UWORD)delta_y) <= DEFENSE_RANGE * DEFENSE_RANGE && (ObjectPtr->hit_points < weakest || (ObjectPtr->hit_points == weakest && dist < best_dist))) { hBestObject = hObject; best_dist = dist; weakest = ObjectPtr->hit_points; } } UnlockElement (hObject); } if (hBestObject) { LASER_BLOCK LaserBlock; HELEMENT hPointDefense; LockElement (hBestObject, &ObjectPtr); LaserBlock.cx = SattPtr->next.location.x; LaserBlock.cy = SattPtr->next.location.y; LaserBlock.face = 0; LaserBlock.ex = ObjectPtr->next.location.x - SattPtr->next.location.x; LaserBlock.ey = ObjectPtr->next.location.y - SattPtr->next.location.y; LaserBlock.sender = (SattPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; LaserBlock.pixoffs = 0; LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x00, 0x01, 0x1F), 0x4D); hPointDefense = initialize_laser (&LaserBlock); if (hPointDefense) { ELEMENTPTR PDPtr; LockElement (hPointDefense, &PDPtr); SetElementStarShip (PDPtr, StarShipPtr); PDPtr->hTarget = 0; UnlockElement (hPointDefense); PutElement (hPointDefense); SattPtr->thrust_wait = DEFENSE_WAIT; } UnlockElement (hBestObject); } UnlockElement (ElementPtr->hTarget); UnlockElement (StarShipPtr->hShip); } static void satellite_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; if (ElementPtr->thrust_wait || ElementPtr->life_span == 0) --ElementPtr->thrust_wait; else { HELEMENT hDefense; hDefense = AllocElement (); if (hDefense) { ELEMENTPTR DefensePtr; PutElement (hDefense); LockElement (hDefense, &DefensePtr); DefensePtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); { ELEMENTPTR SuccPtr; LockElement (GetSuccElement (ElementPtr), &SuccPtr); DefensePtr->hTarget = GetPredElement (SuccPtr); UnlockElement (GetSuccElement (ElementPtr)); DefensePtr->death_func = spawn_point_defense; } GetElementStarShip (ElementPtr, &StarShipPtr); SetElementStarShip (DefensePtr, StarShipPtr); UnlockElement (hDefense); } } } static void satellite_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { (void) ElementPtr0; /* Satisfying compiler (unused parameter) */ (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) ElementPtr1; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } static void satellite_death (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); StarShipPtr->RaceDescPtr->ship_info.ship_flags &= ~POINT_DEFENSE; ElementPtr->state_flags &= ~DISAPPEARING; ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; ElementPtr->life_span = 4; ElementPtr->turn_wait = 1; ElementPtr->next_turn = 0; ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, 8); ElementPtr->preprocess_func = animate; ElementPtr->death_func = NULL_PTR; ElementPtr->postprocess_func = NULL_PTR; ElementPtr->collision_func = NULL_PTR; } static void spawn_satellites (PELEMENT ElementPtr) { #define NUM_SATELLITES 3 COUNT i; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->hShip) { LockElement (StarShipPtr->hShip, &ElementPtr); for (i = 0; i < NUM_SATELLITES; ++i) { HELEMENT hSatellite; hSatellite = AllocElement (); if (hSatellite) { COUNT angle; ELEMENTPTR SattPtr; LockElement (hSatellite, &SattPtr); SattPtr->state_flags = IGNORE_SIMILAR | APPEARING | FINITE_LIFE | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); SattPtr->life_span = NORMAL_LIFE + 1; SattPtr->hit_points = 10; SattPtr->mass_points = 10; angle = (i * FULL_CIRCLE + (NUM_SATELLITES >> 1)) / NUM_SATELLITES; SattPtr->turn_wait = (BYTE)angle; SattPtr->current.location.x = ElementPtr->next.location.x + COSINE (angle, SATELLITE_OFFSET); SattPtr->current.location.y = ElementPtr->next.location.y + SINE (angle, SATELLITE_OFFSET); SattPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; SattPtr->current.image.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.special[0], (COUNT)TFB_Random () & 0x07 ); SattPtr->preprocess_func = satellite_preprocess; SattPtr->postprocess_func = satellite_postprocess; SattPtr->death_func = satellite_death; SattPtr->collision_func = satellite_collision; SetElementStarShip (SattPtr, StarShipPtr); SetPrimType (&(GLOBAL (DisplayArray))[ SattPtr->PrimIndex ], STAMP_PRIM); UnlockElement (hSatellite); PutElement (hSatellite); } } UnlockElement (StarShipPtr->hShip); } } static void chmmr_preprocess (PELEMENT ElementPtr) { HELEMENT hSatellite; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); hSatellite = AllocElement (); if (hSatellite) { ELEMENTPTR SattPtr; STARSHIPPTR StarShipPtr; LockElement (hSatellite, &SattPtr); SattPtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | APPEARING | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); SattPtr->life_span = HYPERJUMP_LIFE + 1; SattPtr->death_func = spawn_satellites; GetElementStarShip (ElementPtr, &StarShipPtr); SetElementStarShip (SattPtr, StarShipPtr); SetPrimType (&(GLOBAL (DisplayArray))[ SattPtr->PrimIndex ], NO_PRIM); UnlockElement (hSatellite); PutElement (hSatellite); } StarShipPtr->RaceDescPtr->preprocess_func = 0; } RACE_DESCPTR init_chmmr (void) { RACE_DESCPTR RaceDescPtr; chmmr_desc.preprocess_func = chmmr_preprocess; chmmr_desc.postprocess_func = chmmr_postprocess; chmmr_desc.init_weapon_func = initialize_megawatt_laser; chmmr_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) chmmr_intelligence; RaceDescPtr = &chmmr_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/chmmr/istrtab.h0000600000175000017500000000005110543202070017651 0ustar joeyjoey#define CHMMR_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/chmmr/imusicre.h0000600000175000017500000000005110543202070020021 0ustar joeyjoey#define CHMMR_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/chmmr/icode.h0000600000175000017500000000004110543202070017263 0ustar joeyjoey#define CHMMR_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/chmmr/Makeinfo0000600000175000017500000000002510543202070017505 0ustar joeyjoeyuqm_CFILES="chmmr.c" uqm-0.6.2/sc2/src/sc2code/ships/chmmr/chmmr.res0000600000175000017500000000147410543202070017663 0ustar joeyjoeyINCLUDE ../star3do.typ PATH chmmr PACKAGE CHMMR_CODE_PACKAGE chmmr.shp CODE CHMMR_CODE chmmr.cod GFXRES CHMMR_ICON_MASK_PMAP_ANIM chmicons.ani GFXRES CHMMR_MICON_MASK_PMAP_ANIM chmmicon.ani STRTAB CHMMR_RACE_STRINGS chmtext.txt PACKAGE CHMMR_PACKAGE chmmr.shp GFXRES CHMMR_BIG_MASK_PMAP_ANIM chmmr.big GFXRES CHMMR_MED_MASK_PMAP_ANIM chmmr.med GFXRES CHMMR_SML_MASK_PMAP_ANIM chmmr.sml GFXRES MUZZLE_BIG_MASK_PMAP_ANIM muzbig.ani GFXRES MUZZLE_MED_MASK_PMAP_ANIM muzmed.ani GFXRES MUZZLE_SML_MASK_PMAP_ANIM muzsml.ani GFXRES SATELLITE_BIG_MASK_PMAP_ANIM satbig.ani GFXRES SATELLITE_MED_MASK_PMAP_ANIM satmed.ani GFXRES SATELLITE_SML_MASK_PMAP_ANIM satsml.ani GFXRES CHMMR_CAPTAIN_MASK_PMAP_ANIM chmcap.ani SNDRES CHMMR_SHIP_SOUNDS chmsound.snd MUSICRES CHMMR_VICTORY_SONG chmditty.mod uqm-0.6.2/sc2/src/sc2code/ships/chmmr/respkg.h0000600000175000017500000000006310543202070017477 0ustar joeyjoeyenum { CHMMR_CODE_PACKAGE = 1, CHMMR_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/chmmr/resinst.h0000600000175000017500000000015010543202070017670 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/spathi/0000755000175000017500000000000010552600274016236 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/spathi/restypes.h0000600000175000017500000000024110543202062020243 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/spathi/igfxres.h0000600000175000017500000000106710543202062020043 0ustar joeyjoey#define SPATHI_ICON_MASK_PMAP_ANIM 0x00200002L #define SPATHI_MICON_MASK_PMAP_ANIM 0x00200102L #define SPATHI_BIG_MASK_PMAP_ANIM 0x00400202L #define SPATHI_MED_MASK_PMAP_ANIM 0x00400302L #define SPATHI_SML_MASK_PMAP_ANIM 0x00400402L #define MISSILE_BIG_MASK_PMAP_ANIM 0x00400502L #define MISSILE_MED_MASK_PMAP_ANIM 0x00400602L #define MISSILE_SML_MASK_PMAP_ANIM 0x00400702L #define DISCRIM_BIG_MASK_PMAP_ANIM 0x00400802L #define DISCRIM_MED_MASK_PMAP_ANIM 0x00400902L #define DISCRIM_SML_MASK_PMAP_ANIM 0x00400a02L #define SPATHI_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/spathi/spathi.res0000600000175000017500000000152310543202062020223 0ustar joeyjoeyINCLUDE ../star3do.typ PATH spathi PACKAGE SPATHI_CODE_PACKAGE spathi.shp CODE SPATHI_CODE spathi.cod GFXRES SPATHI_ICON_MASK_PMAP_ANIM spaicons.ani GFXRES SPATHI_MICON_MASK_PMAP_ANIM spamicon.ani STRTAB SPATHI_RACE_STRINGS spatext.txt PACKAGE SPATHI_PACKAGE spathi.shp GFXRES SPATHI_BIG_MASK_PMAP_ANIM spathi.big GFXRES SPATHI_MED_MASK_PMAP_ANIM spathi.med GFXRES SPATHI_SML_MASK_PMAP_ANIM spathi.sml GFXRES MISSILE_BIG_MASK_PMAP_ANIM missile.big GFXRES MISSILE_MED_MASK_PMAP_ANIM missile.med GFXRES MISSILE_SML_MASK_PMAP_ANIM missile.sml GFXRES DISCRIM_BIG_MASK_PMAP_ANIM discrim.big GFXRES DISCRIM_MED_MASK_PMAP_ANIM discrim.med GFXRES DISCRIM_SML_MASK_PMAP_ANIM discrim.sml GFXRES SPATHI_CAPTAIN_MASK_PMAP_ANIM spacap.ani SNDRES SPATHI_SHIP_SOUNDS spasound.snd MUSICRES SPATHI_VICTORY_SONG spaditty.mod uqm-0.6.2/sc2/src/sc2code/ships/spathi/isndres.h0000600000175000017500000000005110543202062020033 0ustar joeyjoey#define SPATHI_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/spathi/istrtab.h0000600000175000017500000000005210543202062020035 0ustar joeyjoey#define SPATHI_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/spathi/imusicre.h0000600000175000017500000000005210543202062020205 0ustar joeyjoey#define SPATHI_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/spathi/icode.h0000600000175000017500000000004210543202062017447 0ustar joeyjoey#define SPATHI_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/spathi/spathi.c0000600000175000017500000001754610543202062017670 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/spathi/resinst.h" #define MAX_CREW 30 #define MAX_ENERGY 10 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 2 #define SPECIAL_ENERGY_COST 3 #define ENERGY_WAIT 10 #define MAX_THRUST 48 #define THRUST_INCREMENT 12 #define TURN_WAIT 1 #define THRUST_WAIT 1 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 7 #define SHIP_MASS 5 #define MISSILE_SPEED DISPLAY_TO_WORLD (30) #define MISSILE_LIFE 10 #define MISSILE_RANGE (MISSILE_SPEED * MISSILE_LIFE) static RACE_DESC spathi_desc = { { FIRES_FORE | FIRES_AFT | SEEKING_SPECIAL | DONT_CHASE, 18, /* Super Melee cost */ 1000 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 2549, 3600, }, (STRING)SPATHI_RACE_STRINGS, (FRAME)SPATHI_ICON_MASK_PMAP_ANIM, (FRAME)SPATHI_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)SPATHI_BIG_MASK_PMAP_ANIM, (FRAME)SPATHI_MED_MASK_PMAP_ANIM, (FRAME)SPATHI_SML_MASK_PMAP_ANIM, }, { (FRAME)MISSILE_BIG_MASK_PMAP_ANIM, (FRAME)MISSILE_MED_MASK_PMAP_ANIM, (FRAME)MISSILE_SML_MASK_PMAP_ANIM, }, { (FRAME)DISCRIM_BIG_MASK_PMAP_ANIM, (FRAME)DISCRIM_MED_MASK_PMAP_ANIM, (FRAME)DISCRIM_SML_MASK_PMAP_ANIM, }, { (FRAME)SPATHI_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)SPATHI_VICTORY_SONG, (SOUND)SPATHI_SHIP_SOUNDS, }, { 0, MISSILE_RANGE, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define DISCRIMINATOR_SPEED DISPLAY_TO_WORLD (8) #define TRACK_WAIT 1 static void butt_missile_preprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { COUNT facing; facing = GetFrameIndex (ElementPtr->next.image.frame); if (TrackShip (ElementPtr, &facing) > 0) { ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->next.image.frame, facing); ElementPtr->state_flags |= CHANGING; SetVelocityVector (&ElementPtr->velocity, DISCRIMINATOR_SPEED, facing); } ElementPtr->turn_wait = TRACK_WAIT; } } static void spawn_butt_missile (PELEMENT ShipPtr) { #define SPATHI_REAR_OFFSET 20 #define DISCRIMINATOR_LIFE 30 #define DISCRIMINATOR_HITS 1 #define DISCRIMINATOR_DAMAGE 2 #define DISCRIMINATOR_OFFSET 4 HELEMENT ButtMissile; STARSHIPPTR StarShipPtr; MISSILE_BLOCK ButtMissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); ButtMissileBlock.cx = ShipPtr->next.location.x; ButtMissileBlock.cy = ShipPtr->next.location.y; ButtMissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; ButtMissileBlock.face = ButtMissileBlock.index = NORMALIZE_FACING (StarShipPtr->ShipFacing + ANGLE_TO_FACING (HALF_CIRCLE)); ButtMissileBlock.sender = ShipPtr->state_flags & (GOOD_GUY | BAD_GUY); ButtMissileBlock.pixoffs = SPATHI_REAR_OFFSET; ButtMissileBlock.speed = DISCRIMINATOR_SPEED; ButtMissileBlock.hit_points = DISCRIMINATOR_HITS; ButtMissileBlock.damage = DISCRIMINATOR_DAMAGE; ButtMissileBlock.life = DISCRIMINATOR_LIFE; ButtMissileBlock.preprocess_func = butt_missile_preprocess; ButtMissileBlock.blast_offs = DISCRIMINATOR_OFFSET; ButtMissile = initialize_missile (&ButtMissileBlock); if (ButtMissile) { ELEMENTPTR ButtPtr; LockElement (ButtMissile, &ButtPtr); ButtPtr->turn_wait = TRACK_WAIT; SetElementStarShip (ButtPtr, StarShipPtr); ProcessSound (SetAbsSoundIndex ( /* LAUNCH_BUTT_MISSILE */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ButtPtr); UnlockElement (ButtMissile); PutElement (ButtMissile); } } static void spathi_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { STARSHIPPTR StarShipPtr; PEVALUATE_DESC lpEvalDesc; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->ship_input_state &= ~SPECIAL; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->special_counter == 0 && lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 24) { COUNT travel_facing, direction_facing; SIZE delta_x, delta_y; travel_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (GetVelocityTravelAngle (&ShipPtr->velocity) + HALF_CIRCLE) ); delta_x = lpEvalDesc->ObjectPtr->current.location.x - ShipPtr->current.location.x; delta_y = lpEvalDesc->ObjectPtr->current.location.y - ShipPtr->current.location.y; direction_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) ); if (NORMALIZE_FACING (direction_facing - (StarShipPtr->ShipFacing + ANGLE_TO_FACING (HALF_CIRCLE)) + ANGLE_TO_FACING (QUADRANT)) <= ANGLE_TO_FACING (HALF_CIRCLE) && (lpEvalDesc->which_turn <= 8 || NORMALIZE_FACING (direction_facing + ANGLE_TO_FACING (HALF_CIRCLE) - ANGLE_TO_FACING (GetVelocityTravelAngle ( &lpEvalDesc->ObjectPtr->velocity )) + ANGLE_TO_FACING (QUADRANT)) <= ANGLE_TO_FACING (HALF_CIRCLE)) && (!(StarShipPtr->cur_status_flags & (SHIP_BEYOND_MAX_SPEED | SHIP_IN_GRAVITY_WELL)) || NORMALIZE_FACING (direction_facing - travel_facing + ANGLE_TO_FACING (QUADRANT)) <= ANGLE_TO_FACING (HALF_CIRCLE))) StarShipPtr->ship_input_state |= SPECIAL; } } static COUNT initialize_standard_missile (PELEMENT ShipPtr, HELEMENT MissileArray[]) { #define SPATHI_FORWARD_OFFSET 16 #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 1 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = SPATHI_FORWARD_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; MissileArray[0] = initialize_missile (&MissileBlock); return (1); } static void spathi_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { spawn_butt_missile (ElementPtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } RACE_DESCPTR init_spathi (void) { RACE_DESCPTR RaceDescPtr; spathi_desc.postprocess_func = spathi_postprocess; spathi_desc.init_weapon_func = initialize_standard_missile; spathi_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) spathi_intelligence; RaceDescPtr = &spathi_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/spathi/Makeinfo0000600000175000017500000000002610543202062017671 0ustar joeyjoeyuqm_CFILES="spathi.c" uqm-0.6.2/sc2/src/sc2code/ships/spathi/respkg.h0000600000175000017500000000006510543202062017664 0ustar joeyjoeyenum { SPATHI_CODE_PACKAGE = 1, SPATHI_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/spathi/resinst.h0000600000175000017500000000015010543202062020053 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/0000755000175000017500000000000010552600274016270 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/zoqfot/restypes.h0000600000175000017500000000024110543202060020273 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/zoqfot.res0000600000175000017500000000155510543202060020312 0ustar joeyjoeyINCLUDE ../star3do.typ PATH zoqfot PACKAGE ZOQFOTPIK_CODE_PACKAGE zoqfot.shp CODE ZOQFOTPIK_CODE zoqfot.cod GFXRES ZOQFOTPIK_ICON_MASK_PMAP_ANIM zoqicons.ani GFXRES ZOQFOTPIK_MICON_MASK_PMAP_ANIM zoqmicon.ani STRTAB ZOQFOTPIK_RACE_STRINGS zoqtext.txt PACKAGE ZOQFOTPIK_PACKAGE zoqfot.shp GFXRES ZOQFOTPIK_BIG_MASK_PMAP_ANIM zoqfot.big GFXRES ZOQFOTPIK_MED_MASK_PMAP_ANIM zoqfot.med GFXRES ZOQFOTPIK_SML_MASK_PMAP_ANIM zoqfot.sml GFXRES SPIT_BIG_MASK_PMAP_ANIM spitbig.ani GFXRES SPIT_MED_MASK_PMAP_ANIM spitmed.ani GFXRES SPIT_SML_MASK_PMAP_ANIM spitsml.ani GFXRES STINGER_BIG_MASK_PMAP_ANIM stibig.ani GFXRES STINGER_MED_MASK_PMAP_ANIM stimed.ani GFXRES STINGER_SML_MASK_PMAP_ANIM stisml.ani GFXRES ZOQFOTPIK_CAPTAIN_MASK_PMAP_ANIM zoqcap.ani SNDRES ZOQFOTPIK_SHIP_SOUNDS zoqsound.snd MUSICRES ZOQFOTPIK_VICTORY_SONG zoqditty.mod uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/igfxres.h0000600000175000017500000000110010543202060020057 0ustar joeyjoey#define ZOQFOTPIK_ICON_MASK_PMAP_ANIM 0x00200002L #define ZOQFOTPIK_MICON_MASK_PMAP_ANIM 0x00200102L #define ZOQFOTPIK_BIG_MASK_PMAP_ANIM 0x00400202L #define ZOQFOTPIK_MED_MASK_PMAP_ANIM 0x00400302L #define ZOQFOTPIK_SML_MASK_PMAP_ANIM 0x00400402L #define SPIT_BIG_MASK_PMAP_ANIM 0x00400502L #define SPIT_MED_MASK_PMAP_ANIM 0x00400602L #define SPIT_SML_MASK_PMAP_ANIM 0x00400702L #define STINGER_BIG_MASK_PMAP_ANIM 0x00400802L #define STINGER_MED_MASK_PMAP_ANIM 0x00400902L #define STINGER_SML_MASK_PMAP_ANIM 0x00400a02L #define ZOQFOTPIK_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/isndres.h0000600000175000017500000000005410543202060020066 0ustar joeyjoey#define ZOQFOTPIK_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/istrtab.h0000600000175000017500000000005510543202060020070 0ustar joeyjoey#define ZOQFOTPIK_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/imusicre.h0000600000175000017500000000005510543202060020240 0ustar joeyjoey#define ZOQFOTPIK_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/icode.h0000600000175000017500000000004510543202060017502 0ustar joeyjoey#define ZOQFOTPIK_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/Makeinfo0000600000175000017500000000002610543202060017721 0ustar joeyjoeyuqm_CFILES="zoqfot.c" uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/respkg.h0000600000175000017500000000007310543202060017713 0ustar joeyjoeyenum { ZOQFOTPIK_CODE_PACKAGE = 1, ZOQFOTPIK_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/zoqfot.c0000600000175000017500000002300710543202060017737 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/zoqfot/resinst.h" #include "libs/mathlib.h" #define MAX_CREW 10 #define MAX_ENERGY 10 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 1 #define SPECIAL_ENERGY_COST (MAX_ENERGY * 3 / 4) #define ENERGY_WAIT 4 #define MAX_THRUST 40 #define THRUST_INCREMENT 10 #define TURN_WAIT 1 #define THRUST_WAIT 0 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 6 #define SHIP_MASS 5 #define MISSILE_SPEED DISPLAY_TO_WORLD (10) #define MISSILE_LIFE 10 #define MISSILE_RANGE (MISSILE_SPEED * MISSILE_LIFE) static RACE_DESC zoqfotpik_desc = { { FIRES_FORE, 6, /* Super Melee cost */ 320 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 3761, 5333, }, (STRING)ZOQFOTPIK_RACE_STRINGS, (FRAME)ZOQFOTPIK_ICON_MASK_PMAP_ANIM, (FRAME)ZOQFOTPIK_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)ZOQFOTPIK_BIG_MASK_PMAP_ANIM, (FRAME)ZOQFOTPIK_MED_MASK_PMAP_ANIM, (FRAME)ZOQFOTPIK_SML_MASK_PMAP_ANIM, }, { (FRAME)SPIT_BIG_MASK_PMAP_ANIM, (FRAME)SPIT_MED_MASK_PMAP_ANIM, (FRAME)SPIT_SML_MASK_PMAP_ANIM, }, { (FRAME)STINGER_BIG_MASK_PMAP_ANIM, (FRAME)STINGER_MED_MASK_PMAP_ANIM, (FRAME)STINGER_SML_MASK_PMAP_ANIM, }, { (FRAME)ZOQFOTPIK_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)ZOQFOTPIK_VICTORY_SONG, (SOUND)ZOQFOTPIK_SHIP_SOUNDS, }, { 0, MISSILE_RANGE, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define ZOQFOTPIK_OFFSET 13 #define SPIT_WAIT 2 static void spit_preprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { COUNT index, angle, speed; ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->next.image.frame); angle = GetVelocityTravelAngle (&ElementPtr->velocity); if ((index = GetFrameIndex (ElementPtr->next.image.frame)) == 1) angle = angle + (((COUNT)TFB_Random () % 3) - 1); speed = WORLD_TO_VELOCITY (DISPLAY_TO_WORLD ( GetFrameCount (ElementPtr->next.image.frame) - index) << 1); SetVelocityComponents (&ElementPtr->velocity, (SIZE)COSINE (angle, speed), (SIZE)SINE (angle, speed)); ElementPtr->turn_wait = SPIT_WAIT; ElementPtr->state_flags |= CHANGING; } } static COUNT initialize_spit (PELEMENT ShipPtr, HELEMENT SpitArray[]) { #define MISSILE_DAMAGE 1 #define MISSILE_HITS 1 #define MISSILE_OFFSET 0 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = ZOQFOTPIK_OFFSET; MissileBlock.speed = DISPLAY_TO_WORLD ( GetFrameCount (StarShipPtr->RaceDescPtr->ship_data.weapon[0])) << 1; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = spit_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; SpitArray[0] = initialize_missile (&MissileBlock); return (1); } static void spawn_tongue (PELEMENT ElementPtr); static void tongue_postprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait) spawn_tongue (ElementPtr); } static void tongue_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr0, &StarShipPtr); if (StarShipPtr->special_counter == StarShipPtr->RaceDescPtr->characteristics.special_wait) weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); StarShipPtr->special_counter -= ElementPtr0->turn_wait; ElementPtr0->turn_wait = 0; ElementPtr0->state_flags |= NONSOLID; } static void spawn_tongue (ElementPtr) PELEMENT ElementPtr; { #define TONGUE_SPEED 0 #define TONGUE_HITS 1 #define TONGUE_DAMAGE 12 #define TONGUE_OFFSET 4 STARSHIPPTR StarShipPtr; MISSILE_BLOCK TongueBlock; HELEMENT Tongue; GetElementStarShip (ElementPtr, &StarShipPtr); TongueBlock.cx = ElementPtr->next.location.x; TongueBlock.cy = ElementPtr->next.location.y; TongueBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; TongueBlock.face = TongueBlock.index = StarShipPtr->ShipFacing; TongueBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; TongueBlock.pixoffs = 0; TongueBlock.speed = TONGUE_SPEED; TongueBlock.hit_points = TONGUE_HITS; TongueBlock.damage = TONGUE_DAMAGE; TongueBlock.life = 1; TongueBlock.preprocess_func = 0; TongueBlock.blast_offs = TONGUE_OFFSET; Tongue = initialize_missile (&TongueBlock); if (Tongue) { ELEMENTPTR TonguePtr; LockElement (Tongue, &TonguePtr); TonguePtr->postprocess_func = tongue_postprocess; TonguePtr->collision_func = tongue_collision; if (ElementPtr->state_flags & PLAYER_SHIP) TonguePtr->turn_wait = StarShipPtr->special_counter; else { COUNT angle; RECT r; SIZE x_offs, y_offs; TonguePtr->turn_wait = ElementPtr->turn_wait - 1; GetFrameRect (TonguePtr->current.image.frame, &r); x_offs = DISPLAY_TO_WORLD (r.extent.width >> 1); y_offs = DISPLAY_TO_WORLD (r.extent.height >> 1); angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); if (angle > HALF_CIRCLE && angle < FULL_CIRCLE) TonguePtr->current.location.x -= x_offs; else if (angle > 0 && angle < HALF_CIRCLE) TonguePtr->current.location.x += x_offs; if (angle < QUADRANT || angle > FULL_CIRCLE - QUADRANT) TonguePtr->current.location.y -= y_offs; else if (angle > QUADRANT && angle < FULL_CIRCLE - QUADRANT) TonguePtr->current.location.y += y_offs; } SetElementStarShip (TonguePtr, StarShipPtr); UnlockElement (Tongue); PutElement (Tongue); } } static void zoqfotpik_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { BOOLEAN GiveTongueJob; STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); GiveTongueJob = FALSE; if (StarShipPtr->special_counter == 0) { PEVALUATE_DESC lpEnemyEvalDesc; StarShipPtr->ship_input_state &= ~SPECIAL; lpEnemyEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEnemyEvalDesc->ObjectPtr && lpEnemyEvalDesc->which_turn <= 4 #ifdef NEVER && StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST #endif /* NEVER */ ) { SIZE delta_x, delta_y; GiveTongueJob = TRUE; lpEnemyEvalDesc->MoveState = PURSUE; delta_x = lpEnemyEvalDesc->ObjectPtr->next.location.x - ShipPtr->next.location.x; delta_y = lpEnemyEvalDesc->ObjectPtr->next.location.y - ShipPtr->next.location.y; if (StarShipPtr->ShipFacing == NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) )) StarShipPtr->ship_input_state |= SPECIAL; } } ++StarShipPtr->weapon_counter; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); --StarShipPtr->weapon_counter; if (StarShipPtr->weapon_counter == 0) { StarShipPtr->ship_input_state &= ~WEAPON; if (!GiveTongueJob) { ObjectsOfConcern += ConcernCounter; while (ConcernCounter--) { --ObjectsOfConcern; if (ObjectsOfConcern->ObjectPtr && (ConcernCounter == ENEMY_SHIP_INDEX || (ConcernCounter == ENEMY_WEAPON_INDEX && ObjectsOfConcern->MoveState != AVOID #ifdef NEVER && !(PlayerControl[cur_player] & STANDARD_RATING) #endif /* NEVER */ )) && ship_weapons (ShipPtr, ObjectsOfConcern->ObjectPtr, DISPLAY_TO_WORLD (20))) { StarShipPtr->ship_input_state |= WEAPON; break; } } } } } static void zoqfotpik_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { ProcessSound (SetAbsSoundIndex ( /* STICK_OUT_TONGUE */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } if (StarShipPtr->special_counter) spawn_tongue (ElementPtr); } RACE_DESCPTR init_zoqfotpik (void) { RACE_DESCPTR RaceDescPtr; zoqfotpik_desc.postprocess_func = zoqfotpik_postprocess; zoqfotpik_desc.init_weapon_func = initialize_spit; zoqfotpik_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) zoqfotpik_intelligence; RaceDescPtr = &zoqfotpik_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/zoqfot/resinst.h0000600000175000017500000000015010543202060020103 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/androsyn/0000755000175000017500000000000010552600274016603 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/androsyn/restypes.h0000600000175000017500000000024110543202064020612 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/androsyn/igfxres.h0000600000175000017500000000110610543202064020404 0ustar joeyjoey#define ANDROSYNTH_ICON_MASK_PMAP_ANIM 0x00200002L #define ANDROSYNTH_MICON_MASK_PMAP_ANIM 0x00200102L #define ANDROSYNTH_BIG_MASK_PMAP_ANIM 0x00400202L #define ANDROSYNTH_MED_MASK_PMAP_ANIM 0x00400302L #define ANDROSYNTH_SML_MASK_PMAP_ANIM 0x00400402L #define BUBBLE_BIG_MASK_PMAP_ANIM 0x00400502L #define BUBBLE_MED_MASK_PMAP_ANIM 0x00400602L #define BUBBLE_SML_MASK_PMAP_ANIM 0x00400702L #define BLAZER_BIG_MASK_PMAP_ANIM 0x00400802L #define BLAZER_MED_MASK_PMAP_ANIM 0x00400902L #define BLAZER_SML_MASK_PMAP_ANIM 0x00400a02L #define ANDROSYNTH_CAPT_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/androsyn/androsyn.c0000600000175000017500000003263210543202064020575 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/androsyn/resinst.h" #include "libs/mathlib.h" #define MAX_CREW 20 #define MAX_ENERGY 24 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 3 #define SPECIAL_ENERGY_COST 2 #define ENERGY_WAIT 8 #define MAX_THRUST 24 #define THRUST_INCREMENT 3 #define TURN_WAIT 4 #define THRUST_WAIT 0 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 0 #define SHIP_MASS 6 static RACE_DESC androsynth_desc = { { FIRES_FORE | SEEKING_WEAPON, 15, /* Super Melee cost */ ~0, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { MAX_X_UNIVERSE >> 1, MAX_Y_UNIVERSE >> 1, }, (STRING)ANDROSYNTH_RACE_STRINGS, (FRAME)ANDROSYNTH_ICON_MASK_PMAP_ANIM, (FRAME)ANDROSYNTH_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)ANDROSYNTH_BIG_MASK_PMAP_ANIM, (FRAME)ANDROSYNTH_MED_MASK_PMAP_ANIM, (FRAME)ANDROSYNTH_SML_MASK_PMAP_ANIM, }, { (FRAME)BUBBLE_BIG_MASK_PMAP_ANIM, (FRAME)BUBBLE_MED_MASK_PMAP_ANIM, (FRAME)BUBBLE_SML_MASK_PMAP_ANIM, }, { (FRAME)BLAZER_BIG_MASK_PMAP_ANIM, (FRAME)BLAZER_MED_MASK_PMAP_ANIM, (FRAME)BLAZER_SML_MASK_PMAP_ANIM, }, { (FRAME)ANDROSYNTH_CAPT_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)ANDROSYNTH_VICTORY_SONG, (SOUND)ANDROSYNTH_SHIP_SOUNDS, }, { 0, LONG_RANGE_WEAPON >> 2, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define BLAZER_DAMAGE 3 #define BLAZER_MASS 1 static void blazer_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { #define BLAZER_OFFSET 10 BYTE old_offs; COUNT old_crew_level; COUNT old_life; old_crew_level = ElementPtr0->crew_level; old_life = ElementPtr0->life_span; old_offs = ElementPtr0->blast_offset; ElementPtr0->blast_offset = BLAZER_OFFSET; ElementPtr0->mass_points = BLAZER_DAMAGE; weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); ElementPtr0->mass_points = BLAZER_MASS; ElementPtr0->blast_offset = old_offs; ElementPtr0->life_span = old_life; ElementPtr0->crew_level = old_crew_level; ElementPtr0->state_flags &= ~(DISAPPEARING | NONSOLID); collision (ElementPtr0, pPt0, ElementPtr1, pPt1); } #define MISSILE_SPEED DISPLAY_TO_WORLD (8) static void bubble_preprocess (PELEMENT ElementPtr) { BYTE thrust_wait, turn_wait; thrust_wait = HINIBBLE (ElementPtr->turn_wait); turn_wait = LONIBBLE (ElementPtr->turn_wait); if (thrust_wait > 0) --thrust_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; thrust_wait = (BYTE)((COUNT)TFB_Random () & 3); } if (turn_wait > 0) --turn_wait; else { COUNT facing; SIZE delta_facing; facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity) )); if ((delta_facing = TrackShip (ElementPtr, &facing)) == -1) facing = (COUNT)TFB_Random (); else if (delta_facing <= ANGLE_TO_FACING (HALF_CIRCLE)) facing += (COUNT)TFB_Random () & (ANGLE_TO_FACING (HALF_CIRCLE) - 1); else facing -= (COUNT)TFB_Random () & (ANGLE_TO_FACING (HALF_CIRCLE) - 1); SetVelocityVector (&ElementPtr->velocity, MISSILE_SPEED, facing); #define TRACK_WAIT 2 turn_wait = TRACK_WAIT; } ElementPtr->turn_wait = MAKE_BYTE (turn_wait, thrust_wait); } #define MISSILE_DAMAGE 2 #define MISSILE_LIFE 200 static COUNT initialize_bubble (PELEMENT ShipPtr, HELEMENT BubbleArray[]) { #define ANDROSYNTH_OFFSET 14 #define MISSILE_OFFSET 3 #define MISSILE_HITS 3 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = ANDROSYNTH_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = bubble_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; BubbleArray[0] = initialize_missile (&MissileBlock); if (BubbleArray[0]) { ELEMENTPTR BubblePtr; LockElement (BubbleArray[0], &BubblePtr); BubblePtr->turn_wait = 0; UnlockElement (BubbleArray[0]); } return (1); } static void androsynth_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { PEVALUATE_DESC lpEvalDesc; STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; /* in blazer form */ if (ShipPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) { ObjectsOfConcern[CREW_OBJECT_INDEX].ObjectPtr = 0; if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) { if ((lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) && !(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) lpEvalDesc->MoveState = AVOID; else lpEvalDesc->ObjectPtr = 0; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); } else { STARSHIPPTR pEnemyStarShip; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { GetElementStarShip (lpEvalDesc->ObjectPtr, &pEnemyStarShip); if (lpEvalDesc->which_turn <= 16 && (StarShipPtr->special_counter > 0 || StarShipPtr->RaceDescPtr->ship_info.energy_level < MAX_ENERGY / 3 || ((WEAPON_RANGE (&pEnemyStarShip->RaceDescPtr->cyborg_control) <= CLOSE_RANGE_WEAPON && lpEvalDesc->ObjectPtr->crew_level > BLAZER_DAMAGE) || (lpEvalDesc->ObjectPtr->crew_level > (BLAZER_DAMAGE * 3) && MANEUVERABILITY (&pEnemyStarShip->RaceDescPtr->cyborg_control) > SLOW_SHIP)))) lpEvalDesc->MoveState = ENTICE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (StarShipPtr->special_counter == 0) { StarShipPtr->ship_input_state &= ~SPECIAL; if ((ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 4) || (lpEvalDesc->ObjectPtr && StarShipPtr->RaceDescPtr->ship_info.energy_level >= MAX_ENERGY / 3 && (WEAPON_RANGE (&pEnemyStarShip->RaceDescPtr->cyborg_control) >= WEAPON_RANGE (&StarShipPtr->RaceDescPtr->cyborg_control) << 1 || (lpEvalDesc->which_turn < 16 && (WEAPON_RANGE (&pEnemyStarShip->RaceDescPtr->cyborg_control) > CLOSE_RANGE_WEAPON || lpEvalDesc->ObjectPtr->crew_level <= BLAZER_DAMAGE) && (lpEvalDesc->ObjectPtr->crew_level <= (BLAZER_DAMAGE * 3) || MANEUVERABILITY (&pEnemyStarShip->RaceDescPtr->cyborg_control) <= SLOW_SHIP))))) StarShipPtr->ship_input_state |= SPECIAL; } if (!(StarShipPtr->ship_input_state & SPECIAL) && StarShipPtr->weapon_counter == 0 && lpEvalDesc->ObjectPtr) { if (lpEvalDesc->which_turn <= 4) StarShipPtr->ship_input_state |= WEAPON; else if (lpEvalDesc->MoveState != PURSUE && lpEvalDesc->which_turn <= 12) { COUNT travel_facing, direction_facing; SIZE delta_x, delta_y, ship_delta_x, ship_delta_y, other_delta_x, other_delta_y; GetCurrentVelocityComponents (&ShipPtr->velocity, &ship_delta_x, &ship_delta_y); GetCurrentVelocityComponents (&lpEvalDesc->ObjectPtr->velocity, &other_delta_x, &other_delta_y); delta_x = ship_delta_x - other_delta_x; delta_y = ship_delta_y - other_delta_y; travel_facing = ARCTAN (delta_x, delta_y); delta_x = lpEvalDesc->ObjectPtr->next.location.x - ShipPtr->next.location.x; delta_y = lpEvalDesc->ObjectPtr->next.location.y - ShipPtr->next.location.y; direction_facing = ARCTAN (delta_x, delta_y); if (NORMALIZE_ANGLE (travel_facing - direction_facing + OCTANT) <= QUADRANT) StarShipPtr->ship_input_state |= WEAPON; } } } } static void (*ship_collision_func[2]) (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1); #define BLAZER_TURN_WAIT 1 static void androsynth_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); /* take care of blazer effect */ if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) { #define BLAZER_DEGENERATION (-1) if ((StarShipPtr->cur_status_flags & SPECIAL) || StarShipPtr->RaceDescPtr->ship_info.energy_level == 0) { StarShipPtr->RaceDescPtr->characteristics.energy_regeneration = (BYTE)BLAZER_DEGENERATION; StarShipPtr->energy_counter = ENERGY_WAIT; if (StarShipPtr->cur_status_flags & SPECIAL) { ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); /* COMET_ON */ ElementPtr->turn_wait = 0; ElementPtr->thrust_wait = 0; StarShipPtr->RaceDescPtr->characteristics.special_wait = StarShipPtr->RaceDescPtr->characteristics.turn_wait; ElementPtr->mass_points = BLAZER_MASS; StarShipPtr->RaceDescPtr->characteristics.turn_wait = BLAZER_TURN_WAIT; ship_collision_func[WHICH_SIDE(ElementPtr->state_flags)] = ElementPtr->collision_func; ElementPtr->collision_func = blazer_collision; } } if (StarShipPtr->RaceDescPtr->ship_info.energy_level == 0) /* if blazer wasn't able to change back into ship * give it a little more juice to try to get out * of its predicament. */ { DeltaEnergy (ElementPtr, -BLAZER_DEGENERATION); StarShipPtr->energy_counter = 1; } } } static void androsynth_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; ELEMENT_FLAGS cur_status_flags; GetElementStarShip (ElementPtr, &StarShipPtr); cur_status_flags = StarShipPtr->cur_status_flags; if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) { if (cur_status_flags & SPECIAL) { if (StarShipPtr->RaceDescPtr->ship_info.energy_level < SPECIAL_ENERGY_COST) DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST); /* so text will flash */ else { cur_status_flags &= ~WEAPON; ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; ElementPtr->next.image.frame = SetEquFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], ElementPtr->next.image.frame); ElementPtr->state_flags |= CHANGING; } } } else { cur_status_flags &= ~(THRUST | WEAPON | SPECIAL); /* protection against vux */ if (StarShipPtr->RaceDescPtr->characteristics.turn_wait > BLAZER_TURN_WAIT) { StarShipPtr->RaceDescPtr->characteristics.special_wait += StarShipPtr->RaceDescPtr->characteristics.turn_wait - BLAZER_TURN_WAIT; StarShipPtr->RaceDescPtr->characteristics.turn_wait = BLAZER_TURN_WAIT; } if (StarShipPtr->RaceDescPtr->ship_info.energy_level == 0) { ZeroVelocityComponents (&ElementPtr->velocity); cur_status_flags &= ~(LEFT | RIGHT | SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); StarShipPtr->RaceDescPtr->characteristics.turn_wait = StarShipPtr->RaceDescPtr->characteristics.special_wait; StarShipPtr->RaceDescPtr->characteristics.energy_regeneration = ENERGY_REGENERATION; ElementPtr->mass_points = SHIP_MASS; ElementPtr->collision_func = ship_collision_func[WHICH_SIDE(ElementPtr->state_flags)]; ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; ElementPtr->next.image.frame = SetEquFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], ElementPtr->next.image.frame); ElementPtr->state_flags |= CHANGING; } else { if (ElementPtr->thrust_wait) --ElementPtr->thrust_wait; else { #define BLAZER_THRUST 60 COUNT facing; facing = StarShipPtr->ShipFacing; if (ElementPtr->turn_wait == 0 && (cur_status_flags & (LEFT | RIGHT))) { if (cur_status_flags & LEFT) --facing; else ++facing; } SetVelocityVector (&ElementPtr->velocity, BLAZER_THRUST, NORMALIZE_FACING (facing)); cur_status_flags |= SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED; } } } StarShipPtr->cur_status_flags = cur_status_flags; } RACE_DESCPTR init_androsynth (void) { RACE_DESCPTR RaceDescPtr; androsynth_desc.preprocess_func = androsynth_preprocess; androsynth_desc.postprocess_func = androsynth_postprocess; androsynth_desc.init_weapon_func = initialize_bubble; androsynth_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) androsynth_intelligence; RaceDescPtr = &androsynth_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/androsyn/isndres.h0000600000175000017500000000005510543202064020406 0ustar joeyjoey#define ANDROSYNTH_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/androsyn/istrtab.h0000600000175000017500000000005610543202064020410 0ustar joeyjoey#define ANDROSYNTH_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/androsyn/imusicre.h0000600000175000017500000000005610543202064020560 0ustar joeyjoey#define ANDROSYNTH_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/androsyn/icode.h0000600000175000017500000000004610543202064020022 0ustar joeyjoey#define ANDROSYNTH_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/androsyn/Makeinfo0000600000175000017500000000003010543202064020233 0ustar joeyjoeyuqm_CFILES="androsyn.c" uqm-0.6.2/sc2/src/sc2code/ships/androsyn/respkg.h0000600000175000017500000000007510543202064020234 0ustar joeyjoeyenum { ANDROSYNTH_CODE_PACKAGE = 1, ANDROSYNTH_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/androsyn/resinst.h0000600000175000017500000000015010543202064020422 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/androsyn/androsyn.res0000600000175000017500000000162010543202064021135 0ustar joeyjoeyINCLUDE ../star3do.typ PATH androsyn PACKAGE ANDROSYNTH_CODE_PACKAGE androsyn.shp CODE ANDROSYNTH_CODE androsyn.cod GFXRES ANDROSYNTH_ICON_MASK_PMAP_ANIM andicons.ani GFXRES ANDROSYNTH_MICON_MASK_PMAP_ANIM andmicon.ani STRTAB ANDROSYNTH_RACE_STRINGS andtext.txt PACKAGE ANDROSYNTH_PACKAGE androsyn.shp GFXRES ANDROSYNTH_BIG_MASK_PMAP_ANIM androsyn.big GFXRES ANDROSYNTH_MED_MASK_PMAP_ANIM androsyn.med GFXRES ANDROSYNTH_SML_MASK_PMAP_ANIM androsyn.sml GFXRES BUBBLE_BIG_MASK_PMAP_ANIM bubble.big GFXRES BUBBLE_MED_MASK_PMAP_ANIM bubble.med GFXRES BUBBLE_SML_MASK_PMAP_ANIM bubble.sml GFXRES BLAZER_BIG_MASK_PMAP_ANIM blazer.big GFXRES BLAZER_MED_MASK_PMAP_ANIM blazer.med GFXRES BLAZER_SML_MASK_PMAP_ANIM blazer.sml GFXRES ANDROSYNTH_CAPT_MASK_PMAP_ANIM andcap.ani SNDRES ANDROSYNTH_SHIP_SOUNDS andsound.snd MUSICRES ANDROSYNTH_VICTORY_SONG andditty.mod uqm-0.6.2/sc2/src/sc2code/ships/blackurq/0000755000175000017500000000000010552600274016552 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/blackurq/restypes.h0000600000175000017500000000024110543202067020564 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/blackurq/igfxres.h0000600000175000017500000000106110543202067020356 0ustar joeyjoey#define KOHR_AH_ICON_MASK_PMAP_ANIM 0x00200002L #define KOHR_AH_MICON_MASK_PMAP_ANIM 0x00200102L #define KOHR_AH_BIG_MASK_PMAP_ANIM 0x00400202L #define KOHR_AH_MED_MASK_PMAP_ANIM 0x00400302L #define KOHR_AH_SML_MASK_PMAP_ANIM 0x00400402L #define BUZZSAW_BIG_MASK_PMAP_ANIM 0x00400502L #define BUZZSAW_MED_MASK_PMAP_ANIM 0x00400602L #define BUZZSAW_SML_MASK_PMAP_ANIM 0x00400702L #define GAS_BIG_MASK_PMAP_ANIM 0x00400802L #define GAS_MED_MASK_PMAP_ANIM 0x00400902L #define GAS_SML_MASK_PMAP_ANIM 0x00400a02L #define KOHR_AH_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/blackurq/blackurq.c0000600000175000017500000003427610543202067020524 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/blackurq/resinst.h" #include "globdata.h" #define MAX_CREW MAX_CREW_SIZE #define MAX_ENERGY MAX_ENERGY_SIZE #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 6 #define SPECIAL_ENERGY_COST (MAX_ENERGY_SIZE / 2) #define ENERGY_WAIT 4 #define MAX_THRUST 30 #define THRUST_INCREMENT 6 #define TURN_WAIT 4 #define THRUST_WAIT 6 #define WEAPON_WAIT 6 #define SPECIAL_WAIT 9 #define SHIP_MASS 10 #define MISSILE_SPEED 64 #define MISSILE_LIFE 64 /* actually, it's as long as you * hold the button down. */ static RACE_DESC black_urquan_desc = { { FIRES_FORE, 30, /* Super Melee cost */ 2666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 6000, 6250, }, (STRING)KOHR_AH_RACE_STRINGS, (FRAME)KOHR_AH_ICON_MASK_PMAP_ANIM, (FRAME)KOHR_AH_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)KOHR_AH_BIG_MASK_PMAP_ANIM, (FRAME)KOHR_AH_MED_MASK_PMAP_ANIM, (FRAME)KOHR_AH_SML_MASK_PMAP_ANIM, }, { (FRAME)BUZZSAW_BIG_MASK_PMAP_ANIM, (FRAME)BUZZSAW_MED_MASK_PMAP_ANIM, (FRAME)BUZZSAW_SML_MASK_PMAP_ANIM, }, { (FRAME)GAS_BIG_MASK_PMAP_ANIM, (FRAME)GAS_MED_MASK_PMAP_ANIM, (FRAME)GAS_SML_MASK_PMAP_ANIM, }, { (FRAME)KOHR_AH_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)KOHR_AH_VICTORY_SONG, (SOUND)KOHR_AH_SHIP_SOUNDS, }, { 0, CLOSE_RANGE_WEAPON, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define SAW_RATE 0 #define MAX_SAWS 8 static void spin_preprocess (PELEMENT ElementPtr) { ELEMENTPTR ShipPtr; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ShipPtr); if (ShipPtr->crew_level && ++StarShipPtr->RaceDescPtr->characteristics.special_wait > MAX_SAWS) { ElementPtr->life_span = 1; ElementPtr->state_flags |= DISAPPEARING; } else { ++ElementPtr->life_span; if (ElementPtr->turn_wait) --ElementPtr->turn_wait; else { #define LAST_SPIN_INDEX 1 if (GetFrameIndex ( ElementPtr->current.image.frame ) < LAST_SPIN_INDEX) ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); else ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, 0); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = SAW_RATE; } } UnlockElement (StarShipPtr->hShip); } #define TRACK_WAIT 4 static void buzztrack_preprocess (PELEMENT ElementPtr) { if (ElementPtr->thrust_wait) --ElementPtr->thrust_wait; else { COUNT facing = 0; if (ElementPtr->hTarget == 0 && TrackShip (ElementPtr, &facing) < 0) { ZeroVelocityComponents (&ElementPtr->velocity); } else { #define ACTIVATE_RANGE 224 /* Originally SPACE_WIDTH */ SIZE delta_x, delta_y; ELEMENTPTR eptr; LockElement (ElementPtr->hTarget, &eptr); delta_x = eptr->current.location.x - ElementPtr->current.location.x; delta_y = eptr->current.location.y - ElementPtr->current.location.y; UnlockElement (ElementPtr->hTarget); delta_x = WRAP_DELTA_X (delta_x); delta_y = WRAP_DELTA_Y (delta_y); facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) ); if (delta_x < 0) delta_x = -delta_x; if (delta_y < 0) delta_y = -delta_y; delta_x = WORLD_TO_DISPLAY (delta_x); delta_y = WORLD_TO_DISPLAY (delta_y); if (delta_x >= ACTIVATE_RANGE || delta_y >= ACTIVATE_RANGE || (DWORD)((UWORD)delta_x * delta_x) + (DWORD)((UWORD)delta_y * delta_y) >= (DWORD)ACTIVATE_RANGE * ACTIVATE_RANGE) { ZeroVelocityComponents (&ElementPtr->velocity); } else { ElementPtr->thrust_wait = TRACK_WAIT; SetVelocityVector (&ElementPtr->velocity, DISPLAY_TO_WORLD (2), facing); } } } spin_preprocess (ElementPtr); } static void decelerate_preprocess (PELEMENT ElementPtr) { SIZE dx, dy; GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); dx /= 2; dy /= 2; SetVelocityComponents (&ElementPtr->velocity, dx, dy); if (dx == 0 && dy == 0) { ElementPtr->preprocess_func = buzztrack_preprocess; } spin_preprocess (ElementPtr); } static void splinter_preprocess (PELEMENT ElementPtr) { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; } static void buzzsaw_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if (ElementPtr0->state_flags & DISAPPEARING) { ElementPtr0->state_flags &= ~DISAPPEARING; ElementPtr0->state_flags |= NONSOLID | CHANGING; ElementPtr0->life_span = 5; ElementPtr0->next.image.frame = SetAbsFrameIndex (ElementPtr0->current.image.frame, 2); ElementPtr0->preprocess_func = splinter_preprocess; } } static void buzzsaw_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (!(StarShipPtr->cur_status_flags & WEAPON)) { ElementPtr->life_span >>= 1; ElementPtr->preprocess_func = decelerate_preprocess; } spin_preprocess (ElementPtr); } static void buzzsaw_postprocess (PELEMENT ElementPtr) { HELEMENT hElement; ElementPtr->postprocess_func = 0; hElement = AllocElement (); if (hElement) { COUNT primIndex; ELEMENTPTR ListElementPtr; STARSHIPPTR StarShipPtr; LockElement (hElement, &ListElementPtr); primIndex = ListElementPtr->PrimIndex; *ListElementPtr = *ElementPtr; ListElementPtr->PrimIndex = primIndex; (GLOBAL (DisplayArray))[primIndex] = (GLOBAL (DisplayArray))[ElementPtr->PrimIndex]; ListElementPtr->current = ListElementPtr->next; InitIntersectStartPoint (ListElementPtr); InitIntersectEndPoint (ListElementPtr); ListElementPtr->state_flags = (ListElementPtr->state_flags & ~(PRE_PROCESS | CHANGING | APPEARING)) | POST_PROCESS; UnlockElement (hElement); GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ListElementPtr); InsertElement (hElement, GetSuccElement (ListElementPtr)); UnlockElement (StarShipPtr->hShip); ElementPtr->life_span = 0; } } static COUNT initialize_buzzsaw (PELEMENT ShipPtr, HELEMENT SawArray[]) { #define MISSILE_HITS 10 #define MISSILE_DAMAGE 4 #define MISSILE_OFFSET 9 #define KOHR_AH_OFFSET 28 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = KOHR_AH_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = buzzsaw_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; SawArray[0] = initialize_missile (&MissileBlock); if (SawArray[0]) { ELEMENTPTR SawPtr; LockElement (SawArray[0], &SawPtr); SawPtr->turn_wait = SAW_RATE; SawPtr->thrust_wait = 0; SawPtr->postprocess_func = buzzsaw_postprocess; SawPtr->collision_func = buzzsaw_collision; UnlockElement (SawArray[0]); } return (1); } static void black_urquan_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { PEVALUATE_DESC lpEvalDesc; STARSHIPPTR StarShipPtr; lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE && (lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT) && lpEvalDesc->which_turn <= 8) lpEvalDesc->MoveState = PURSUE; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->ship_input_state &= ~SPECIAL; if (StarShipPtr->special_counter == 0 && StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST && lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 8) StarShipPtr->ship_input_state |= SPECIAL; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { #define FRAGMENT_LIFE 10 #define FRAGMENT_SPEED MISSILE_SPEED #define FRAGMENT_RANGE (FRAGMENT_LIFE * FRAGMENT_SPEED) HELEMENT h, hNext; ELEMENTPTR BuzzSawPtr; h = (StarShipPtr->old_status_flags & WEAPON) ? GetSuccElement (ShipPtr) : (HELEMENT)0; for (; h; h = hNext) { LockElement (h, &BuzzSawPtr); hNext = GetSuccElement (BuzzSawPtr); if (!(BuzzSawPtr->state_flags & NONSOLID) && BuzzSawPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.weapon && BuzzSawPtr->life_span > MISSILE_LIFE * 3 / 4 && (BuzzSawPtr->state_flags & (GOOD_GUY | BAD_GUY)) == (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY))) { { //COUNT which_turn; if (!PlotIntercept (BuzzSawPtr, lpEvalDesc->ObjectPtr, BuzzSawPtr->life_span, FRAGMENT_RANGE / 2)) StarShipPtr->ship_input_state &= ~WEAPON; else if (StarShipPtr->weapon_counter == 0) StarShipPtr->ship_input_state |= WEAPON; UnlockElement (h); break; } hNext = 0; } UnlockElement (h); } if (h == 0) { if (StarShipPtr->old_status_flags & WEAPON) StarShipPtr->ship_input_state &= ~WEAPON; else if (StarShipPtr->weapon_counter == 0 && ship_weapons (ShipPtr, lpEvalDesc->ObjectPtr, FRAGMENT_RANGE / 2)) StarShipPtr->ship_input_state |= WEAPON; if (StarShipPtr->special_counter == 0 && !(StarShipPtr->ship_input_state & WEAPON) && lpEvalDesc->which_turn <= 8 && (StarShipPtr->ship_input_state & (LEFT | RIGHT)) && StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST) StarShipPtr->ship_input_state |= SPECIAL; } } } #define GAS_RATE 2 static void gas_cloud_preprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait) --ElementPtr->turn_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = GAS_RATE; } } #define GAS_DAMAGE 3 static void gas_cloud_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if (ElementPtr1->state_flags & PLAYER_SHIP) ElementPtr0->mass_points = GAS_DAMAGE; else ElementPtr0->mass_points = 50; weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); } static void spawn_gas_cloud (PELEMENT ElementPtr) { #define GAS_SPEED 16 #define GAS_HITS 100 #define GAS_OFFSET 2 #define NUM_GAS_CLOUDS 16 SIZE dx, dy; STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ElementPtr, &StarShipPtr); MissileBlock.cx = ElementPtr->next.location.x; MissileBlock.cy = ElementPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; MissileBlock.index = 0; MissileBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = 20; MissileBlock.speed = GAS_SPEED; MissileBlock.hit_points = GAS_HITS; MissileBlock.damage = GAS_DAMAGE; MissileBlock.life = GetFrameCount (MissileBlock.farray[0]) * (GAS_RATE + 1) - 1; MissileBlock.preprocess_func = gas_cloud_preprocess; MissileBlock.blast_offs = GAS_OFFSET; GetCurrentVelocityComponents (&ElementPtr->velocity, &dx, &dy); for (MissileBlock.face = 0; MissileBlock.face < ANGLE_TO_FACING (FULL_CIRCLE); MissileBlock.face += (ANGLE_TO_FACING (FULL_CIRCLE) / NUM_GAS_CLOUDS)) { HELEMENT hGasCloud; hGasCloud = initialize_missile (&MissileBlock); if (hGasCloud) { ELEMENTPTR GasCloudPtr; LockElement (hGasCloud, &GasCloudPtr); SetElementStarShip (GasCloudPtr, StarShipPtr); GasCloudPtr->hTarget = 0; GasCloudPtr->turn_wait = GAS_RATE - 1; GasCloudPtr->collision_func = gas_cloud_collision; DeltaVelocityComponents (&GasCloudPtr->velocity, dx, dy); UnlockElement (hGasCloud); PutElement (hGasCloud); } } } static void black_urquan_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { spawn_gas_cloud (ElementPtr); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); StarShipPtr->special_counter = SPECIAL_WAIT; } } static void black_urquan_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); /* no spinning disks */ StarShipPtr->RaceDescPtr->characteristics.special_wait = 0; if (StarShipPtr->weapon_counter == 0 && (StarShipPtr->cur_status_flags & StarShipPtr->old_status_flags & WEAPON)) ++StarShipPtr->weapon_counter; } RACE_DESCPTR init_black_urquan (void) { RACE_DESCPTR RaceDescPtr; black_urquan_desc.preprocess_func = black_urquan_preprocess; black_urquan_desc.postprocess_func = black_urquan_postprocess; black_urquan_desc.init_weapon_func = initialize_buzzsaw; black_urquan_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) black_urquan_intelligence; RaceDescPtr = &black_urquan_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/blackurq/isndres.h0000600000175000017500000000005210543202067020355 0ustar joeyjoey#define KOHR_AH_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/blackurq/istrtab.h0000600000175000017500000000005310543202067020357 0ustar joeyjoey#define KOHR_AH_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/blackurq/imusicre.h0000600000175000017500000000005310543202067020527 0ustar joeyjoey#define KOHR_AH_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/blackurq/icode.h0000600000175000017500000000004310543202067017771 0ustar joeyjoey#define KOHR_AH_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/blackurq/Makeinfo0000600000175000017500000000003010543202067020205 0ustar joeyjoeyuqm_CFILES="blackurq.c" uqm-0.6.2/sc2/src/sc2code/ships/blackurq/blackurq.res0000600000175000017500000000153610543202067021064 0ustar joeyjoeyINCLUDE ../star3do.typ PATH blackurq PACKAGE KOHR_AH_CODE_PACKAGE blackurq.shp CODE KOHR_AH_CODE blackurq.cod GFXRES KOHR_AH_ICON_MASK_PMAP_ANIM blaicons.ani GFXRES KOHR_AH_MICON_MASK_PMAP_ANIM blamicon.ani STRTAB KOHR_AH_RACE_STRINGS blatext.txt PACKAGE KOHR_AH_PACKAGE blackurq.shp GFXRES KOHR_AH_BIG_MASK_PMAP_ANIM blackurq.big GFXRES KOHR_AH_MED_MASK_PMAP_ANIM blackurq.med GFXRES KOHR_AH_SML_MASK_PMAP_ANIM blackurq.sml GFXRES BUZZSAW_BIG_MASK_PMAP_ANIM buzbig.ani GFXRES BUZZSAW_MED_MASK_PMAP_ANIM buzmed.ani GFXRES BUZZSAW_SML_MASK_PMAP_ANIM buzsml.ani GFXRES GAS_BIG_MASK_PMAP_ANIM gasbig.ani GFXRES GAS_MED_MASK_PMAP_ANIM gasmed.ani GFXRES GAS_SML_MASK_PMAP_ANIM gassml.ani GFXRES KOHR_AH_CAPTAIN_MASK_PMAP_ANIM blacap.ani SNDRES KOHR_AH_SHIP_SOUNDS blasound.snd MUSICRES KOHR_AH_VICTORY_SONG bladitty.mod uqm-0.6.2/sc2/src/sc2code/ships/blackurq/respkg.h0000600000175000017500000000006710543202067020207 0ustar joeyjoeyenum { KOHR_AH_CODE_PACKAGE = 1, KOHR_AH_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/blackurq/resinst.h0000600000175000017500000000015010543202067020374 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/human/0000755000175000017500000000000010552600274016056 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/human/human.res0000600000175000017500000000125210543202071017662 0ustar joeyjoeyINCLUDE ../star3do.typ PATH human PACKAGE HUMAN_CODE_PACKAGE human.shp CODE HUMAN_CODE human.cod GFXRES HUMAN_ICON_MASK_PMAP_ANIM humicons.ani GFXRES HUMAN_MICON_MASK_PMAP_ANIM hummicon.ani STRTAB HUMAN_RACE_STRINGS humtext.txt PACKAGE HUMAN_PACKAGE human.shp GFXRES HUMAN_BIG_MASK_PMAP_ANIM human.big GFXRES HUMAN_MED_MASK_PMAP_ANIM human.med GFXRES HUMAN_SML_MASK_PMAP_ANIM human.sml GFXRES SATURN_BIG_MASK_PMAP_ANIM saturn.big GFXRES SATURN_MED_MASK_PMAP_ANIM saturn.med GFXRES SATURN_SML_MASK_PMAP_ANIM saturn.sml GFXRES HUMAN_CAPTAIN_MASK_PMAP_ANIM humcap.ani SNDRES HUMAN_SHIP_SOUNDS humsound.snd MUSICRES HUMAN_VICTORY_SONG humditty.mod uqm-0.6.2/sc2/src/sc2code/ships/human/restypes.h0000600000175000017500000000024110543202071020063 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/human/igfxres.h0000600000175000017500000000064110543202071017660 0ustar joeyjoey#define HUMAN_ICON_MASK_PMAP_ANIM 0x00200002L #define HUMAN_MICON_MASK_PMAP_ANIM 0x00200102L #define HUMAN_BIG_MASK_PMAP_ANIM 0x00400202L #define HUMAN_MED_MASK_PMAP_ANIM 0x00400302L #define HUMAN_SML_MASK_PMAP_ANIM 0x00400402L #define SATURN_BIG_MASK_PMAP_ANIM 0x00400502L #define SATURN_MED_MASK_PMAP_ANIM 0x00400602L #define SATURN_SML_MASK_PMAP_ANIM 0x00400702L #define HUMAN_CAPTAIN_MASK_PMAP_ANIM 0x00400802L uqm-0.6.2/sc2/src/sc2code/ships/human/human.c0000600000175000017500000002146310543202071017321 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/human/resinst.h" #include "colors.h" #include "globdata.h" #define MAX_CREW 18 #define MAX_ENERGY 18 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 9 #define SPECIAL_ENERGY_COST 4 #define ENERGY_WAIT 8 #define MAX_THRUST /* DISPLAY_TO_WORLD (6) */ 24 #define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 3 #define TURN_WAIT 1 #define THRUST_WAIT 4 #define WEAPON_WAIT 10 #define SPECIAL_WAIT 9 #define SHIP_MASS 6 #define MISSILE_LIFE 60 #define MIN_MISSILE_SPEED DISPLAY_TO_WORLD (10) #define MAX_MISSILE_SPEED DISPLAY_TO_WORLD (20) static RACE_DESC human_desc = { { FIRES_FORE | SEEKING_WEAPON | POINT_DEFENSE, 11, /* Super Melee cost */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 1752, 1450, }, (STRING)HUMAN_RACE_STRINGS, (FRAME)HUMAN_ICON_MASK_PMAP_ANIM, (FRAME)HUMAN_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)HUMAN_BIG_MASK_PMAP_ANIM, (FRAME)HUMAN_MED_MASK_PMAP_ANIM, (FRAME)HUMAN_SML_MASK_PMAP_ANIM, }, { (FRAME)SATURN_BIG_MASK_PMAP_ANIM, (FRAME)SATURN_MED_MASK_PMAP_ANIM, (FRAME)SATURN_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)HUMAN_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)HUMAN_VICTORY_SONG, (SOUND)HUMAN_SHIP_SOUNDS, }, { 0, LONG_RANGE_WEAPON, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define MISSILE_SPEED (MAX_THRUST >= MIN_MISSILE_SPEED ? \ MAX_THRUST : MIN_MISSILE_SPEED) #define TRACK_WAIT 3 static void nuke_preprocess (PELEMENT ElementPtr) { COUNT facing; facing = GetFrameIndex (ElementPtr->next.image.frame); if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { if (TrackShip (ElementPtr, &facing) > 0) { ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->next.image.frame, facing); ElementPtr->state_flags |= CHANGING; } ElementPtr->turn_wait = TRACK_WAIT; } { SIZE speed; #define THRUST_SCALE DISPLAY_TO_WORLD (1) if ((speed = MISSILE_SPEED + ((MISSILE_LIFE - ElementPtr->life_span) * THRUST_SCALE)) > MAX_MISSILE_SPEED) speed = MAX_MISSILE_SPEED; SetVelocityVector (&ElementPtr->velocity, speed, facing); } } static void spawn_point_defense (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (ElementPtr->state_flags & PLAYER_SHIP) { HELEMENT hDefense; hDefense = AllocElement (); if (hDefense) { ELEMENTPTR DefensePtr; LockElement (hDefense, &DefensePtr); DefensePtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); { DefensePtr->death_func = spawn_point_defense; } GetElementStarShip (ElementPtr, &StarShipPtr); SetElementStarShip (DefensePtr, StarShipPtr); UnlockElement (hDefense); PutElement (hDefense); } } else { BOOLEAN PaidFor; HELEMENT hObject, hNextObject; ELEMENTPTR ShipPtr; PaidFor = FALSE; LockElement (StarShipPtr->hShip, &ShipPtr); for (hObject = GetTailElement (); hObject; hObject = hNextObject) { ELEMENTPTR ObjectPtr; LockElement (hObject, &ObjectPtr); hNextObject = GetPredElement (ObjectPtr); if (ObjectPtr != ShipPtr && CollidingElement (ObjectPtr) && !OBJECT_CLOAKED (ObjectPtr)) { #define LASER_RANGE (UWORD)100 SIZE delta_x, delta_y; delta_x = ObjectPtr->next.location.x - ShipPtr->next.location.x; delta_y = ObjectPtr->next.location.y - ShipPtr->next.location.y; if (delta_x < 0) delta_x = -delta_x; if (delta_y < 0) delta_y = -delta_y; delta_x = WORLD_TO_DISPLAY (delta_x); delta_y = WORLD_TO_DISPLAY (delta_y); if ((UWORD)delta_x <= LASER_RANGE && (UWORD)delta_y <= LASER_RANGE && (UWORD)delta_x * (UWORD)delta_x + (UWORD)delta_y * (UWORD)delta_y <= LASER_RANGE * LASER_RANGE) { HELEMENT hPointDefense; LASER_BLOCK LaserBlock; if (!PaidFor) { if (!DeltaEnergy (ShipPtr, -SPECIAL_ENERGY_COST)) break; ProcessSound (SetAbsSoundIndex ( /* POINT_DEFENSE_LASER */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; PaidFor = TRUE; } LaserBlock.cx = ShipPtr->next.location.x; LaserBlock.cy = ShipPtr->next.location.y; LaserBlock.face = 0; LaserBlock.ex = ObjectPtr->next.location.x - ShipPtr->next.location.x; LaserBlock.ey = ObjectPtr->next.location.y - ShipPtr->next.location.y; LaserBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; LaserBlock.pixoffs = 0; LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F); hPointDefense = initialize_laser (&LaserBlock); if (hPointDefense) { ELEMENTPTR PDPtr; LockElement (hPointDefense, &PDPtr); SetElementStarShip (PDPtr, StarShipPtr); PDPtr->hTarget = 0; UnlockElement (hPointDefense); PutElement (hPointDefense); } } } UnlockElement (hObject); } UnlockElement (StarShipPtr->hShip); } } static COUNT initialize_nuke (PELEMENT ShipPtr, HELEMENT NukeArray[]) { #define HUMAN_OFFSET 42 #define MISSILE_DAMAGE 4 #define MISSILE_HITS 1 #define NUKE_OFFSET 8 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = ShipPtr->state_flags & (GOOD_GUY | BAD_GUY); MissileBlock.pixoffs = HUMAN_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = nuke_preprocess; MissileBlock.blast_offs = NUKE_OFFSET; NukeArray[0] = initialize_missile (&MissileBlock); if (NukeArray[0]) { ELEMENTPTR NukePtr; LockElement (NukeArray[0], &NukePtr); NukePtr->turn_wait = TRACK_WAIT; UnlockElement (NukeArray[0]); } return (1); } static void human_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->special_counter == 0 && ((ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr != NULL_PTR && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 2) || (ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr != NULL_PTR && ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn <= 4))) StarShipPtr->ship_input_state |= SPECIAL; else StarShipPtr->ship_input_state &= ~SPECIAL; ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr = NULL_PTR; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (StarShipPtr->weapon_counter == 0) { if (ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr && (!(StarShipPtr->ship_input_state & (LEFT | RIGHT /* | THRUST */)) || ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn <= 12)) StarShipPtr->ship_input_state |= WEAPON; } } static void human_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0) { spawn_point_defense (ElementPtr); } } RACE_DESCPTR init_human (void) { RACE_DESCPTR RaceDescPtr; human_desc.postprocess_func = human_postprocess; human_desc.init_weapon_func = initialize_nuke; human_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) human_intelligence; RaceDescPtr = &human_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/human/isndres.h0000600000175000017500000000005010543202071017652 0ustar joeyjoey#define HUMAN_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/human/istrtab.h0000600000175000017500000000005110543202071017654 0ustar joeyjoey#define HUMAN_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/human/imusicre.h0000600000175000017500000000005110543202071020024 0ustar joeyjoey#define HUMAN_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/human/icode.h0000600000175000017500000000004110543202071017266 0ustar joeyjoey#define HUMAN_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/human/Makeinfo0000600000175000017500000000002510543202071017510 0ustar joeyjoeyuqm_CFILES="human.c" uqm-0.6.2/sc2/src/sc2code/ships/human/respkg.h0000600000175000017500000000006310543202071017502 0ustar joeyjoeyenum { HUMAN_CODE_PACKAGE = 1, HUMAN_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/human/resinst.h0000600000175000017500000000015010543202071017673 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/shofixti/0000755000175000017500000000000010552600274016603 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/shofixti/restypes.h0000600000175000017500000000024110543202065020613 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/shofixti/igfxres.h0000600000175000017500000000135610543202066020415 0ustar joeyjoey#define SHOFIXTI_ICON_MASK_PMAP_ANIM 0x00200002L #define SHOFIXTI_MICON_MASK_PMAP_ANIM 0x00200102L #define SHOFIXTI_BIG_MASK_PMAP_ANIM 0x00400202L #define SHOFIXTI_MED_MASK_PMAP_ANIM 0x00400302L #define SHOFIXTI_SML_MASK_PMAP_ANIM 0x00400402L #define DESTRUCT_BIG_MASK_ANIM 0x00400502L #define DESTRUCT_MED_MASK_ANIM 0x00400602L #define DESTRUCT_SML_MASK_ANIM 0x00400702L #define SHOFIXTI_CAPTAIN_MASK_PMAP_ANIM 0x00400802L #define OLDSHOF_BIG_MASK_PMAP_ANIM 0x00600902L #define OLDSHOF_MED_MASK_PMAP_ANIM 0x00600a02L #define OLDSHOF_SML_MASK_PMAP_ANIM 0x00600b02L #define OLDSHOF_CAPTAIN_MASK_PMAP_ANIM 0x00600c02L #define DART_BIG_MASK_PMAP_ANIM 0x00800d02L #define DART_MED_MASK_PMAP_ANIM 0x00800e02L #define DART_SML_MASK_PMAP_ANIM 0x00800f02L uqm-0.6.2/sc2/src/sc2code/ships/shofixti/isndres.h0000600000175000017500000000005310543202066020406 0ustar joeyjoey#define SHOFIXTI_SHIP_SOUNDS 0x00800005L uqm-0.6.2/sc2/src/sc2code/ships/shofixti/istrtab.h0000600000175000017500000000005410543202066020410 0ustar joeyjoey#define SHOFIXTI_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/shofixti/imusicre.h0000600000175000017500000000005410543202065020557 0ustar joeyjoey#define SHOFIXTI_VICTORY_SONG 0x00800006L uqm-0.6.2/sc2/src/sc2code/ships/shofixti/icode.h0000600000175000017500000000004410543202066020022 0ustar joeyjoey#define SHOFIXTI_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/shofixti/shofixti.c0000600000175000017500000003060610543202066020576 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/shofixti/resinst.h" #include "globdata.h" #include "libs/mathlib.h" #define MAX_CREW 6 #define MAX_ENERGY 4 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 1 #define SPECIAL_ENERGY_COST 0 #define ENERGY_WAIT 9 #define MAX_THRUST 35 #define THRUST_INCREMENT 5 #define TURN_WAIT 1 #define THRUST_WAIT 0 #define WEAPON_WAIT 3 #define SPECIAL_WAIT 0 #define SHIP_MASS 1 #define MISSILE_SPEED DISPLAY_TO_WORLD (24) #define MISSILE_LIFE 10 static RACE_DESC shofixti_desc = { { FIRES_FORE, 5, /* Super Melee cost */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 0, 0, }, (STRING)SHOFIXTI_RACE_STRINGS, (FRAME)SHOFIXTI_ICON_MASK_PMAP_ANIM, (FRAME)SHOFIXTI_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)SHOFIXTI_BIG_MASK_PMAP_ANIM, (FRAME)SHOFIXTI_MED_MASK_PMAP_ANIM, (FRAME)SHOFIXTI_SML_MASK_PMAP_ANIM, }, { (FRAME)DART_BIG_MASK_PMAP_ANIM, (FRAME)DART_MED_MASK_PMAP_ANIM, (FRAME)DART_SML_MASK_PMAP_ANIM, }, { (FRAME)DESTRUCT_BIG_MASK_ANIM, (FRAME)DESTRUCT_MED_MASK_ANIM, (FRAME)DESTRUCT_SML_MASK_ANIM, }, { (FRAME)SHOFIXTI_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)SHOFIXTI_VICTORY_SONG, (SOUND)SHOFIXTI_SHIP_SOUNDS, }, { 0, MISSILE_SPEED * MISSILE_LIFE, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static COUNT initialize_standard_missile (PELEMENT ShipPtr, HELEMENT MissileArray[]) { #define SHOFIXTI_OFFSET 15 #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 1 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = SHOFIXTI_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; MissileArray[0] = initialize_missile (&MissileBlock); return (1); } static void destruct_preprocess (PELEMENT ElementPtr) { #define DESTRUCT_SWITCH ((NUM_EXPLOSION_FRAMES * 3) - 3) PPRIMITIVE lpPrim; lpPrim = &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex]; ElementPtr->state_flags |= CHANGING; if (ElementPtr->life_span > DESTRUCT_SWITCH) { SetPrimType (lpPrim, STAMPFILL_PRIM); if (ElementPtr->life_span == DESTRUCT_SWITCH + 2) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E)); else SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); } else if (ElementPtr->life_span < DESTRUCT_SWITCH) { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); if (GetPrimColor (lpPrim) == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E)); else if (GetPrimColor (lpPrim) == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C)); else if (GetPrimColor (lpPrim) == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x14, 0x0A, 0x00), 0x06)); else if (GetPrimColor (lpPrim) == BUILD_COLOR (MAKE_RGB15 (0x14, 0x0A, 0x00), 0x06)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04)); } else { HELEMENT hDestruct; SetPrimType (lpPrim, NO_PRIM); ElementPtr->preprocess_func = NULL_PTR; hDestruct = AllocElement (); if (hDestruct) { ELEMENTPTR DestructPtr; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); PutElement (hDestruct); LockElement (hDestruct, &DestructPtr); SetElementStarShip (DestructPtr, StarShipPtr); DestructPtr->hit_points = DestructPtr->mass_points = 0; DestructPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; DestructPtr->life_span = (NUM_EXPLOSION_FRAMES - 3) - 1; SetPrimType ( &(GLOBAL (DisplayArray))[DestructPtr->PrimIndex], STAMPFILL_PRIM ); SetPrimColor ( &(GLOBAL (DisplayArray))[DestructPtr->PrimIndex], BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) ); DestructPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; DestructPtr->current.image.frame = StarShipPtr->RaceDescPtr->ship_data.special[0]; DestructPtr->current.location = ElementPtr->current.location; { DestructPtr->preprocess_func = destruct_preprocess; } DestructPtr->postprocess_func = DestructPtr->death_func = NULL_PTR; ZeroVelocityComponents (&DestructPtr->velocity); UnlockElement (hDestruct); } } } /* In order to detect any Orz Marines that have boarded the ship when it self-destructs, we'll need to see these Orz functions */ void intruder_preprocess (PELEMENT); void marine_collision (PELEMENT, PPOINT, PELEMENT, PPOINT); #define ORZ_MARINE(ptr) (ptr->preprocess_func == intruder_preprocess && \ ptr->collision_func == marine_collision) static void self_destruct (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (ElementPtr->state_flags & PLAYER_SHIP) { HELEMENT hDestruct; hDestruct = AllocElement (); if (hDestruct) { ELEMENTPTR DestructPtr; LockElement (hDestruct, &DestructPtr); DestructPtr->state_flags = APPEARING | NONSOLID | FINITE_LIFE | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); DestructPtr->next.location = ElementPtr->next.location; DestructPtr->life_span = 0; DestructPtr->pParent = ElementPtr->pParent; DestructPtr->hTarget = 0; DestructPtr->death_func = self_destruct; UnlockElement (hDestruct); PutElement (hDestruct); } ElementPtr->state_flags |= NONSOLID; ElementPtr->life_span = 0; ElementPtr->preprocess_func = destruct_preprocess; } else { HELEMENT hElement, hNextElement; for (hElement = GetHeadElement (); hElement != 0; hElement = hNextElement) { ELEMENTPTR ObjPtr; LockElement (hElement, &ObjPtr); hNextElement = GetSuccElement (ObjPtr); if (CollidingElement (ObjPtr) || ORZ_MARINE (ObjPtr)) { #define DESTRUCT_RANGE 180 SIZE delta_x, delta_y; DWORD dist; if ((delta_x = ObjPtr->next.location.x - ElementPtr->next.location.x) < 0) delta_x = -delta_x; if ((delta_y = ObjPtr->next.location.y - ElementPtr->next.location.y) < 0) delta_y = -delta_y; delta_x = WORLD_TO_DISPLAY (delta_x); delta_y = WORLD_TO_DISPLAY (delta_y); if (delta_x <= DESTRUCT_RANGE && delta_y <= DESTRUCT_RANGE && (dist = (DWORD)(delta_x * delta_x) + (DWORD)(delta_y * delta_y)) <= (DWORD)(DESTRUCT_RANGE * DESTRUCT_RANGE)) { #define MAX_DESTRUCTION (DESTRUCT_RANGE / 10) SIZE destruction; destruction = ((MAX_DESTRUCTION * (DESTRUCT_RANGE - square_root (dist))) / DESTRUCT_RANGE) + 1; if (ObjPtr->state_flags & PLAYER_SHIP) { if (!DeltaCrew (ObjPtr, -destruction)) ObjPtr->life_span = 0; } else if (!GRAVITY_MASS (ObjPtr->mass_points)) { if ((BYTE)destruction < ObjPtr->hit_points) ObjPtr->hit_points -= (BYTE)destruction; else { ObjPtr->hit_points = 0; ObjPtr->life_span = 0; } } } } UnlockElement (hElement); } } } static void shofixti_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { STARSHIPPTR StarShipPtr; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->special_counter == 0) { if (StarShipPtr->ship_input_state & SPECIAL) StarShipPtr->ship_input_state &= ~SPECIAL; else { PEVALUATE_DESC lpWeaponEvalDesc, lpShipEvalDesc; lpWeaponEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; lpShipEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->RaceDescPtr->ship_data.special[0] && (GetFrameCount (StarShipPtr->RaceDescPtr->ship_data.captain_control.special) - GetFrameIndex (StarShipPtr->RaceDescPtr->ship_data.captain_control.special) > 5 || (lpShipEvalDesc->ObjectPtr != NULL_PTR && lpShipEvalDesc->which_turn <= 4) || (lpWeaponEvalDesc->ObjectPtr != NULL_PTR /* means IMMEDIATE WEAPON */ && (((lpWeaponEvalDesc->ObjectPtr->state_flags & PLAYER_SHIP) && ShipPtr->crew_level == 1) || (PlotIntercept (lpWeaponEvalDesc->ObjectPtr, ShipPtr, 2, 0) && lpWeaponEvalDesc->ObjectPtr->mass_points >= ShipPtr->crew_level && (TFB_Random () & 1)))))) StarShipPtr->ship_input_state |= SPECIAL; } } } static void shofixti_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags ^ StarShipPtr->old_status_flags) & SPECIAL) { StarShipPtr->RaceDescPtr->ship_data.captain_control.special = IncFrameIndex (StarShipPtr->RaceDescPtr->ship_data.captain_control.special); if (GetFrameCount (StarShipPtr->RaceDescPtr->ship_data.captain_control.special) - GetFrameIndex (StarShipPtr->RaceDescPtr->ship_data.captain_control.special) == 3) self_destruct (ElementPtr); } } RACE_DESCPTR init_shofixti (void) { RACE_DESCPTR RaceDescPtr; static RACE_DESC new_shofixti_desc; shofixti_desc.postprocess_func = shofixti_postprocess; shofixti_desc.init_weapon_func = initialize_standard_missile; shofixti_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) shofixti_intelligence; new_shofixti_desc = shofixti_desc; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER && !GET_GAME_STATE (SHOFIXTI_RECRUITED)) { #define NUM_LIMPETS 3 COUNT i; new_shofixti_desc.ship_data.ship[0] = (FRAME)OLDSHOF_BIG_MASK_PMAP_ANIM; new_shofixti_desc.ship_data.ship[1] = (FRAME)OLDSHOF_MED_MASK_PMAP_ANIM; new_shofixti_desc.ship_data.ship[2] = (FRAME)OLDSHOF_SML_MASK_PMAP_ANIM; new_shofixti_desc.ship_data.special[0] = new_shofixti_desc.ship_data.special[1] = new_shofixti_desc.ship_data.special[2] = (FRAME)0; new_shofixti_desc.ship_data.captain_control.background = (FRAME)OLDSHOF_CAPTAIN_MASK_PMAP_ANIM; /* weapon doesn't work as well */ new_shofixti_desc.characteristics.weapon_wait = 10; /* simulate VUX limpets */ for (i = 0; i < NUM_LIMPETS; ++i) { if (++new_shofixti_desc.characteristics.turn_wait == 0) --new_shofixti_desc.characteristics.turn_wait; if (++new_shofixti_desc.characteristics.thrust_wait == 0) --new_shofixti_desc.characteristics.thrust_wait; #define MIN_THRUST_INCREMENT DISPLAY_TO_WORLD (1) if (new_shofixti_desc.characteristics.thrust_increment <= MIN_THRUST_INCREMENT) { new_shofixti_desc.characteristics.max_thrust = new_shofixti_desc.characteristics.thrust_increment << 1; } else { COUNT num_thrusts; num_thrusts = new_shofixti_desc.characteristics.max_thrust / new_shofixti_desc.characteristics.thrust_increment; --new_shofixti_desc.characteristics.thrust_increment; new_shofixti_desc.characteristics.max_thrust = new_shofixti_desc.characteristics.thrust_increment * num_thrusts; } } } RaceDescPtr = &new_shofixti_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/shofixti/Makeinfo0000600000175000017500000000003010543202065020234 0ustar joeyjoeyuqm_CFILES="shofixti.c" uqm-0.6.2/sc2/src/sc2code/ships/shofixti/respkg.h0000600000175000017500000000014510543202065020233 0ustar joeyjoeyenum { SHOFIXTI_CODE_PACKAGE = 1, SHOFIXTI_PACKAGE, OLDSHOF_PACKAGE, SHOFIXTI_SHARED_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/shofixti/shofixti.res0000600000175000017500000000220510543202065021136 0ustar joeyjoeyINCLUDE ../star3do.typ PATH shofixti PACKAGE SHOFIXTI_CODE_PACKAGE shofixti.shp CODE SHOFIXTI_CODE shofixti.cod GFXRES SHOFIXTI_ICON_MASK_PMAP_ANIM shoicons.ani GFXRES SHOFIXTI_MICON_MASK_PMAP_ANIM shomicon.ani STRTAB SHOFIXTI_RACE_STRINGS shotext.txt PACKAGE SHOFIXTI_PACKAGE shofixti.shp GFXRES SHOFIXTI_BIG_MASK_PMAP_ANIM shofixti.big GFXRES SHOFIXTI_MED_MASK_PMAP_ANIM shofixti.med GFXRES SHOFIXTI_SML_MASK_PMAP_ANIM shofixti.sml GFXRES DESTRUCT_BIG_MASK_ANIM destruct.big GFXRES DESTRUCT_MED_MASK_ANIM destruct.med GFXRES DESTRUCT_SML_MASK_ANIM destruct.sml GFXRES SHOFIXTI_CAPTAIN_MASK_PMAP_ANIM shocap.ani PACKAGE OLDSHOF_PACKAGE shofixti.shp GFXRES OLDSHOF_BIG_MASK_PMAP_ANIM oldshof.big GFXRES OLDSHOF_MED_MASK_PMAP_ANIM oldshof.med GFXRES OLDSHOF_SML_MASK_PMAP_ANIM oldshof.sml GFXRES OLDSHOF_CAPTAIN_MASK_PMAP_ANIM oldcap.ani PACKAGE SHOFIXTI_SHARED_PACKAGE shofixti.shp GFXRES DART_BIG_MASK_PMAP_ANIM missile.big GFXRES DART_MED_MASK_PMAP_ANIM missile.med GFXRES DART_SML_MASK_PMAP_ANIM missile.sml SNDRES SHOFIXTI_SHIP_SOUNDS shosound.snd MUSICRES SHOFIXTI_VICTORY_SONG shoditty.mod uqm-0.6.2/sc2/src/sc2code/ships/shofixti/resinst.h0000600000175000017500000000015010543202066020424 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/thradd/0000755000175000017500000000000010552600274016214 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/thradd/thradd.c0000600000175000017500000002550310543202070017613 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/thradd/resinst.h" #include "globdata.h" #define MAX_CREW 8 #define MAX_ENERGY 24 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 2 #define SPECIAL_ENERGY_COST 1 #define ENERGY_WAIT 6 #define MAX_THRUST 28 #define THRUST_INCREMENT 7 #define TURN_WAIT 1 #define THRUST_WAIT 0 #define WEAPON_WAIT 12 #define SPECIAL_WAIT 0 #define SHIP_MASS 7 #define THRADDASH_OFFSET 9 #define MISSILE_SPEED DISPLAY_TO_WORLD (30) #define MISSILE_LIFE 15 static RACE_DESC thraddash_desc = { { FIRES_FORE, 10, /* Super Melee cost */ 833 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 2535, 8358, }, (STRING)THRADDASH_RACE_STRINGS, (FRAME)THRADDASH_ICON_MASK_PMAP_ANIM, (FRAME)THRADDASH_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)THRADDASH_BIG_MASK_PMAP_ANIM, (FRAME)THRADDASH_MED_MASK_PMAP_ANIM, (FRAME)THRADDASH_SML_MASK_PMAP_ANIM, }, { (FRAME)HORN_BIG_MASK_PMAP_ANIM, (FRAME)HORN_MED_MASK_PMAP_ANIM, (FRAME)HORN_SML_MASK_PMAP_ANIM, }, { (FRAME)NAPALM_BIG_MASK_PMAP_ANIM, (FRAME)NAPALM_MED_MASK_PMAP_ANIM, (FRAME)NAPALM_SML_MASK_PMAP_ANIM, }, { (FRAME)THRADDASH_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)THRADDASH_VICTORY_SONG, (SOUND)THRADDASH_SHIP_SOUNDS, }, { 0, (MISSILE_SPEED * MISSILE_LIFE) >> 1, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static void thraddash_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { STARSHIPPTR StarShipPtr; PEVALUATE_DESC lpEvalDesc; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { #define STATIONARY_SPEED WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (4)) SIZE dx, dy; GetCurrentVelocityComponents ( &lpEvalDesc->ObjectPtr->velocity, &dx, &dy ); if (lpEvalDesc->which_turn > 8 || (long)dx * dx + (long)dy * dy <= (long)STATIONARY_SPEED * STATIONARY_SPEED) lpEvalDesc->MoveState = PURSUE; else lpEvalDesc->MoveState = ENTICE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->special_counter == 0) { StarShipPtr->ship_input_state &= ~SPECIAL; if (ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr && ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState == ENTICE) { if ((StarShipPtr->ship_input_state & THRUST) || (ShipPtr->turn_wait == 0 && !(StarShipPtr->ship_input_state & (LEFT | RIGHT))) || NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle ( &ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr->velocity ) + HALF_CIRCLE + OCTANT) - StarShipPtr->ShipFacing) > ANGLE_TO_FACING (QUADRANT)) StarShipPtr->ship_input_state |= SPECIAL; } else if (lpEvalDesc->ObjectPtr) { if (lpEvalDesc->MoveState == PURSUE) { if (StarShipPtr->RaceDescPtr->ship_info.energy_level >= WEAPON_ENERGY_COST + SPECIAL_ENERGY_COST && ShipPtr->turn_wait == 0 && !(StarShipPtr->ship_input_state & (LEFT | RIGHT)) && (!(StarShipPtr->cur_status_flags & SPECIAL) || !(StarShipPtr->cur_status_flags & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)))) StarShipPtr->ship_input_state |= SPECIAL; } else if (lpEvalDesc->MoveState == ENTICE) { COUNT direction_angle; SIZE delta_x, delta_y; delta_x = lpEvalDesc->ObjectPtr->next.location.x - ShipPtr->next.location.x; delta_y = lpEvalDesc->ObjectPtr->next.location.y - ShipPtr->next.location.y; direction_angle = ARCTAN (delta_x, delta_y); if ((lpEvalDesc->which_turn > 24 && !(StarShipPtr->ship_input_state & (LEFT | RIGHT))) || (lpEvalDesc->which_turn <= 16 && NORMALIZE_ANGLE (direction_angle - (FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE) + QUADRANT) <= HALF_CIRCLE && (lpEvalDesc->which_turn < 12 || NORMALIZE_ANGLE (direction_angle - (GetVelocityTravelAngle ( &lpEvalDesc->ObjectPtr->velocity ) + HALF_CIRCLE) + (OCTANT + 2)) <= ((OCTANT + 2) << 1)))) StarShipPtr->ship_input_state |= SPECIAL; } } if ((StarShipPtr->ship_input_state & SPECIAL) && StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST) StarShipPtr->ship_input_state &= ~THRUST; } } #define NAPALM_WAIT 1 static void flame_napalm_preprocess (PELEMENT ElementPtr) { ZeroVelocityComponents (&ElementPtr->velocity); if (ElementPtr->state_flags & NONSOLID) { ElementPtr->state_flags &= ~NONSOLID; ElementPtr->state_flags |= APPEARING; SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], STAMP_PRIM); InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); InitIntersectFrame (ElementPtr); } else if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { #define NUM_NAPALM_FADES 6 if (ElementPtr->life_span <= NUM_NAPALM_FADES * (NAPALM_WAIT + 1) || GetFrameIndex ( ElementPtr->current.image.frame ) != NUM_NAPALM_FADES) ElementPtr->next.image.frame = DecFrameIndex (ElementPtr->current.image.frame); else if (ElementPtr->life_span > NUM_NAPALM_FADES * (NAPALM_WAIT + 1)) ElementPtr->next.image.frame = SetAbsFrameIndex ( ElementPtr->current.image.frame, GetFrameCount (ElementPtr->current.image.frame) - 1 ); ElementPtr->turn_wait = NAPALM_WAIT; ElementPtr->state_flags |= CHANGING; } } static COUNT initialize_horn (PELEMENT ShipPtr, HELEMENT HornArray[]) { #define MISSILE_HITS 2 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 3 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = THRADDASH_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; HornArray[0] = initialize_missile (&MissileBlock); return (1); } static void thraddash_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (!(StarShipPtr->cur_status_flags & SPECIAL)) { if ((StarShipPtr->old_status_flags & SPECIAL) && (StarShipPtr->cur_status_flags & SHIP_AT_MAX_SPEED)) StarShipPtr->cur_status_flags |= SHIP_BEYOND_MAX_SPEED; } else if (DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { #define SPECIAL_THRUST_INCREMENT 12 #define SPECIAL_MAX_THRUST 72 COUNT max_thrust, thrust_increment; UWORD thrust_status; HELEMENT hTrailElement; if (!(StarShipPtr->old_status_flags & SPECIAL)) StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); if (ElementPtr->thrust_wait == 0) ++ElementPtr->thrust_wait; thrust_increment = StarShipPtr->RaceDescPtr->characteristics.thrust_increment; max_thrust = StarShipPtr->RaceDescPtr->characteristics.max_thrust; StarShipPtr->RaceDescPtr->characteristics.thrust_increment = SPECIAL_THRUST_INCREMENT; StarShipPtr->RaceDescPtr->characteristics.max_thrust = SPECIAL_MAX_THRUST; thrust_status = inertial_thrust (ElementPtr); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED | SHIP_IN_GRAVITY_WELL); StarShipPtr->cur_status_flags |= thrust_status; StarShipPtr->RaceDescPtr->characteristics.thrust_increment = thrust_increment; StarShipPtr->RaceDescPtr->characteristics.max_thrust = max_thrust; { #define NAPALM_HITS 1 #define NAPALM_DAMAGE 2 #define NAPALM_LIFE 48 #define NAPALM_OFFSET 0 MISSILE_BLOCK MissileBlock; MissileBlock.cx = ElementPtr->next.location.x; MissileBlock.cy = ElementPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; MissileBlock.face = 0; MissileBlock.index = GetFrameCount ( StarShipPtr->RaceDescPtr->ship_data.special[0] ) - 1; MissileBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = 0; MissileBlock.speed = 0; MissileBlock.hit_points = NAPALM_HITS; MissileBlock.damage = NAPALM_DAMAGE; MissileBlock.life = NAPALM_LIFE; MissileBlock.preprocess_func = flame_napalm_preprocess; MissileBlock.blast_offs = NAPALM_OFFSET; hTrailElement = initialize_missile (&MissileBlock); if (hTrailElement) { ELEMENTPTR TrailElementPtr; LockElement (hTrailElement, &TrailElementPtr); SetElementStarShip (TrailElementPtr, StarShipPtr); TrailElementPtr->hTarget = 0; TrailElementPtr->turn_wait = NAPALM_WAIT; TrailElementPtr->state_flags |= NONSOLID; SetPrimType ( &(GLOBAL (DisplayArray))[TrailElementPtr->PrimIndex], NO_PRIM ); /* normally done during preprocess, but because * object is being inserted at head rather than * appended after tail it may never get preprocessed. */ TrailElementPtr->next = TrailElementPtr->current; TrailElementPtr->state_flags |= PRE_PROCESS; UnlockElement (hTrailElement); InsertElement (hTrailElement, GetHeadElement ()); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); } } } } RACE_DESCPTR init_thraddash (void) { RACE_DESCPTR RaceDescPtr; thraddash_desc.preprocess_func = thraddash_preprocess; thraddash_desc.init_weapon_func = initialize_horn; thraddash_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) thraddash_intelligence; RaceDescPtr = &thraddash_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/thradd/thradd.res0000600000175000017500000000154710543202070020164 0ustar joeyjoeyINCLUDE ../star3do.typ PATH thradd PACKAGE THRADDASH_CODE_PACKAGE thradd.shp CODE THRADDASH_CODE thradd.cod GFXRES THRADDASH_ICON_MASK_PMAP_ANIM thricons.ani GFXRES THRADDASH_MICON_MASK_PMAP_ANIM thrmicon.ani STRTAB THRADDASH_RACE_STRINGS thrtext.txt PACKAGE THRADDASH_PACKAGE thradd.shp GFXRES THRADDASH_BIG_MASK_PMAP_ANIM thradd.big GFXRES THRADDASH_MED_MASK_PMAP_ANIM thradd.med GFXRES THRADDASH_SML_MASK_PMAP_ANIM thradd.sml GFXRES HORN_BIG_MASK_PMAP_ANIM horbig.ani GFXRES HORN_MED_MASK_PMAP_ANIM hormed.ani GFXRES HORN_SML_MASK_PMAP_ANIM horsml.ani GFXRES NAPALM_BIG_MASK_PMAP_ANIM napbig.ani GFXRES NAPALM_MED_MASK_PMAP_ANIM napmed.ani GFXRES NAPALM_SML_MASK_PMAP_ANIM napsml.ani GFXRES THRADDASH_CAPTAIN_MASK_PMAP_ANIM thrcap.ani SNDRES THRADDASH_SHIP_SOUNDS thrsound.snd MUSICRES THRADDASH_VICTORY_SONG thrditty.mod uqm-0.6.2/sc2/src/sc2code/ships/thradd/restypes.h0000600000175000017500000000024110543202070020220 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/thradd/igfxres.h0000600000175000017500000000107510543202070020017 0ustar joeyjoey#define THRADDASH_ICON_MASK_PMAP_ANIM 0x00200002L #define THRADDASH_MICON_MASK_PMAP_ANIM 0x00200102L #define THRADDASH_BIG_MASK_PMAP_ANIM 0x00400202L #define THRADDASH_MED_MASK_PMAP_ANIM 0x00400302L #define THRADDASH_SML_MASK_PMAP_ANIM 0x00400402L #define HORN_BIG_MASK_PMAP_ANIM 0x00400502L #define HORN_MED_MASK_PMAP_ANIM 0x00400602L #define HORN_SML_MASK_PMAP_ANIM 0x00400702L #define NAPALM_BIG_MASK_PMAP_ANIM 0x00400802L #define NAPALM_MED_MASK_PMAP_ANIM 0x00400902L #define NAPALM_SML_MASK_PMAP_ANIM 0x00400a02L #define THRADDASH_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/thradd/isndres.h0000600000175000017500000000005410543202070020013 0ustar joeyjoey#define THRADDASH_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/thradd/istrtab.h0000600000175000017500000000005510543202070020015 0ustar joeyjoey#define THRADDASH_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/thradd/imusicre.h0000600000175000017500000000005510543202070020165 0ustar joeyjoey#define THRADDASH_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/thradd/icode.h0000600000175000017500000000004510543202070017427 0ustar joeyjoey#define THRADDASH_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/thradd/Makeinfo0000600000175000017500000000002610543202070017646 0ustar joeyjoeyuqm_CFILES="thradd.c" uqm-0.6.2/sc2/src/sc2code/ships/thradd/respkg.h0000600000175000017500000000007310543202070017640 0ustar joeyjoeyenum { THRADDASH_CODE_PACKAGE = 1, THRADDASH_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/thradd/resinst.h0000600000175000017500000000015010543202070020030 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/lastbat/0000755000175000017500000000000010552600274016400 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/lastbat/restypes.h0000600000175000017500000000024110543202062020405 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/lastbat/igfxres.h0000600000175000017500000000072610543202062020206 0ustar joeyjoey#define SAMATRA_BIG_MASK_ANIM 0x00400002L #define SAMATRA_MED_MASK_PMAP_ANIM 0x00400102L #define SAMATRA_SML_MASK_PMAP_ANIM 0x00400202L #define SENTINEL_BIG_MASK_ANIM 0x00400302L #define SENTINEL_MED_MASK_PMAP_ANIM 0x00400402L #define SENTINEL_SML_MASK_PMAP_ANIM 0x00400502L #define GENERATOR_BIG_MASK_ANIM 0x00400602L #define GENERATOR_MED_MASK_PMAP_ANIM 0x00400702L #define GENERATOR_SML_MASK_PMAP_ANIM 0x00400802L #define SAMATRA_CAPTAIN_MASK_PMAP_ANIM 0x00600902L uqm-0.6.2/sc2/src/sc2code/ships/lastbat/isndres.h0000600000175000017500000000005210543202062020176 0ustar joeyjoey#define SAMATRA_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/lastbat/istrtab.h0000600000175000017500000000005210543202062020177 0ustar joeyjoey#define SAMATRA_SHIP_SOUNDS 0x00400004L uqm-0.6.2/sc2/src/sc2code/ships/lastbat/imusicre.h0000600000175000017500000000011610543202062020350 0ustar joeyjoey#define SAMATRA_VICTORY_SONG 0x00400005L typedef RESOURCE MUSICRES_INSTANCE; uqm-0.6.2/sc2/src/sc2code/ships/lastbat/icode.h0000600000175000017500000000004310543202062017612 0ustar joeyjoey#define SAMATRA_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/lastbat/Makeinfo0000600000175000017500000000002710543202062020034 0ustar joeyjoeyuqm_CFILES="lastbat.c" uqm-0.6.2/sc2/src/sc2code/ships/lastbat/respkg.h0000600000175000017500000000012010543202062020016 0ustar joeyjoeyenum { SAMATRA_CODE_PACKAGE = 1, SAMATRA_PACKAGE, SAMATRA_STATUS_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/lastbat/lastbat.res0000600000175000017500000000131210543202062020523 0ustar joeyjoeyINCLUDE ../star3do.typ PATH lastbat PACKAGE SAMATRA_CODE_PACKAGE lastbat.sc2 CODE SAMATRA_CODE lastbat.cod PACKAGE SAMATRA_PACKAGE lastbat.sc2 GFXRES SAMATRA_BIG_MASK_ANIM lastbat.big GFXRES SAMATRA_MED_MASK_PMAP_ANIM lastbat.med GFXRES SAMATRA_SML_MASK_PMAP_ANIM lastbat.sml GFXRES SENTINEL_BIG_MASK_ANIM senbig.ani GFXRES SENTINEL_MED_MASK_PMAP_ANIM senmed.ani GFXRES SENTINEL_SML_MASK_PMAP_ANIM sensml.ani GFXRES GENERATOR_BIG_MASK_ANIM genbig.ani GFXRES GENERATOR_MED_MASK_PMAP_ANIM genmed.ani GFXRES GENERATOR_SML_MASK_PMAP_ANIM gensml.ani SNDRES SAMATRA_SHIP_SOUNDS lassound.snd PACKAGE SAMATRA_STATUS_PACKAGE lastbat.sc2 GFXRES SAMATRA_CAPTAIN_MASK_PMAP_ANIM lascap.ani uqm-0.6.2/sc2/src/sc2code/ships/lastbat/resinst.h0000600000175000017500000000007510543202062020223 0ustar joeyjoey#include "igfxres.h" #include "isndres.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/lastbat/lastbat.c0000600000175000017500000005554710543202062020177 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/lastbat/resinst.h" #include "colors.h" #include "globdata.h" #include "libs/mathlib.h" #include "libs/timelib.h" #define num_generators characteristics.max_thrust #define MAX_CREW 1 #define MAX_ENERGY MAX_ENERGY_SIZE #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 2 #define SPECIAL_ENERGY_COST 3 #define ENERGY_WAIT 6 #define MAX_THRUST 0 #define THRUST_INCREMENT 0 #define TURN_WAIT 0 #define THRUST_WAIT 0 #define WEAPON_WAIT ((ONE_SECOND / BATTLE_FRAME_RATE) * 10) #define SPECIAL_WAIT ((ONE_SECOND / BATTLE_FRAME_RATE) * 3) #define SHIP_MASS (MAX_SHIP_MASS * 10) #define SAMATRA_OFFSET 9 #define MISSILE_SPEED DISPLAY_TO_WORLD (8) static RACE_DESC samatra_desc = { { /* FIRES_FORE | */ IMMEDIATE_WEAPON | CREW_IMMUNE, 16, /* Super Melee cost */ 0, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 0, 0, }, (STRING)0, (FRAME)0, (FRAME)0, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)SAMATRA_BIG_MASK_ANIM, (FRAME)SAMATRA_MED_MASK_PMAP_ANIM, (FRAME)SAMATRA_SML_MASK_PMAP_ANIM, }, { (FRAME)SENTINEL_BIG_MASK_ANIM, (FRAME)SENTINEL_MED_MASK_PMAP_ANIM, (FRAME)SENTINEL_SML_MASK_PMAP_ANIM, }, { (FRAME)GENERATOR_BIG_MASK_ANIM, (FRAME)GENERATOR_MED_MASK_PMAP_ANIM, (FRAME)GENERATOR_SML_MASK_PMAP_ANIM, }, { (FRAME)SAMATRA_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, 0, (SOUND)SAMATRA_SHIP_SOUNDS, }, { 0, 0, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static HELEMENT spawn_comet (PELEMENT ElementPtr); static void comet_preprocess (PELEMENT ElementPtr) { COUNT frame_index; frame_index = GetFrameIndex (ElementPtr->current.image.frame) + 1; if (frame_index < 29) { if (frame_index == 25) { SIZE cur_delta_x, cur_delta_y; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); ++StarShipPtr->RaceDescPtr->characteristics.weapon_wait; spawn_comet (ElementPtr); ElementPtr->state_flags |= NONSOLID; GetCurrentVelocityComponents (&ElementPtr->velocity, &cur_delta_x, &cur_delta_y); SetVelocityComponents (&ElementPtr->velocity, cur_delta_x / 2, cur_delta_y / 2); } ++ElementPtr->life_span; } ElementPtr->next.image.frame = SetAbsFrameIndex ( ElementPtr->current.image.frame, frame_index ); ElementPtr->state_flags |= CHANGING; } #define COMET_DAMAGE 2 static void comet_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if (ElementPtr1->state_flags & GOOD_GUY) { BYTE old_hits; COUNT old_life; HELEMENT hBlastElement; if (ElementPtr1->state_flags & PLAYER_SHIP) ElementPtr0->mass_points = COMET_DAMAGE; else ElementPtr0->mass_points = 50; old_hits = ElementPtr0->hit_points; old_life = ElementPtr0->life_span; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if (ElementPtr1->state_flags & PLAYER_SHIP) { ElementPtr0->hit_points = old_hits; ElementPtr0->life_span = old_life; ElementPtr0->state_flags &= ~(DISAPPEARING | NONSOLID | COLLISION); if (hBlastElement) { RemoveElement (hBlastElement); FreeElement (hBlastElement); } } if (ElementPtr0->state_flags & DISAPPEARING) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr0, &StarShipPtr); --StarShipPtr->RaceDescPtr->characteristics.weapon_wait; } } } static HELEMENT spawn_comet (PELEMENT ElementPtr) { #define COMET_OFFSET 0 #define COMET_HITS 12 #define COMET_SPEED DISPLAY_TO_WORLD (12) #define COMET_LIFE 2 MISSILE_BLOCK MissileBlock; HELEMENT hComet; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); MissileBlock.cx = ElementPtr->next.location.x; MissileBlock.cy = ElementPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = 0; MissileBlock.index = 24; MissileBlock.sender = BAD_GUY | IGNORE_SIMILAR; MissileBlock.pixoffs = 0; MissileBlock.speed = 0; MissileBlock.hit_points = COMET_HITS; MissileBlock.damage = COMET_DAMAGE; MissileBlock.life = COMET_LIFE; MissileBlock.preprocess_func = comet_preprocess; MissileBlock.blast_offs = COMET_OFFSET; hComet = initialize_missile (&MissileBlock); if (hComet) { ELEMENTPTR CometPtr; PutElement (hComet); LockElement (hComet, &CometPtr); CometPtr->collision_func = comet_collision; SetElementStarShip (CometPtr, StarShipPtr); { COUNT facing; CometPtr->turn_wait = ElementPtr->turn_wait; CometPtr->hTarget = ElementPtr->hTarget; if (ElementPtr->state_flags & PLAYER_SHIP) { CometPtr->turn_wait = 0; facing = (COUNT)TFB_Random (); SetVelocityVector (&CometPtr->velocity, COMET_SPEED, facing); } else { CometPtr->velocity = ElementPtr->velocity; CometPtr->hit_points = ElementPtr->hit_points; facing = ANGLE_TO_FACING ( GetVelocityTravelAngle (&CometPtr->velocity) ); } if (CometPtr->turn_wait) --CometPtr->turn_wait; else { #define COMET_WAIT 3 facing = NORMALIZE_FACING (facing); if (TrackShip (CometPtr, &facing) > 0) SetVelocityVector (&CometPtr->velocity, COMET_SPEED, facing); CometPtr->turn_wait = COMET_WAIT; } } UnlockElement (hComet); } return (hComet); } static void turret_preprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { #define TURRET_WAIT 0 ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, (GetFrameIndex (ElementPtr->current.image.frame) % 10) + 1); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = TURRET_WAIT; } } #define GATE_DAMAGE 1 #define GATE_HITS 100 static void gate_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if (ElementPtr1->state_flags & GOOD_GUY) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr0, &StarShipPtr); if (StarShipPtr->RaceDescPtr->num_generators == 0) { if (!(ElementPtr1->state_flags & FINITE_LIFE)) ElementPtr0->state_flags |= COLLISION; if ((ElementPtr1->state_flags & PLAYER_SHIP) && GetPrimType ( &GLOBAL (DisplayArray[ElementPtr0->PrimIndex]) ) == STAMPFILL_PRIM && GET_GAME_STATE (BOMB_CARRIER)) { GLOBAL (CurrentActivity) &= ~IN_BATTLE; } } else { HELEMENT hBlastElement; if (ElementPtr1->state_flags & PLAYER_SHIP) ElementPtr0->mass_points = GATE_DAMAGE; else ElementPtr0->mass_points = 50; ElementPtr0->hit_points = GATE_HITS; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); ElementPtr0->state_flags &= ~(DISAPPEARING | NONSOLID | COLLISION); ElementPtr0->life_span = NORMAL_LIFE; if (hBlastElement) { RemoveElement (hBlastElement); FreeElement (hBlastElement); } } } } static void gate_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->RaceDescPtr->num_generators == 0) { ElementPtr->mass_points = SHIP_MASS; ElementPtr->state_flags &= ~FINITE_LIFE; ElementPtr->life_span = NORMAL_LIFE + 1; ElementPtr->preprocess_func = 0; SetPrimColor ( &GLOBAL (DisplayArray[ElementPtr->PrimIndex]), BLACK_COLOR ); SetPrimType ( &GLOBAL (DisplayArray[ElementPtr->PrimIndex]), STAMPFILL_PRIM ); } else { ++ElementPtr->life_span; ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); if (GetFrameIndex (ElementPtr->next.image.frame) == 0) ElementPtr->next.image.frame = SetAbsFrameIndex ( ElementPtr->next.image.frame, 11 ); ElementPtr->state_flags |= CHANGING; } } static void generator_death (PELEMENT ElementPtr) { if (!(ElementPtr->state_flags & FINITE_LIFE)) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); --StarShipPtr->RaceDescPtr->num_generators; ElementPtr->state_flags |= FINITE_LIFE | NONSOLID; ElementPtr->preprocess_func = 0; ElementPtr->turn_wait = 12; ElementPtr->thrust_wait = 0; ElementPtr->current.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, 10 - 1); } if (ElementPtr->thrust_wait) { --ElementPtr->thrust_wait; ElementPtr->state_flags &= ~DISAPPEARING; ElementPtr->state_flags |= CHANGING; ++ElementPtr->life_span; } else if (ElementPtr->turn_wait--) { ElementPtr->state_flags &= ~DISAPPEARING; ElementPtr->state_flags |= CHANGING; ++ElementPtr->life_span; ElementPtr->next.image.frame = IncFrameIndex ( ElementPtr->current.image.frame ); ElementPtr->thrust_wait = 1; } } #define GENERATOR_HITS 15 static void generator_preprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else if ((ElementPtr->turn_wait = (BYTE)((GENERATOR_HITS - ElementPtr->hit_points) / 5)) < 3) { ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, (GetFrameIndex (ElementPtr->current.image.frame) + 1) % 10); ElementPtr->state_flags |= CHANGING; } } static void generator_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if (!(ElementPtr1->state_flags & FINITE_LIFE)) { ElementPtr0->state_flags |= COLLISION; } (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } #define TRACK_WAIT 1 static void sentinel_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); ++StarShipPtr->RaceDescPtr->characteristics.special_wait; ++ElementPtr->life_span; if (ElementPtr->thrust_wait) --ElementPtr->thrust_wait; else { #define ANIMATION_WAIT 1 ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, (GetFrameIndex (ElementPtr->current.image.frame) + 1) % 6); ElementPtr->state_flags |= CHANGING; ElementPtr->thrust_wait = ANIMATION_WAIT; } if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { COUNT facing; HELEMENT hTarget; if (!(ElementPtr->state_flags & NONSOLID)) facing = ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity) ); else { ElementPtr->state_flags &= ~NONSOLID; facing = (COUNT)TFB_Random (); SetVelocityVector (&ElementPtr->velocity, MISSILE_SPEED, facing); } facing = NORMALIZE_FACING (facing); if (ElementPtr->hTarget == 0) { COUNT f; f = facing; TrackShip (ElementPtr, &f); } if (ElementPtr->hTarget == 0) hTarget = StarShipPtr->hShip; else if (StarShipPtr->hShip == 0) hTarget = ElementPtr->hTarget; else { SIZE delta_x0, delta_y0, delta_x1, delta_y1; ELEMENTPTR ShipPtr, EnemyShipPtr; LockElement (ElementPtr->hTarget, &EnemyShipPtr); LockElement (StarShipPtr->hShip, &ShipPtr); delta_x0 = ShipPtr->current.location.x - ElementPtr->current.location.x; delta_y0 = ShipPtr->current.location.y - ElementPtr->current.location.y; delta_x1 = ShipPtr->current.location.x - EnemyShipPtr->current.location.x; delta_y1 = ShipPtr->current.location.y - EnemyShipPtr->current.location.y; UnlockElement (StarShipPtr->hShip); if ((long)delta_x0 * delta_x0 + (long)delta_y0 * delta_y0 > (long)delta_x1 * delta_x1 + (long)delta_y1 * delta_y1) hTarget = StarShipPtr->hShip; else hTarget = ElementPtr->hTarget; UnlockElement (ElementPtr->hTarget); } if (hTarget) { COUNT num_frames; SIZE delta_x, delta_y; ELEMENTPTR TargetPtr; VELOCITY_DESC TargetVelocity; LockElement (hTarget, &TargetPtr); delta_x = TargetPtr->current.location.x - ElementPtr->current.location.x; delta_x = WRAP_DELTA_X (delta_x); delta_y = TargetPtr->current.location.y - ElementPtr->current.location.y; delta_y = WRAP_DELTA_Y (delta_y); if ((num_frames = WORLD_TO_TURN ( square_root ((long)delta_x * delta_x + (long)delta_y * delta_y) )) == 0) num_frames = 1; TargetVelocity = TargetPtr->velocity; GetNextVelocityComponents (&TargetVelocity, &delta_x, &delta_y, num_frames); delta_x = (TargetPtr->current.location.x + delta_x) - ElementPtr->current.location.x; delta_x = WRAP_DELTA_X (delta_x); delta_y = (TargetPtr->current.location.y + delta_y) - ElementPtr->current.location.y; delta_y = WRAP_DELTA_Y (delta_y); UnlockElement (hTarget); delta_x = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) - facing ); if (delta_x > 0) { if (delta_x <= ANGLE_TO_FACING (HALF_CIRCLE)) ++facing; else --facing; } SetVelocityVector (&ElementPtr->velocity, MISSILE_SPEED, facing); } ElementPtr->turn_wait = TRACK_WAIT; } } #define RECOIL_VELOCITY WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (10)) #define MAX_RECOIL_VELOCITY (RECOIL_VELOCITY * 4) static void sentinel_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { COUNT angle; STARSHIPPTR StarShipPtr; if (ElementPtr1->state_flags & BAD_GUY) { if (ElementPtr0->preprocess_func == ElementPtr1->preprocess_func && !(ElementPtr0->state_flags & DEFY_PHYSICS) && (pPt0->x != ElementPtr0->IntersectControl.IntersectStamp.origin.x || pPt0->y != ElementPtr0->IntersectControl.IntersectStamp.origin.y)) { angle = ARCTAN (pPt0->x - pPt1->x, pPt0->y - pPt1->y); SetVelocityComponents (&ElementPtr0->velocity, COSINE (angle, WORLD_TO_VELOCITY (MISSILE_SPEED)), SINE (angle, WORLD_TO_VELOCITY (MISSILE_SPEED))); ElementPtr0->turn_wait = TRACK_WAIT; ElementPtr0->state_flags |= COLLISION | DEFY_PHYSICS; } } else { BYTE old_hits; COUNT old_life; HELEMENT hBlastElement; old_hits = ElementPtr0->hit_points; old_life = ElementPtr0->life_span; ElementPtr0->blast_offset = 0; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); ElementPtr0->thrust_wait = 0; if ((ElementPtr1->state_flags & PLAYER_SHIP) && ElementPtr1->crew_level && !GRAVITY_MASS (ElementPtr1->mass_points + 1)) { SIZE cur_delta_x, cur_delta_y; ElementPtr0->life_span = old_life; ElementPtr0->hit_points = old_hits; ElementPtr0->state_flags &= ~DISAPPEARING; ElementPtr0->state_flags |= DEFY_PHYSICS; ElementPtr0->turn_wait = (ONE_SECOND / BATTLE_FRAME_RATE) >> 1; GetElementStarShip (ElementPtr1, &StarShipPtr); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); if (ElementPtr1->turn_wait < COLLISION_TURN_WAIT) ElementPtr1->turn_wait += COLLISION_TURN_WAIT; if (ElementPtr1->thrust_wait < COLLISION_THRUST_WAIT) ElementPtr1->thrust_wait += COLLISION_THRUST_WAIT; angle = GetVelocityTravelAngle (&ElementPtr0->velocity); DeltaVelocityComponents (&ElementPtr1->velocity, COSINE (angle, RECOIL_VELOCITY), SINE (angle, RECOIL_VELOCITY)); GetCurrentVelocityComponents (&ElementPtr1->velocity, &cur_delta_x, &cur_delta_y); if ((long)cur_delta_x * (long)cur_delta_x + (long)cur_delta_y * (long)cur_delta_y > (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY) { angle = ARCTAN (cur_delta_x, cur_delta_y); SetVelocityComponents (&ElementPtr1->velocity, COSINE (angle, MAX_RECOIL_VELOCITY), SINE (angle, MAX_RECOIL_VELOCITY)); } ZeroVelocityComponents (&ElementPtr0->velocity); } if (ElementPtr0->state_flags & DISAPPEARING) { GetElementStarShip (ElementPtr0, &StarShipPtr); --StarShipPtr->RaceDescPtr->characteristics.special_wait; if (hBlastElement) { ELEMENTPTR BlastElementPtr; LockElement (hBlastElement, &BlastElementPtr); BlastElementPtr->life_span = 6; BlastElementPtr->current.image.frame = SetAbsFrameIndex ( BlastElementPtr->current.image.farray[0], 6 ); UnlockElement (hBlastElement); } } } } static void samatra_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); } #define MAX_COMETS 3 #define MAX_SENTINELS 4 static void samatra_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->RaceDescPtr->num_generators) { if (StarShipPtr->weapon_counter == 0 && StarShipPtr->RaceDescPtr->characteristics.weapon_wait < MAX_COMETS && spawn_comet (ElementPtr)) { StarShipPtr->weapon_counter = WEAPON_WAIT; } if (StarShipPtr->special_counter == 0 && StarShipPtr->RaceDescPtr->characteristics.special_wait < MAX_SENTINELS) { #define MISSILE_LIFE 2 #define MISSILE_OFFSET 0 #define MISSILE_HITS 10 #define MISSILE_DAMAGE 1 MISSILE_BLOCK MissileBlock; HELEMENT hSentinel; MissileBlock.cx = ElementPtr->next.location.x; MissileBlock.cy = ElementPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = 0; MissileBlock.index = 0; MissileBlock.sender = BAD_GUY; MissileBlock.pixoffs = 0; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = sentinel_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; hSentinel = initialize_missile (&MissileBlock); if (hSentinel) { ELEMENTPTR SentinelPtr; LockElement (hSentinel, &SentinelPtr); SentinelPtr->collision_func = sentinel_collision; SentinelPtr->turn_wait = TRACK_WAIT + 2; SetElementStarShip (SentinelPtr, StarShipPtr); UnlockElement (hSentinel); StarShipPtr->special_counter = SPECIAL_WAIT; PutElement (hSentinel); } } } } static void samatra_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); StarShipPtr->RaceDescPtr->characteristics.weapon_wait = 0; StarShipPtr->RaceDescPtr->characteristics.special_wait = 0; if (!(ElementPtr->state_flags & APPEARING)) { ++ElementPtr->turn_wait; ++ElementPtr->thrust_wait; } else { #define MAX_GENERATORS 8 POINT offs[] = { {-127-9, -53+18}, { -38-9, -88+18}, { 44-9, -85+18}, { 127-9, -60+18}, { 124-9, 28+18}, { 73-9, 61+18}, { -87-9, 58+18}, {-136-9, 29+18}, }; for (StarShipPtr->RaceDescPtr->num_generators = 0; StarShipPtr->RaceDescPtr->num_generators < MAX_GENERATORS; ++StarShipPtr->RaceDescPtr->num_generators) { HELEMENT hGenerator; hGenerator = AllocElement (); if (hGenerator) { ELEMENTPTR GeneratorPtr; LockElement (hGenerator, &GeneratorPtr); GeneratorPtr->hit_points = GENERATOR_HITS; GeneratorPtr->mass_points = MAX_SHIP_MASS * 10; GeneratorPtr->life_span = NORMAL_LIFE; GeneratorPtr->state_flags = APPEARING | BAD_GUY | IGNORE_SIMILAR; SetPrimType ( &GLOBAL (DisplayArray[GeneratorPtr->PrimIndex]), STAMP_PRIM ); GeneratorPtr->current.location.x = ((LOG_SPACE_WIDTH >> 1) + DISPLAY_TO_WORLD (offs[StarShipPtr->RaceDescPtr->num_generators].x)) & ~((SCALED_ONE << MAX_VIS_REDUCTION) - 1); GeneratorPtr->current.location.y = ((LOG_SPACE_HEIGHT >> 1) + DISPLAY_TO_WORLD (offs[StarShipPtr->RaceDescPtr->num_generators].y)) & ~((SCALED_ONE << MAX_VIS_REDUCTION) - 1); GeneratorPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; GeneratorPtr->current.image.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.special[0], (BYTE)TFB_Random () % 10 ); GeneratorPtr->preprocess_func = generator_preprocess; GeneratorPtr->collision_func = generator_collision; GeneratorPtr->death_func = generator_death; SetElementStarShip (GeneratorPtr, StarShipPtr); UnlockElement (hGenerator); InsertElement (hGenerator, GetHeadElement ()); } } { HELEMENT hTurret; hTurret = AllocElement (); if (hTurret) { ELEMENTPTR TurretPtr; LockElement (hTurret, &TurretPtr); TurretPtr->hit_points = 1; TurretPtr->life_span = NORMAL_LIFE; TurretPtr->state_flags = APPEARING | BAD_GUY | IGNORE_SIMILAR | NONSOLID; SetPrimType ( &GLOBAL (DisplayArray[TurretPtr->PrimIndex]), STAMP_PRIM ); TurretPtr->current.location.x = LOG_SPACE_WIDTH >> 1; TurretPtr->current.location.y = LOG_SPACE_HEIGHT >> 1; TurretPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; TurretPtr->current.image.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.ship[0], 1 ); TurretPtr->preprocess_func = turret_preprocess; SetElementStarShip (TurretPtr, StarShipPtr); UnlockElement (hTurret); InsertElement (hTurret, GetSuccElement (ElementPtr)); } } { HELEMENT hGate; hGate = AllocElement (); if (hGate) { ELEMENTPTR GatePtr; LockElement (hGate, &GatePtr); GatePtr->hit_points = GATE_HITS; GatePtr->mass_points = GATE_DAMAGE; GatePtr->life_span = 2; GatePtr->state_flags = APPEARING | FINITE_LIFE | BAD_GUY | IGNORE_SIMILAR; SetPrimType ( &GLOBAL (DisplayArray[GatePtr->PrimIndex]), STAMP_PRIM ); GatePtr->current.location.x = LOG_SPACE_WIDTH >> 1; GatePtr->current.location.y = LOG_SPACE_HEIGHT >> 1; GatePtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; GatePtr->current.image.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.ship[0], 11 ); GatePtr->preprocess_func = gate_preprocess; GatePtr->collision_func = gate_collision; SetElementStarShip (GatePtr, StarShipPtr); UnlockElement (hGate); InsertElement (hGate, GetSuccElement (ElementPtr)); } } StarShipPtr->weapon_counter = WEAPON_WAIT >> 1; StarShipPtr->special_counter = SPECIAL_WAIT >> 1; } } RACE_DESCPTR init_samatra (void) { RACE_DESCPTR RaceDescPtr; samatra_desc.preprocess_func = samatra_preprocess; samatra_desc.postprocess_func = samatra_postprocess; samatra_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) samatra_intelligence; RaceDescPtr = &samatra_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/ship.h0000600000175000017500000000200110543202075016040 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * This file contains definitions that are common to all ship files. */ #ifndef _SHIP_H #define _SHIP_H #include "collide.h" // XXX: Do we really need this one? //#include "reslib.h" #include "intel.h" #include "races.h" #include "sounds.h" #include "weapon.h" #endif /* _SHIP_H */ uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/0000755000175000017500000000000010552600274016420 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/ilwrath/restypes.h0000600000175000017500000000024110543202073020427 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/igfxres.h0000600000175000017500000000064710543202073020232 0ustar joeyjoey#define ILWRATH_ICON_MASK_PMAP_ANIM 0x00200002L #define ILWRATH_MICON_MASK_PMAP_ANIM 0x00200102L #define ILWRATH_BIG_MASK_PMAP_ANIM 0x00400202L #define ILWRATH_MED_MASK_PMAP_ANIM 0x00400302L #define ILWRATH_SML_MASK_PMAP_ANIM 0x00400402L #define FIRE_BIG_MASK_PMAP_ANIM 0x00400502L #define FIRE_MED_MASK_PMAP_ANIM 0x00400602L #define FIRE_SML_MASK_PMAP_ANIM 0x00400702L #define ILWRATH_CAPTAIN_MASK_PMAP_ANIM 0x00400802L uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/isndres.h0000600000175000017500000000005210543202073020220 0ustar joeyjoey#define ILWRATH_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/istrtab.h0000600000175000017500000000005310543202073020222 0ustar joeyjoey#define ILWRATH_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/imusicre.h0000600000175000017500000000005310543202073020372 0ustar joeyjoey#define ILWRATH_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/icode.h0000600000175000017500000000004310543202073017634 0ustar joeyjoey#define ILWRATH_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/ilwrath.res0000600000175000017500000000130710543202073020571 0ustar joeyjoeyINCLUDE ../star3do.typ PATH ilwrath PACKAGE ILWRATH_CODE_PACKAGE ilwrath.shp CODE ILWRATH_CODE ilwrath.cod GFXRES ILWRATH_ICON_MASK_PMAP_ANIM ilwicons.ani GFXRES ILWRATH_MICON_MASK_PMAP_ANIM ilwmicon.ani STRTAB ILWRATH_RACE_STRINGS ilwtext.txt PACKAGE ILWRATH_PACKAGE ilwrath.shp GFXRES ILWRATH_BIG_MASK_PMAP_ANIM ilwrath.big GFXRES ILWRATH_MED_MASK_PMAP_ANIM ilwrath.med GFXRES ILWRATH_SML_MASK_PMAP_ANIM ilwrath.sml GFXRES FIRE_BIG_MASK_PMAP_ANIM fire.big GFXRES FIRE_MED_MASK_PMAP_ANIM fire.med GFXRES FIRE_SML_MASK_PMAP_ANIM fire.sml GFXRES ILWRATH_CAPTAIN_MASK_PMAP_ANIM ilwcap.ani SNDRES ILWRATH_SHIP_SOUNDS ilwsound.snd MUSICRES ILWRATH_VICTORY_SONG ilwditty.mod uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/Makeinfo0000600000175000017500000000002710543202073020056 0ustar joeyjoeyuqm_CFILES="ilwrath.c" uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/respkg.h0000600000175000017500000000006710543202073020052 0ustar joeyjoeyenum { ILWRATH_CODE_PACKAGE = 1, ILWRATH_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/ilwrath.c0000600000175000017500000002477610543202073020241 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/ilwrath/resinst.h" #include "colors.h" #include "globdata.h" #define MAX_CREW 22 #define MAX_ENERGY 16 #define ENERGY_REGENERATION 4 #define WEAPON_ENERGY_COST 1 #define SPECIAL_ENERGY_COST 3 #define ENERGY_WAIT 4 #define MAX_THRUST 25 #define THRUST_INCREMENT 5 #define TURN_WAIT 2 #define THRUST_WAIT 0 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 13 #define SHIP_MASS 7 #define MISSILE_LIFE 8 static RACE_DESC ilwrath_desc = { { FIRES_FORE, 10, /* Super Melee cost */ 1410 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 48, 1700, }, (STRING)ILWRATH_RACE_STRINGS, (FRAME)ILWRATH_ICON_MASK_PMAP_ANIM, (FRAME)ILWRATH_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)ILWRATH_BIG_MASK_PMAP_ANIM, (FRAME)ILWRATH_MED_MASK_PMAP_ANIM, (FRAME)ILWRATH_SML_MASK_PMAP_ANIM, }, { (FRAME)FIRE_BIG_MASK_PMAP_ANIM, (FRAME)FIRE_MED_MASK_PMAP_ANIM, (FRAME)FIRE_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)ILWRATH_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)ILWRATH_VICTORY_SONG, (SOUND)ILWRATH_SHIP_SOUNDS, }, { 0, CLOSE_RANGE_WEAPON, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static void flame_preprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = ElementPtr->next_turn; } } static void flame_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); ElementPtr0->state_flags &= ~DISAPPEARING; ElementPtr0->state_flags |= NONSOLID; } static void ilwrath_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { PEVALUATE_DESC lpEvalDesc; STARSHIPPTR StarShipPtr; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; lpEvalDesc->MoveState = PURSUE; if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 10) /* don't want to dodge when you could be flaming */ ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr = 0; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); if (lpEvalDesc->ObjectPtr && (lpEvalDesc->which_turn <= 6 || (lpEvalDesc->which_turn <= 10 && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 10))) { StarShipPtr->ship_input_state &= ~SPECIAL; if (OBJECT_CLOAKED (ShipPtr)) { StarShipPtr->ship_input_state &= ~LEFT | RIGHT; StarShipPtr->ship_input_state |= THRUST; } StarShipPtr->ship_input_state |= WEAPON; } else if (StarShipPtr->special_counter == 0 && (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER || !GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER))) { StarShipPtr->ship_input_state &= ~SPECIAL; if (!OBJECT_CLOAKED (ShipPtr) && !(StarShipPtr->ship_input_state & WEAPON)) StarShipPtr->ship_input_state |= SPECIAL; } } static COUNT initialize_flame (PELEMENT ShipPtr, HELEMENT FlameArray[]) { #define ILWRATH_OFFSET 29 #define MISSILE_SPEED MAX_THRUST #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 0 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = ILWRATH_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = flame_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; FlameArray[0] = initialize_missile (&MissileBlock); if (FlameArray[0]) { SIZE dx, dy; ELEMENTPTR FlamePtr; LockElement (FlameArray[0], &FlamePtr); GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); DeltaVelocityComponents (&FlamePtr->velocity, dx, dy); FlamePtr->current.location.x -= VELOCITY_TO_WORLD (dx); FlamePtr->current.location.y -= VELOCITY_TO_WORLD (dy); FlamePtr->collision_func = flame_collision; FlamePtr->turn_wait = 0; UnlockElement (FlameArray[0]); } return (1); } static void ilwrath_preprocess (PELEMENT ElementPtr) { ELEMENT_FLAGS status_flags; STARSHIPPTR StarShipPtr; PPRIMITIVE lpPrim; GetElementStarShip (ElementPtr, &StarShipPtr); status_flags = StarShipPtr->cur_status_flags; lpPrim = &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex]; if (GetPrimType (lpPrim) == STAMPFILL_PRIM) { COLOR Color; BOOLEAN weapon_discharge; Color = GetPrimColor (lpPrim); weapon_discharge = ((status_flags & WEAPON) && StarShipPtr->RaceDescPtr->ship_info.energy_level >= WEAPON_ENERGY_COST); if (weapon_discharge || (StarShipPtr->special_counter == 0 && ((status_flags & SPECIAL) || Color != BLACK_COLOR))) { if (Color == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)) SetPrimType (lpPrim, STAMP_PRIM); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); else { ProcessSound (SetAbsSoundIndex ( /* CLOAKING_OFF */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), ElementPtr); SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); if (weapon_discharge) { COUNT facing; facing = StarShipPtr->ShipFacing; if (TrackShip (ElementPtr, &facing) >= 0) { #define LOOK_AHEAD 4 ELEMENTPTR eptr; SIZE dx0, dy0, dx1, dy1; VELOCITY_DESC v; LockElement (ElementPtr->hTarget, &eptr); v = eptr->velocity; GetNextVelocityComponents (&v, &dx0, &dy0, LOOK_AHEAD); v = ElementPtr->velocity; GetNextVelocityComponents (&v, &dx1, &dy1, LOOK_AHEAD); dx0 = (eptr->current.location.x + dx0) - (ElementPtr->current.location.x + dx1); dy0 = (eptr->current.location.y + dy0) - (ElementPtr->current.location.y + dy1); UnlockElement (ElementPtr->hTarget); StarShipPtr->ShipFacing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (dx0, dy0)) ); #ifdef NOTYET if (ElementPtr->thrust_wait == 0 && (StarShipPtr->cur_status_flags & THRUST)) { COUNT last_facing; do { VELOCITY_DESC temp_v; last_facing = StarShipPtr->ShipFacing; inertial_thrust (ElementPtr); temp_v = ElementPtr->velocity; ElementPtr->velocity = v; dx0 += dx1; dy0 += dy1; GetNextVelocityComponents (&temp_v, &dx1, &dy1, LOOK_AHEAD); dx0 -= dx1; dy0 -= dy1; StarShipPtr->ShipFacing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (dx0, dy0)) ); } while (StarShipPtr->ShipFacing != last_facing); } #endif /* NOTYET */ if (ElementPtr->turn_wait == 0) ++ElementPtr->turn_wait; ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->next.image.frame, StarShipPtr->ShipFacing); } ElementPtr->hTarget = 0; } } ElementPtr->state_flags |= CHANGING; status_flags &= ~SPECIAL; StarShipPtr->special_counter = 0; } else if (Color != BLACK_COLOR) { if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)) { SetPrimColor (lpPrim, BLACK_COLOR); Untarget (ElementPtr); } else if (Color == BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); else if (Color == BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)) SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); else SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)); ElementPtr->state_flags |= CHANGING; } } if ((status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); SetPrimType (lpPrim, STAMPFILL_PRIM); ProcessSound (SetAbsSoundIndex ( /* CLOAKING_ON */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; ElementPtr->state_flags |= CHANGING; } } RACE_DESCPTR init_ilwrath (void) { RACE_DESCPTR RaceDescPtr; ilwrath_desc.preprocess_func = ilwrath_preprocess; ilwrath_desc.init_weapon_func = initialize_flame; ilwrath_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) ilwrath_intelligence; RaceDescPtr = &ilwrath_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/ilwrath/resinst.h0000600000175000017500000000015010543202073020237 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/urquan/0000755000175000017500000000000010552600274016261 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/urquan/restypes.h0000600000175000017500000000024110543202074020271 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/urquan/urquan.c0000600000175000017500000003657110543202074017740 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/urquan/resinst.h" #include "globdata.h" #include #define MAX_CREW MAX_CREW_SIZE #define MAX_ENERGY MAX_ENERGY_SIZE #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 6 #define SPECIAL_ENERGY_COST 8 #define ENERGY_WAIT 4 #define MAX_THRUST 30 #define THRUST_INCREMENT 6 #define TURN_WAIT 4 #define THRUST_WAIT 6 #define WEAPON_WAIT 6 #define SPECIAL_WAIT 9 #define SHIP_MASS 10 #define MISSILE_SPEED DISPLAY_TO_WORLD (20) #define MISSILE_LIFE 20 static RACE_DESC urquan_desc = { { FIRES_FORE | SEEKING_SPECIAL, 30, /* Super Melee cost */ 2666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 5750, 6000, }, (STRING)URQUAN_RACE_STRINGS, (FRAME)URQUAN_ICON_MASK_PMAP_ANIM, (FRAME)URQUAN_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)URQUAN_BIG_MASK_PMAP_ANIM, (FRAME)URQUAN_MED_MASK_PMAP_ANIM, (FRAME)URQUAN_SML_MASK_PMAP_ANIM, }, { (FRAME)FUSION_BIG_MASK_PMAP_ANIM, (FRAME)FUSION_MED_MASK_PMAP_ANIM, (FRAME)FUSION_SML_MASK_PMAP_ANIM, }, { (FRAME)FIGHTER_BIG_MASK_PMAP_ANIM, (FRAME)FIGHTER_MED_MASK_PMAP_ANIM, (FRAME)FIGHTER_SML_MASK_PMAP_ANIM, }, { (FRAME)URQUAN_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)URQUAN_VICTORY_SONG, (SOUND)URQUAN_SHIP_SOUNDS, }, { 0, MISSILE_SPEED * MISSILE_LIFE, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static COUNT initialize_fusion (PELEMENT ShipPtr, HELEMENT FusionArray[]) { #define MISSILE_HITS 10 #define MISSILE_DAMAGE 6 #define MISSILE_OFFSET 8 #define URQUAN_OFFSET 32 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = URQUAN_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; FusionArray[0] = initialize_missile (&MissileBlock); return (1); } #define TRACK_THRESHOLD 6 #define FIGHTER_SPEED DISPLAY_TO_WORLD (8) #define ONE_WAY_FLIGHT 125 #define FIGHTER_LIFE (ONE_WAY_FLIGHT + ONE_WAY_FLIGHT + 150) #define FIGHTER_WEAPON_WAIT 8 #define FIGHTER_OFFSET 4 #define LASER_RANGE DISPLAY_TO_WORLD (40 + FIGHTER_OFFSET) static void fighter_postprocess (PELEMENT ElementPtr) { HELEMENT Laser; STARSHIPPTR StarShipPtr; LASER_BLOCK LaserBlock; GetElementStarShip (ElementPtr, &StarShipPtr); LaserBlock.cx = ElementPtr->next.location.x; LaserBlock.cy = ElementPtr->next.location.y; LaserBlock.face = ElementPtr->thrust_wait; LaserBlock.ex = COSINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); LaserBlock.ey = SINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); LaserBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; LaserBlock.pixoffs = FIGHTER_OFFSET; LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E); Laser = initialize_laser (&LaserBlock); if (Laser) { ELEMENTPTR LaserPtr; LockElement (Laser, &LaserPtr); SetElementStarShip (LaserPtr, StarShipPtr); ProcessSound (SetAbsSoundIndex ( /* FIGHTER_ZAP */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), LaserPtr); UnlockElement (Laser); PutElement (Laser); } ElementPtr->postprocess_func = 0; ElementPtr->thrust_wait = FIGHTER_WEAPON_WAIT; } static void fighter_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); ++StarShipPtr->RaceDescPtr->characteristics.special_wait; if (FIGHTER_LIFE - ElementPtr->life_span > TRACK_THRESHOLD && !(ElementPtr->state_flags & CHANGING)) { BOOLEAN Enroute; COUNT orig_facing, facing; SIZE delta_x, delta_y; ELEMENTPTR eptr; Enroute = TRUE; delta_x = StarShipPtr->RaceDescPtr->ship_info.crew_level; delta_y = ElementPtr->life_span; orig_facing = facing = GetFrameIndex (ElementPtr->current.image.frame); if (((delta_y & 1) || ElementPtr->hTarget || TrackShip (ElementPtr, &facing) >= 0) && (delta_x == 0 || delta_y >= ONE_WAY_FLIGHT)) ElementPtr->state_flags |= IGNORE_SIMILAR; else if (delta_x) { LockElement (StarShipPtr->hShip, &eptr); delta_x = eptr->current.location.x - ElementPtr->current.location.x; delta_y = eptr->current.location.y - ElementPtr->current.location.y; UnlockElement (StarShipPtr->hShip); delta_x = WRAP_DELTA_X (delta_x); delta_y = WRAP_DELTA_Y (delta_y); facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) ); #ifdef NEVER if (delta_x < 0) delta_x = -delta_x; if (delta_y < 0) delta_y = -delta_y; if (delta_x <= LASER_RANGE && delta_y <= LASER_RANGE) #endif /* NEVER */ ElementPtr->state_flags &= ~IGNORE_SIMILAR; Enroute = FALSE; } if (ElementPtr->thrust_wait > 0) --ElementPtr->thrust_wait; if (ElementPtr->hTarget) { LockElement (ElementPtr->hTarget, &eptr); delta_x = eptr->current.location.x - ElementPtr->current.location.x; delta_y = eptr->current.location.y - ElementPtr->current.location.y; UnlockElement (ElementPtr->hTarget); delta_x = WRAP_DELTA_X (delta_x); delta_y = WRAP_DELTA_Y (delta_y); if (ElementPtr->thrust_wait == 0 && abs (delta_x) < LASER_RANGE * 3 / 4 && abs (delta_y) < LASER_RANGE * 3 / 4 && delta_x * delta_x + delta_y * delta_y < (LASER_RANGE * 3 / 4) * (LASER_RANGE * 3 / 4)) { ElementPtr->thrust_wait = (BYTE)NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) ); ElementPtr->postprocess_func = fighter_postprocess; } if (Enroute) { facing = GetFrameIndex (eptr->current.image.frame); if (ElementPtr->turn_wait & LEFT) { delta_x += COSINE (FACING_TO_ANGLE (facing - 4), DISPLAY_TO_WORLD (30)); delta_y += SINE (FACING_TO_ANGLE (facing - 4), DISPLAY_TO_WORLD (30)); } else { delta_x += COSINE (FACING_TO_ANGLE (facing + 4), DISPLAY_TO_WORLD (30)); delta_y += SINE (FACING_TO_ANGLE (facing + 4), DISPLAY_TO_WORLD (30)); } facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) ); } } ElementPtr->state_flags |= CHANGING; if (facing != orig_facing) ElementPtr->next.image.frame = SetAbsFrameIndex ( ElementPtr->next.image.frame, facing ); SetVelocityVector ( &ElementPtr->velocity, FIGHTER_SPEED, facing ); } } static void fighter_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr0, &StarShipPtr); if (GRAVITY_MASS (ElementPtr1->mass_points)) { HELEMENT hFighterElement; hFighterElement = AllocElement (); if (hFighterElement) { COUNT primIndex, travel_facing; SIZE delta_facing; ELEMENTPTR FighterElementPtr; LockElement (hFighterElement, &FighterElementPtr); primIndex = FighterElementPtr->PrimIndex; *FighterElementPtr = *ElementPtr0; FighterElementPtr->PrimIndex = primIndex; (GLOBAL (DisplayArray))[primIndex] = (GLOBAL (DisplayArray))[ElementPtr0->PrimIndex]; FighterElementPtr->state_flags &= ~PRE_PROCESS; FighterElementPtr->state_flags |= CHANGING; FighterElementPtr->next = FighterElementPtr->current; travel_facing = GetVelocityTravelAngle ( &FighterElementPtr->velocity ); delta_facing = NORMALIZE_ANGLE ( ARCTAN (pPt1->x - pPt0->x, pPt1->y - pPt0->y) - travel_facing); if (delta_facing == 0) { if (FighterElementPtr->turn_wait & LEFT) travel_facing -= QUADRANT; else travel_facing += QUADRANT; } else if (delta_facing <= HALF_CIRCLE) travel_facing -= QUADRANT; else travel_facing += QUADRANT; travel_facing = NORMALIZE_FACING (ANGLE_TO_FACING ( NORMALIZE_ANGLE (travel_facing) )); FighterElementPtr->next.image.frame = SetAbsFrameIndex (FighterElementPtr->next.image.frame, travel_facing); SetVelocityVector (&FighterElementPtr->velocity, FIGHTER_SPEED, travel_facing); UnlockElement (hFighterElement); PutElement (hFighterElement); } ElementPtr0->state_flags |= DISAPPEARING | COLLISION; } else if (ElementPtr0->pParent != ElementPtr1->pParent) { ElementPtr0->blast_offset = 0; weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); ElementPtr0->state_flags |= DISAPPEARING | COLLISION; } else if (ElementPtr1->state_flags & PLAYER_SHIP) { ProcessSound (SetAbsSoundIndex ( /* FIGHTERS_RETURN */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 3), ElementPtr1); DeltaCrew (ElementPtr1, 1); ElementPtr0->state_flags |= DISAPPEARING | COLLISION; } if (ElementPtr0->state_flags & DISAPPEARING) { ElementPtr0->state_flags &= ~DISAPPEARING; ElementPtr0->hit_points = 0; ElementPtr0->life_span = 0; ElementPtr0->state_flags |= NONSOLID; --StarShipPtr->RaceDescPtr->characteristics.special_wait; } } static void spawn_fighters (PELEMENT ElementPtr) { SIZE i; COUNT facing; SIZE delta_x, delta_y; HELEMENT hFighterElement; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); facing = StarShipPtr->ShipFacing + ANGLE_TO_FACING (HALF_CIRCLE); delta_x = COSINE (FACING_TO_ANGLE (facing), DISPLAY_TO_WORLD (14)); delta_y = SINE (FACING_TO_ANGLE (facing), DISPLAY_TO_WORLD (14)); i = ElementPtr->crew_level > 2 ? 2 : 1; while (i-- && (hFighterElement = AllocElement ())) { SIZE sx, sy; COUNT fighter_facing; ELEMENTPTR FighterElementPtr; DeltaCrew (ElementPtr, -1); PutElement (hFighterElement); LockElement (hFighterElement, &FighterElementPtr); FighterElementPtr->hit_points = 1; FighterElementPtr->mass_points = 0; FighterElementPtr->thrust_wait = TRACK_THRESHOLD + 1; FighterElementPtr->state_flags = APPEARING | FINITE_LIFE | CREW_OBJECT | IGNORE_SIMILAR | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); FighterElementPtr->life_span = FIGHTER_LIFE; SetPrimType (&(GLOBAL (DisplayArray))[FighterElementPtr->PrimIndex], STAMP_PRIM); { FighterElementPtr->preprocess_func = fighter_preprocess; FighterElementPtr->postprocess_func = 0; FighterElementPtr->collision_func = fighter_collision; FighterElementPtr->death_func = NULL_PTR; } FighterElementPtr->current.location = ElementPtr->next.location; if (i == 1) { FighterElementPtr->turn_wait = LEFT; fighter_facing = NORMALIZE_FACING (facing + 2); FighterElementPtr->current.location.x += delta_x - delta_y; FighterElementPtr->current.location.y += delta_y + delta_x; } else { FighterElementPtr->turn_wait = RIGHT; fighter_facing = NORMALIZE_FACING (facing - 2); FighterElementPtr->current.location.x += delta_x + delta_y; FighterElementPtr->current.location.y += delta_y - delta_x; } sx = COSINE (FACING_TO_ANGLE (fighter_facing), WORLD_TO_VELOCITY (FIGHTER_SPEED)); sy = SINE (FACING_TO_ANGLE (fighter_facing), WORLD_TO_VELOCITY (FIGHTER_SPEED)); SetVelocityComponents (&FighterElementPtr->velocity, sx, sy); FighterElementPtr->current.location.x -= VELOCITY_TO_WORLD (sx); FighterElementPtr->current.location.y -= VELOCITY_TO_WORLD (sy); FighterElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; FighterElementPtr->current.image.frame = SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], fighter_facing); SetElementStarShip (FighterElementPtr, StarShipPtr); UnlockElement (hFighterElement); } } static void urquan_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { PEVALUATE_DESC lpEvalDesc; STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); ObjectsOfConcern[ENEMY_SHIP_INDEX].MoveState = PURSUE; lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE && (!(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT) || lpEvalDesc->which_turn <= 8) && (!(lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) || (lpEvalDesc->ObjectPtr->mass_points >= 4 && lpEvalDesc->which_turn == 2 && ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn > 16))) lpEvalDesc->MoveState = PURSUE; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; { STARSHIPPTR EnemyStarShipPtr; if (lpEvalDesc->ObjectPtr) GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if (StarShipPtr->special_counter == 0 && lpEvalDesc->ObjectPtr && StarShipPtr->RaceDescPtr->ship_info.crew_level > (StarShipPtr->RaceDescPtr->ship_info.max_crew >> 2) && !(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & POINT_DEFENSE) && (StarShipPtr->RaceDescPtr->characteristics.special_wait < 6 || (MANEUVERABILITY ( &EnemyStarShipPtr->RaceDescPtr->cyborg_control ) <= SLOW_SHIP && !(EnemyStarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED)) || (lpEvalDesc->which_turn <= 12 && (StarShipPtr->ship_input_state & (LEFT | RIGHT)) && StarShipPtr->RaceDescPtr->ship_info.energy_level >= (BYTE)(StarShipPtr->RaceDescPtr->ship_info.max_energy >> 1)))) StarShipPtr->ship_input_state |= SPECIAL; else StarShipPtr->ship_input_state &= ~SPECIAL; } StarShipPtr->RaceDescPtr->characteristics.special_wait = 0; } static void urquan_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && ElementPtr->crew_level > 1 && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { ProcessSound (SetAbsSoundIndex ( /* LAUNCH_FIGHTERS */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); spawn_fighters (ElementPtr); StarShipPtr->special_counter = SPECIAL_WAIT; } } RACE_DESCPTR init_urquan (void) { RACE_DESCPTR RaceDescPtr; urquan_desc.postprocess_func = urquan_postprocess; urquan_desc.init_weapon_func = initialize_fusion; urquan_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) urquan_intelligence; RaceDescPtr = &urquan_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/urquan/igfxres.h0000600000175000017500000000106410543202074020066 0ustar joeyjoey#define URQUAN_ICON_MASK_PMAP_ANIM 0x00200002L #define URQUAN_MICON_MASK_PMAP_ANIM 0x00200102L #define URQUAN_BIG_MASK_PMAP_ANIM 0x00400202L #define URQUAN_MED_MASK_PMAP_ANIM 0x00400302L #define URQUAN_SML_MASK_PMAP_ANIM 0x00400402L #define FUSION_BIG_MASK_PMAP_ANIM 0x00400502L #define FUSION_MED_MASK_PMAP_ANIM 0x00400602L #define FUSION_SML_MASK_PMAP_ANIM 0x00400702L #define FIGHTER_BIG_MASK_PMAP_ANIM 0x00400802L #define FIGHTER_MED_MASK_PMAP_ANIM 0x00400902L #define FIGHTER_SML_MASK_PMAP_ANIM 0x00400a02L #define URQUAN_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/urquan/isndres.h0000600000175000017500000000005110543202074020061 0ustar joeyjoey#define URQUAN_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/urquan/istrtab.h0000600000175000017500000000005210543202074020063 0ustar joeyjoey#define URQUAN_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/urquan/imusicre.h0000600000175000017500000000005210543202074020233 0ustar joeyjoey#define URQUAN_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/urquan/icode.h0000600000175000017500000000004210543202074017475 0ustar joeyjoey#define URQUAN_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/urquan/urquan.res0000600000175000017500000000150710543202074020276 0ustar joeyjoeyINCLUDE ../star3do.typ PATH urquan PACKAGE URQUAN_CODE_PACKAGE urquan.shp CODE URQUAN_CODE urquan.cod GFXRES URQUAN_ICON_MASK_PMAP_ANIM urqicons.ani GFXRES URQUAN_MICON_MASK_PMAP_ANIM urqmicon.ani STRTAB URQUAN_RACE_STRINGS urqtext.txt PACKAGE URQUAN_PACKAGE urquan.shp GFXRES URQUAN_BIG_MASK_PMAP_ANIM urquan.big GFXRES URQUAN_MED_MASK_PMAP_ANIM urquan.med GFXRES URQUAN_SML_MASK_PMAP_ANIM urquan.sml GFXRES FUSION_BIG_MASK_PMAP_ANIM fusion.big GFXRES FUSION_MED_MASK_PMAP_ANIM fusion.med GFXRES FUSION_SML_MASK_PMAP_ANIM fusion.sml GFXRES FIGHTER_BIG_MASK_PMAP_ANIM fight.big GFXRES FIGHTER_MED_MASK_PMAP_ANIM fight.med GFXRES FIGHTER_SML_MASK_PMAP_ANIM fight.sml GFXRES URQUAN_CAPTAIN_MASK_PMAP_ANIM urqcap.ani SNDRES URQUAN_SHIP_SOUNDS urqsound.snd MUSICRES URQUAN_VICTORY_SONG urqditty.mod uqm-0.6.2/sc2/src/sc2code/ships/urquan/Makeinfo0000600000175000017500000000002610543202074017717 0ustar joeyjoeyuqm_CFILES="urquan.c" uqm-0.6.2/sc2/src/sc2code/ships/urquan/respkg.h0000600000175000017500000000006510543202074017712 0ustar joeyjoeyenum { URQUAN_CODE_PACKAGE = 1, URQUAN_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/urquan/resinst.h0000600000175000017500000000015010543202074020101 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/arilou/0000755000175000017500000000000010552600274016241 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/arilou/restypes.h0000600000175000017500000000024110543202063020247 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/arilou/igfxres.h0000600000175000017500000000064110543202063020044 0ustar joeyjoey#define ARILOU_ICON_MASK_PMAP_ANIM 0x00200002L #define ARILOU_MICON_MASK_PMAP_ANIM 0x00200102L #define ARILOU_BIG_MASK_PMAP_ANIM 0x00400202L #define ARILOU_MED_MASK_PMAP_ANIM 0x00400302L #define ARILOU_SML_MASK_PMAP_ANIM 0x00400402L #define WARP_BIG_MASK_PMAP_ANIM 0x00400502L #define WARP_MED_MASK_PMAP_ANIM 0x00400602L #define WARP_SML_MASK_PMAP_ANIM 0x00400702L #define ARILOU_CAPTAIN_MASK_PMAP_ANIM 0x00400802L uqm-0.6.2/sc2/src/sc2code/ships/arilou/isndres.h0000600000175000017500000000005110543202063020037 0ustar joeyjoey#define ARILOU_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/arilou/istrtab.h0000600000175000017500000000005210543202063020041 0ustar joeyjoey#define ARILOU_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/arilou/imusicre.h0000600000175000017500000000005210543202063020211 0ustar joeyjoey#define ARILOU_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/arilou/icode.h0000600000175000017500000000004210543202063017453 0ustar joeyjoey#define ARILOU_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/arilou/arilou.c0000600000175000017500000001771710543202063017677 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/arilou/resinst.h" #include "libs/mathlib.h" #define MAX_CREW 6 #define MAX_ENERGY 20 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 2 #define SPECIAL_ENERGY_COST 3 #define ENERGY_WAIT 6 #define MAX_THRUST /* DISPLAY_TO_WORLD (10) */ 40 #define THRUST_INCREMENT MAX_THRUST #define TURN_WAIT 0 #define THRUST_WAIT 0 #define WEAPON_WAIT 1 #define SPECIAL_WAIT 2 #define SHIP_MASS 1 #define ARILOU_OFFSET 9 #define LASER_RANGE DISPLAY_TO_WORLD (100 + ARILOU_OFFSET) static RACE_DESC arilou_desc = { { /* FIRES_FORE | */ IMMEDIATE_WEAPON, 16, /* Super Melee cost */ 250 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 438, 6372, }, (STRING)ARILOU_RACE_STRINGS, (FRAME)ARILOU_ICON_MASK_PMAP_ANIM, (FRAME)ARILOU_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)ARILOU_BIG_MASK_PMAP_ANIM, (FRAME)ARILOU_MED_MASK_PMAP_ANIM, (FRAME)ARILOU_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)WARP_BIG_MASK_PMAP_ANIM, (FRAME)WARP_MED_MASK_PMAP_ANIM, (FRAME)WARP_SML_MASK_PMAP_ANIM, }, { (FRAME)ARILOU_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)ARILOU_VICTORY_SONG, (SOUND)ARILOU_SHIP_SOUNDS, }, { 0, LASER_RANGE >> 1, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static COUNT initialize_autoaim_laser (PELEMENT ShipPtr, HELEMENT LaserArray[]) { COUNT orig_facing; SIZE delta_facing; STARSHIPPTR StarShipPtr; LASER_BLOCK LaserBlock; GetElementStarShip (ShipPtr, &StarShipPtr); LaserBlock.face = orig_facing = StarShipPtr->ShipFacing; if ((delta_facing = TrackShip (ShipPtr, &LaserBlock.face)) > 0) LaserBlock.face = NORMALIZE_FACING (orig_facing + delta_facing); ShipPtr->hTarget = 0; LaserBlock.cx = ShipPtr->next.location.x; LaserBlock.cy = ShipPtr->next.location.y; LaserBlock.ex = COSINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); LaserBlock.ey = SINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); LaserBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; LaserBlock.pixoffs = ARILOU_OFFSET; LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E); LaserArray[0] = initialize_laser (&LaserBlock); return (1); } static void arilou_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->ship_input_state |= THRUST; ObjectsOfConcern[ENEMY_SHIP_INDEX].MoveState = ENTICE; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (StarShipPtr->special_counter == 0) { PEVALUATE_DESC lpEvalDesc; StarShipPtr->ship_input_state &= ~SPECIAL; lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 6) { BOOLEAN IsTrackingWeapon; STARSHIPPTR EnemyStarShipPtr; GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if (((EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_WEAPON) && lpEvalDesc->ObjectPtr->next.image.farray == EnemyStarShipPtr->RaceDescPtr->ship_data.weapon) || ((EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_SPECIAL) && lpEvalDesc->ObjectPtr->next.image.farray == EnemyStarShipPtr->RaceDescPtr->ship_data.special)) IsTrackingWeapon = TRUE; else IsTrackingWeapon = FALSE; if (((lpEvalDesc->ObjectPtr->state_flags & PLAYER_SHIP) /* means IMMEDIATE WEAPON */ || (IsTrackingWeapon && (lpEvalDesc->which_turn == 1 || (lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT))) /* FIGHTERS!!! */ || PlotIntercept (lpEvalDesc->ObjectPtr, ShipPtr, 3, 0)) && !(TFB_Random () & 3)) { StarShipPtr->ship_input_state &= ~(LEFT | RIGHT | THRUST | WEAPON); StarShipPtr->ship_input_state |= SPECIAL; } } } if (StarShipPtr->RaceDescPtr->ship_info.energy_level <= SPECIAL_ENERGY_COST << 1) StarShipPtr->ship_input_state &= ~WEAPON; } static void arilou_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (!(ElementPtr->state_flags & NONSOLID)) { if (ElementPtr->thrust_wait == 0) { ZeroVelocityComponents (&ElementPtr->velocity); StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; } if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { #define HYPER_LIFE 5 ZeroVelocityComponents (&ElementPtr->velocity); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | LEFT | RIGHT | THRUST | WEAPON); ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; ElementPtr->life_span = HYPER_LIFE; ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; ElementPtr->next.image.frame = StarShipPtr->RaceDescPtr->ship_data.special[0]; ProcessSound (SetAbsSoundIndex ( /* HYPERJUMP */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } else if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) { COUNT life_span; StarShipPtr->cur_status_flags = (StarShipPtr->cur_status_flags & ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL)) | (StarShipPtr->old_status_flags & (LEFT | RIGHT | THRUST | WEAPON | SPECIAL)); ++StarShipPtr->weapon_counter; ++StarShipPtr->special_counter; ++StarShipPtr->energy_counter; ++ElementPtr->turn_wait; ++ElementPtr->thrust_wait; if ((life_span = ElementPtr->life_span) == NORMAL_LIFE) { ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE); ElementPtr->state_flags |= APPEARING; ElementPtr->current.image.farray = ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; ElementPtr->current.image.frame = ElementPtr->next.image.frame = SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], StarShipPtr->ShipFacing); InitIntersectStartPoint (ElementPtr); } else { --life_span; if (life_span != 2) { if (life_span < 2) ElementPtr->next.image.frame = DecFrameIndex (ElementPtr->next.image.frame); else ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->next.image.frame); } else { ElementPtr->next.location.x = WRAP_X (DISPLAY_ALIGN_X (TFB_Random ())); ElementPtr->next.location.y = WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ())); } } ElementPtr->state_flags |= CHANGING; } } RACE_DESCPTR init_arilou (void) { RACE_DESCPTR RaceDescPtr; arilou_desc.preprocess_func = arilou_preprocess; arilou_desc.init_weapon_func = initialize_autoaim_laser; arilou_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) arilou_intelligence; RaceDescPtr = &arilou_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/arilou/arilou.res0000600000175000017500000000126310543202063020233 0ustar joeyjoeyINCLUDE ../star3do.typ PATH arilou PACKAGE ARILOU_CODE_PACKAGE arilou.shp CODE ARILOU_CODE arilou.cod GFXRES ARILOU_ICON_MASK_PMAP_ANIM ariicons.ani GFXRES ARILOU_MICON_MASK_PMAP_ANIM arimicon.ani STRTAB ARILOU_RACE_STRINGS aritext.txt PACKAGE ARILOU_PACKAGE arilou.shp GFXRES ARILOU_BIG_MASK_PMAP_ANIM arilou.big GFXRES ARILOU_MED_MASK_PMAP_ANIM arilou.med GFXRES ARILOU_SML_MASK_PMAP_ANIM arilou.sml GFXRES WARP_BIG_MASK_PMAP_ANIM warp.big GFXRES WARP_MED_MASK_PMAP_ANIM warp.med GFXRES WARP_SML_MASK_PMAP_ANIM warp.sml GFXRES ARILOU_CAPTAIN_MASK_PMAP_ANIM aricap.ani SNDRES ARILOU_SHIP_SOUNDS arisound.snd MUSICRES ARILOU_VICTORY_SONG ariditty.mod uqm-0.6.2/sc2/src/sc2code/ships/arilou/Makeinfo0000600000175000017500000000002610543202063017675 0ustar joeyjoeyuqm_CFILES="arilou.c" uqm-0.6.2/sc2/src/sc2code/ships/arilou/respkg.h0000600000175000017500000000006510543202063017670 0ustar joeyjoeyenum { ARILOU_CODE_PACKAGE = 1, ARILOU_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/arilou/resinst.h0000600000175000017500000000015010543202063020057 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/mycon/0000755000175000017500000000000010552600274016073 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/mycon/restypes.h0000600000175000017500000000024110543202061020077 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/mycon/igfxres.h0000600000175000017500000000064110543202061017674 0ustar joeyjoey#define MYCON_ICON_MASK_PMAP_ANIM 0x00200002L #define MYCON_MICON_MASK_PMAP_ANIM 0x00200102L #define MYCON_BIG_MASK_PMAP_ANIM 0x00400202L #define MYCON_MED_MASK_PMAP_ANIM 0x00400302L #define MYCON_SML_MASK_PMAP_ANIM 0x00400402L #define PLASMA_BIG_MASK_PMAP_ANIM 0x00400502L #define PLASMA_MED_MASK_PMAP_ANIM 0x00400602L #define PLASMA_SML_MASK_PMAP_ANIM 0x00400702L #define MYCON_CAPTAIN_MASK_PMAP_ANIM 0x00400802L uqm-0.6.2/sc2/src/sc2code/ships/mycon/isndres.h0000600000175000017500000000005010543202061017666 0ustar joeyjoey#define MYCON_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/mycon/istrtab.h0000600000175000017500000000005110543202061017670 0ustar joeyjoey#define MYCON_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/mycon/imusicre.h0000600000175000017500000000005110543202061020040 0ustar joeyjoey#define MYCON_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/mycon/icode.h0000600000175000017500000000004110543202061017302 0ustar joeyjoey#define MYCON_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/mycon/mycon.c0000600000175000017500000002375710543202061017362 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/mycon/resinst.h" #define MAX_CREW 20 #define MAX_ENERGY 40 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 20 #define SPECIAL_ENERGY_COST MAX_ENERGY #define ENERGY_WAIT 4 #define MAX_THRUST /* DISPLAY_TO_WORLD (7) */ 27 #define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 9 #define TURN_WAIT 6 #define THRUST_WAIT 6 #define WEAPON_WAIT 5 #define SPECIAL_WAIT 0 #define SHIP_MASS 7 #define NUM_PLASMAS 11 #define NUM_GLOBALLS 8 #define PLASMA_DURATION 13 #define MISSILE_LIFE (NUM_PLASMAS * PLASMA_DURATION) #define MISSILE_SPEED DISPLAY_TO_WORLD (8) static RACE_DESC mycon_desc = { { FIRES_FORE | SEEKING_WEAPON, 21, /* Super Melee cost */ 1070 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 6392, 2200, }, (STRING)MYCON_RACE_STRINGS, (FRAME)MYCON_ICON_MASK_PMAP_ANIM, (FRAME)MYCON_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)MYCON_BIG_MASK_PMAP_ANIM, (FRAME)MYCON_MED_MASK_PMAP_ANIM, (FRAME)MYCON_SML_MASK_PMAP_ANIM, }, { (FRAME)PLASMA_BIG_MASK_PMAP_ANIM, (FRAME)PLASMA_MED_MASK_PMAP_ANIM, (FRAME)PLASMA_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)MYCON_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)MYCON_VICTORY_SONG, (SOUND)MYCON_SHIP_SOUNDS, }, { 0, DISPLAY_TO_WORLD (800), NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define MISSILE_DAMAGE 10 #define TRACK_WAIT 1 static void plasma_preprocess (PELEMENT ElementPtr) { COUNT plasma_index; if (ElementPtr->mass_points > ElementPtr->hit_points) ElementPtr->life_span = ElementPtr->hit_points * PLASMA_DURATION; else ElementPtr->hit_points = (BYTE)((ElementPtr->life_span * MISSILE_DAMAGE + (MISSILE_LIFE - 1)) / MISSILE_LIFE); ElementPtr->mass_points = ElementPtr->hit_points; plasma_index = NUM_PLASMAS - ((ElementPtr->life_span + (PLASMA_DURATION - 1)) / PLASMA_DURATION); if (plasma_index != GetFrameIndex (ElementPtr->next.image.frame)) { ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->next.image.frame, plasma_index); ElementPtr->state_flags |= CHANGING; } if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { COUNT facing; facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity) )); if (TrackShip (ElementPtr, &facing) > 0) SetVelocityVector (&ElementPtr->velocity, MISSILE_SPEED, facing); ElementPtr->turn_wait = TRACK_WAIT; } } static void plasma_blast_preprocess (PELEMENT ElementPtr) { if (ElementPtr->life_span >= ElementPtr->thrust_wait) ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->next.image.frame); else ElementPtr->next.image.frame = DecFrameIndex (ElementPtr->next.image.frame); if (ElementPtr->hTarget) { ELEMENTPTR ShipPtr; LockElement (ElementPtr->hTarget, &ShipPtr); ElementPtr->next.location = ShipPtr->next.location; UnlockElement (ElementPtr->hTarget); } ElementPtr->state_flags |= CHANGING; } static void plasma_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { SIZE old_mass; HELEMENT hBlastElement; old_mass = (SIZE)ElementPtr0->mass_points; if ((ElementPtr0->pParent != ElementPtr1->pParent || (ElementPtr1->state_flags & PLAYER_SHIP)) && (hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1))) { SIZE num_animations; ELEMENTPTR BlastElementPtr; LockElement (hBlastElement, &BlastElementPtr); BlastElementPtr->pParent = ElementPtr0->pParent; if (!(ElementPtr1->state_flags & PLAYER_SHIP)) BlastElementPtr->hTarget = 0; else { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr1, &StarShipPtr); BlastElementPtr->hTarget = StarShipPtr->hShip; } BlastElementPtr->current.location = ElementPtr1->current.location; if ((num_animations = (old_mass * NUM_GLOBALLS + (MISSILE_DAMAGE - 1)) / MISSILE_DAMAGE) == 0) num_animations = 1; BlastElementPtr->thrust_wait = (BYTE)num_animations; BlastElementPtr->life_span = (num_animations << 1) - 1; { BlastElementPtr->preprocess_func = plasma_blast_preprocess; } BlastElementPtr->current.image.farray = ElementPtr0->next.image.farray; BlastElementPtr->current.image.frame = SetAbsFrameIndex (BlastElementPtr->current.image.farray[0], NUM_PLASMAS); UnlockElement (hBlastElement); } } static void mycon_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { STARSHIPPTR StarShipPtr; PEVALUATE_DESC lpEvalDesc; lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) { if ((lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) && !(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) lpEvalDesc->MoveState = AVOID; else lpEvalDesc->MoveState = PURSUE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); if (ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState == PURSUE) StarShipPtr->ship_input_state &= ~THRUST; /* don't pursue seekers */ lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->weapon_counter == 0 && lpEvalDesc->ObjectPtr && (lpEvalDesc->which_turn <= 16 || ShipPtr->crew_level == StarShipPtr->RaceDescPtr->ship_info.max_crew)) { COUNT travel_facing, direction_facing; SIZE delta_x, delta_y; travel_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (GetVelocityTravelAngle (&ShipPtr->velocity) + HALF_CIRCLE) ); delta_x = lpEvalDesc->ObjectPtr->current.location.x - ShipPtr->current.location.x; delta_y = lpEvalDesc->ObjectPtr->current.location.y - ShipPtr->current.location.y; direction_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) ); if (NORMALIZE_FACING (direction_facing - StarShipPtr->ShipFacing + ANGLE_TO_FACING (QUADRANT)) <= ANGLE_TO_FACING (HALF_CIRCLE) && (!(StarShipPtr->cur_status_flags & (SHIP_BEYOND_MAX_SPEED | SHIP_IN_GRAVITY_WELL)) || NORMALIZE_FACING (direction_facing - travel_facing + ANGLE_TO_FACING (OCTANT)) <= ANGLE_TO_FACING (QUADRANT))) StarShipPtr->ship_input_state |= WEAPON; } if (StarShipPtr->special_counter == 0) { StarShipPtr->ship_input_state &= ~SPECIAL; StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = DISPLAY_TO_WORLD (800); if (ShipPtr->crew_level < StarShipPtr->RaceDescPtr->ship_info.max_crew) { StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = MISSILE_SPEED * MISSILE_LIFE; if (StarShipPtr->RaceDescPtr->ship_info.energy_level >= SPECIAL_ENERGY_COST && !(StarShipPtr->ship_input_state & WEAPON)) StarShipPtr->ship_input_state |= SPECIAL; } } } static COUNT initialize_plasma (PELEMENT ShipPtr, HELEMENT PlasmaArray[]) { #define MYCON_OFFSET 24 #define MISSILE_OFFSET 0 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = 0; MissileBlock.sender = ShipPtr->state_flags & (GOOD_GUY | BAD_GUY); MissileBlock.pixoffs = MYCON_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_DAMAGE; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = plasma_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; PlasmaArray[0] = initialize_missile (&MissileBlock); if (PlasmaArray[0]) { ELEMENTPTR PlasmaPtr; LockElement (PlasmaArray[0], &PlasmaPtr); PlasmaPtr->collision_func = plasma_collision; PlasmaPtr->turn_wait = TRACK_WAIT + 2; UnlockElement (PlasmaArray[0]); } return (1); } static void mycon_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && ElementPtr->crew_level != StarShipPtr->RaceDescPtr->ship_info.max_crew && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { #define REGENERATION_AMOUNT 4 SIZE add_crew; ProcessSound (SetAbsSoundIndex ( /* GROW_NEW_CREW */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); if ((add_crew = REGENERATION_AMOUNT) > StarShipPtr->RaceDescPtr->ship_info.max_crew - ElementPtr->crew_level) add_crew = StarShipPtr->RaceDescPtr->ship_info.max_crew - ElementPtr->crew_level; DeltaCrew (ElementPtr, add_crew); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } RACE_DESCPTR init_mycon (void) { RACE_DESCPTR RaceDescPtr; mycon_desc.postprocess_func = mycon_postprocess; mycon_desc.init_weapon_func = initialize_plasma; mycon_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) mycon_intelligence; RaceDescPtr = &mycon_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/mycon/mycon.res0000600000175000017500000000125210543202061017713 0ustar joeyjoeyINCLUDE ../star3do.typ PATH mycon PACKAGE MYCON_CODE_PACKAGE mycon.shp CODE MYCON_CODE mycon.cod GFXRES MYCON_ICON_MASK_PMAP_ANIM mycicons.ani GFXRES MYCON_MICON_MASK_PMAP_ANIM mycmicon.ani STRTAB MYCON_RACE_STRINGS myctext.txt PACKAGE MYCON_PACKAGE mycon.shp GFXRES MYCON_BIG_MASK_PMAP_ANIM mycon.big GFXRES MYCON_MED_MASK_PMAP_ANIM mycon.med GFXRES MYCON_SML_MASK_PMAP_ANIM mycon.sml GFXRES PLASMA_BIG_MASK_PMAP_ANIM plasma.big GFXRES PLASMA_MED_MASK_PMAP_ANIM plasma.med GFXRES PLASMA_SML_MASK_PMAP_ANIM plasma.sml GFXRES MYCON_CAPTAIN_MASK_PMAP_ANIM myccap.ani SNDRES MYCON_SHIP_SOUNDS mycsound.snd MUSICRES MYCON_VICTORY_SONG mycditty.mod uqm-0.6.2/sc2/src/sc2code/ships/mycon/Makeinfo0000600000175000017500000000002510543202061017524 0ustar joeyjoeyuqm_CFILES="mycon.c" uqm-0.6.2/sc2/src/sc2code/ships/mycon/respkg.h0000600000175000017500000000006310543202061017516 0ustar joeyjoeyenum { MYCON_CODE_PACKAGE = 1, MYCON_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/mycon/resinst.h0000600000175000017500000000015010543202061017707 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/druuge/0000755000175000017500000000000010552600274016241 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/druuge/restypes.h0000600000175000017500000000024110543202062020246 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/druuge/igfxres.h0000600000175000017500000000067110543202063020047 0ustar joeyjoey#define DRUUGE_ICON_MASK_PMAP_ANIM 0x00200002L #define DRUUGE_MICON_MASK_PMAP_ANIM 0x00200102L #define DRUUGE_BIG_MASK_PMAP_ANIM 0x00400202L #define DRUUGE_MED_MASK_PMAP_ANIM 0x00400302L #define DRUUGE_SML_MASK_PMAP_ANIM 0x00400402L #define DRUUGE_CANNON_BIG_MASK_PMAP_ANIM 0x00400502L #define DRUUGE_CANNON_MED_MASK_PMAP_ANIM 0x00400602L #define DRUUGE_CANNON_SML_MASK_PMAP_ANIM 0x00400702L #define DRUUGE_CAPT_MASK_PMAP_ANIM 0x00400802L uqm-0.6.2/sc2/src/sc2code/ships/druuge/isndres.h0000600000175000017500000000005110543202063020037 0ustar joeyjoey#define DRUUGE_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/druuge/druuge.c0000600000175000017500000002071110543202062017662 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/druuge/resinst.h" #define MAX_CREW 14 #define MAX_ENERGY 32 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 4 #define SPECIAL_ENERGY_COST 16 #define ENERGY_WAIT 50 #define MAX_THRUST 20 #define THRUST_INCREMENT 2 #define TURN_WAIT 4 #define THRUST_WAIT 1 #define WEAPON_WAIT 10 #define SPECIAL_WAIT 30 #define SHIP_MASS 5 #define MISSILE_SPEED DISPLAY_TO_WORLD (30) #define MISSILE_LIFE 20 #define MISSILE_RANGE (MISSILE_SPEED * MISSILE_LIFE) static RACE_DESC druuge_desc = { { FIRES_FORE, 17, /* Super Melee cost */ 1400 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 9500, 2792, }, (STRING)DRUUGE_RACE_STRINGS, (FRAME)DRUUGE_ICON_MASK_PMAP_ANIM, (FRAME)DRUUGE_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)DRUUGE_BIG_MASK_PMAP_ANIM, (FRAME)DRUUGE_MED_MASK_PMAP_ANIM, (FRAME)DRUUGE_SML_MASK_PMAP_ANIM, }, { (FRAME)DRUUGE_CANNON_BIG_MASK_PMAP_ANIM, (FRAME)DRUUGE_CANNON_MED_MASK_PMAP_ANIM, (FRAME)DRUUGE_CANNON_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)DRUUGE_CAPT_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)DRUUGE_VICTORY_SONG, (SOUND)DRUUGE_SHIP_SOUNDS, }, { 0, MISSILE_RANGE, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define RECOIL_VELOCITY WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (6)) #define MAX_RECOIL_VELOCITY (RECOIL_VELOCITY * 4) static void cannon_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if ((ElementPtr1->state_flags & PLAYER_SHIP) && ElementPtr1->crew_level && !GRAVITY_MASS (ElementPtr1->mass_points + 1)) { COUNT angle; SIZE cur_delta_x, cur_delta_y; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr1, &StarShipPtr); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); angle = FACING_TO_ANGLE ( GetFrameIndex (ElementPtr0->next.image.frame) ); DeltaVelocityComponents (&ElementPtr1->velocity, COSINE (angle, RECOIL_VELOCITY), SINE (angle, RECOIL_VELOCITY)); GetCurrentVelocityComponents (&ElementPtr1->velocity, &cur_delta_x, &cur_delta_y); if ((long)cur_delta_x * (long)cur_delta_x + (long)cur_delta_y * (long)cur_delta_y > (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY) { angle = ARCTAN (cur_delta_x, cur_delta_y); SetVelocityComponents (&ElementPtr1->velocity, COSINE (angle, MAX_RECOIL_VELOCITY), SINE (angle, MAX_RECOIL_VELOCITY)); } } } static COUNT initialize_cannon (PELEMENT ShipPtr, HELEMENT CannonArray[]) { #define DRUUGE_OFFSET 24 #define MISSILE_OFFSET 6 #define MISSILE_HITS 4 #define MISSILE_DAMAGE 6 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.index = MissileBlock.face; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = DRUUGE_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; CannonArray[0] = initialize_missile (&MissileBlock); if (CannonArray[0]) { ELEMENTPTR CannonPtr; LockElement (CannonArray[0], &CannonPtr); CannonPtr->collision_func = cannon_collision; UnlockElement (CannonArray[0]); } return (1); } static void druuge_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { UWORD ship_flags; STARSHIPPTR StarShipPtr, EnemyStarShipPtr; PEVALUATE_DESC lpEvalDesc; GetElementStarShip (ShipPtr, &StarShipPtr); ship_flags = 0; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED) lpEvalDesc->MoveState = ENTICE; else if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= WORLD_TO_TURN (MISSILE_RANGE * 3 / 4)) { GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); ship_flags = EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags; EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags &= ~(FIRES_FORE | FIRES_RIGHT | FIRES_AFT | FIRES_LEFT); lpEvalDesc->MoveState = PURSUE; if (ShipPtr->thrust_wait == 0) ++ShipPtr->thrust_wait; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (ship_flags) { EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags = ship_flags; } if (!(StarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED) && (lpEvalDesc->which_turn <= 12 || ( ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn <= 6 ))) { StarShipPtr->ship_input_state |= WEAPON; if (ShipPtr->thrust_wait < WEAPON_WAIT + 1) ShipPtr->thrust_wait = WEAPON_WAIT + 1; } if ((StarShipPtr->ship_input_state & WEAPON) && StarShipPtr->RaceDescPtr->ship_info.energy_level < WEAPON_ENERGY_COST && ShipPtr->crew_level > 1) StarShipPtr->ship_input_state |= SPECIAL; else StarShipPtr->ship_input_state &= ~SPECIAL; } static void druuge_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); /* if just fired cannon */ if ((StarShipPtr->cur_status_flags & WEAPON) && StarShipPtr->weapon_counter == StarShipPtr->RaceDescPtr->characteristics.weapon_wait) { COUNT angle; SIZE cur_delta_x, cur_delta_y; StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; DeltaVelocityComponents (&ElementPtr->velocity, COSINE (angle, RECOIL_VELOCITY), SINE (angle, RECOIL_VELOCITY)); GetCurrentVelocityComponents (&ElementPtr->velocity, &cur_delta_x, &cur_delta_y); if ((long)cur_delta_x * (long)cur_delta_x + (long)cur_delta_y * (long)cur_delta_y > (long)MAX_RECOIL_VELOCITY * (long)MAX_RECOIL_VELOCITY) { angle = ARCTAN (cur_delta_x, cur_delta_y); SetVelocityComponents (&ElementPtr->velocity, COSINE (angle, MAX_RECOIL_VELOCITY), SINE (angle, MAX_RECOIL_VELOCITY)); } } } static void druuge_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->cur_status_flags & SPECIAL) { if (StarShipPtr->special_counter || ElementPtr->crew_level == 1 || StarShipPtr->RaceDescPtr->ship_info.energy_level == StarShipPtr->RaceDescPtr->ship_info.max_energy) StarShipPtr->cur_status_flags &= ~SPECIAL; else { ProcessSound (SetAbsSoundIndex ( /* BURN UP CREW */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); DeltaCrew (ElementPtr, -1); DeltaEnergy (ElementPtr, SPECIAL_ENERGY_COST); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } } RACE_DESCPTR init_druuge (void) { RACE_DESCPTR RaceDescPtr; druuge_desc.preprocess_func = druuge_preprocess; druuge_desc.postprocess_func = druuge_postprocess; druuge_desc.init_weapon_func = initialize_cannon; druuge_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) druuge_intelligence; RaceDescPtr = &druuge_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/druuge/istrtab.h0000600000175000017500000000005210543202063020041 0ustar joeyjoey#define DRUUGE_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/druuge/imusicre.h0000600000175000017500000000005210543202062020210 0ustar joeyjoey#define DRUUGE_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/druuge/icode.h0000600000175000017500000000004210543202062017452 0ustar joeyjoey#define DRUUGE_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/druuge/Makeinfo0000600000175000017500000000002610543202062017674 0ustar joeyjoeyuqm_CFILES="druuge.c" uqm-0.6.2/sc2/src/sc2code/ships/druuge/respkg.h0000600000175000017500000000006510543202062017667 0ustar joeyjoeyenum { DRUUGE_CODE_PACKAGE = 1, DRUUGE_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/druuge/druuge.res0000600000175000017500000000131510543202062020230 0ustar joeyjoeyINCLUDE ../star3do.typ PATH druuge PACKAGE DRUUGE_CODE_PACKAGE druuge.shp CODE DRUUGE_CODE druuge.cod GFXRES DRUUGE_ICON_MASK_PMAP_ANIM druicons.ani GFXRES DRUUGE_MICON_MASK_PMAP_ANIM drumicon.ani STRTAB DRUUGE_RACE_STRINGS drutext.txt PACKAGE DRUUGE_PACKAGE druuge.shp GFXRES DRUUGE_BIG_MASK_PMAP_ANIM druuge.big GFXRES DRUUGE_MED_MASK_PMAP_ANIM druuge.med GFXRES DRUUGE_SML_MASK_PMAP_ANIM druuge.sml GFXRES DRUUGE_CANNON_BIG_MASK_PMAP_ANIM canbig.ani GFXRES DRUUGE_CANNON_MED_MASK_PMAP_ANIM canmed.ani GFXRES DRUUGE_CANNON_SML_MASK_PMAP_ANIM cansml.ani GFXRES DRUUGE_CAPT_MASK_PMAP_ANIM drucap.ani SNDRES DRUUGE_SHIP_SOUNDS drusound.snd MUSICRES DRUUGE_VICTORY_SONG druditty.mod uqm-0.6.2/sc2/src/sc2code/ships/druuge/resinst.h0000600000175000017500000000015010543202063020057 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/vux/0000755000175000017500000000000010552600274015570 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/vux/vux.c0000600000175000017500000002515210543202060016542 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/vux/resinst.h" #include "globdata.h" #include "libs/mathlib.h" #define MAX_CREW 20 #define MAX_ENERGY 40 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 1 #define SPECIAL_ENERGY_COST 2 #define ENERGY_WAIT 8 #define MAX_THRUST /* DISPLAY_TO_WORLD (5) */ 21 #define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 7 #define TURN_WAIT 6 #define THRUST_WAIT 4 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 7 #define SHIP_MASS 6 #define WARP_OFFSET 46 /* How far outside of laser-range ship can warp in */ #define VUX_OFFSET 12 #define LASER_BASE 150 #define LASER_RANGE DISPLAY_TO_WORLD (LASER_BASE + VUX_OFFSET) static RACE_DESC vux_desc = { { FIRES_FORE | SEEKING_SPECIAL | IMMEDIATE_WEAPON, 12, /* Super Melee cost */ 900 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 4412, 1558, }, (STRING)VUX_RACE_STRINGS, (FRAME)VUX_ICON_MASK_PMAP_ANIM, (FRAME)VUX_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)VUX_BIG_MASK_PMAP_ANIM, (FRAME)VUX_MED_MASK_PMAP_ANIM, (FRAME)VUX_SML_MASK_PMAP_ANIM, }, { (FRAME)SLIME_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, }, { (FRAME)LIMPETS_BIG_MASK_PMAP_ANIM, (FRAME)LIMPETS_MED_MASK_PMAP_ANIM, (FRAME)LIMPETS_SML_MASK_PMAP_ANIM, }, { (FRAME)VUX_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)VUX_VICTORY_SONG, (SOUND)VUX_SHIP_SOUNDS, }, { 0, CLOSE_RANGE_WEAPON, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define LIMPET_SPEED 25 static void limpet_preprocess (PELEMENT ElementPtr) { COUNT facing, orig_facing; SIZE delta_facing; facing = orig_facing = NORMALIZE_FACING (ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity) )); if ((delta_facing = TrackShip (ElementPtr, &facing)) > 0) { facing = orig_facing + delta_facing; SetVelocityVector (&ElementPtr->velocity, LIMPET_SPEED, facing); } ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->next.image.frame); ElementPtr->state_flags |= CHANGING; } static void limpet_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if (ElementPtr1->state_flags & PLAYER_SHIP) { STAMP s; STARSHIPPTR StarShipPtr; RACE_DESCPTR RDPtr; GetElementStarShip (ElementPtr1, &StarShipPtr); RDPtr = StarShipPtr->RaceDescPtr; if (++RDPtr->characteristics.turn_wait == 0) --RDPtr->characteristics.turn_wait; if (++RDPtr->characteristics.thrust_wait == 0) --RDPtr->characteristics.thrust_wait; #define MIN_THRUST_INCREMENT DISPLAY_TO_WORLD (1) if (RDPtr->characteristics.thrust_increment <= MIN_THRUST_INCREMENT) { RDPtr->characteristics.max_thrust = RDPtr->characteristics.thrust_increment << 1; } else { COUNT num_thrusts; num_thrusts = RDPtr->characteristics.max_thrust / RDPtr->characteristics.thrust_increment; --RDPtr->characteristics.thrust_increment; RDPtr->characteristics.max_thrust = RDPtr->characteristics.thrust_increment * num_thrusts; } RDPtr->cyborg_control.ManeuverabilityIndex = 0; GetElementStarShip (ElementPtr0, &StarShipPtr); ProcessSound (SetAbsSoundIndex ( /* LIMPET_AFFIXES */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), ElementPtr1); s.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.weapon[0], (COUNT)TFB_Random () ); ModifySilhouette (ElementPtr1, &s, MODIFY_IMAGE); } ElementPtr0->hit_points = 0; ElementPtr0->life_span = 0; ElementPtr0->state_flags |= COLLISION | DISAPPEARING; (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } static void spawn_limpets (PELEMENT ElementPtr) { #define LIMPET_OFFSET 8 #define LIMPET_LIFE 80 #define LIMPET_HITS 1 #define LIMPET_DAMAGE 0 HELEMENT Limpet; STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ElementPtr, &StarShipPtr); MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; MissileBlock.face = StarShipPtr->ShipFacing + HALF_CIRCLE; MissileBlock.index = 0; MissileBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = LIMPET_OFFSET; MissileBlock.speed = LIMPET_SPEED; MissileBlock.hit_points = LIMPET_HITS; MissileBlock.damage = LIMPET_DAMAGE; MissileBlock.life = LIMPET_LIFE; MissileBlock.preprocess_func = limpet_preprocess; MissileBlock.blast_offs = 0; MissileBlock.cx = ElementPtr->next.location.x; MissileBlock.cy = ElementPtr->next.location.y; Limpet = initialize_missile (&MissileBlock); if (Limpet) { ELEMENTPTR LimpetPtr; LockElement (Limpet, &LimpetPtr); LimpetPtr->collision_func = limpet_collision; SetElementStarShip (LimpetPtr, StarShipPtr); UnlockElement (Limpet); PutElement (Limpet); } } static COUNT initialize_horrific_laser (PELEMENT ShipPtr, HELEMENT LaserArray[]) { STARSHIPPTR StarShipPtr; LASER_BLOCK LaserBlock; GetElementStarShip (ShipPtr, &StarShipPtr); LaserBlock.face = StarShipPtr->ShipFacing; LaserBlock.cx = ShipPtr->next.location.x; LaserBlock.cy = ShipPtr->next.location.y; LaserBlock.ex = COSINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); LaserBlock.ey = SINE (FACING_TO_ANGLE (LaserBlock.face), LASER_RANGE); LaserBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; LaserBlock.pixoffs = VUX_OFFSET; LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x0A), 0x0A); LaserArray[0] = initialize_laser (&LaserBlock); return (1); } static void vux_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { PEVALUATE_DESC lpEvalDesc; STARSHIPPTR StarShipPtr; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; lpEvalDesc->MoveState = PURSUE; if (ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr != 0 && ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState == ENTICE) { if ((ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr->state_flags & FINITE_LIFE) && !(ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr->state_flags & CREW_OBJECT)) ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState = AVOID; else ObjectsOfConcern[ENEMY_WEAPON_INDEX].MoveState = PURSUE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->special_counter == 0 && lpEvalDesc->ObjectPtr != 0 && lpEvalDesc->which_turn <= 12 && (StarShipPtr->ship_input_state & (LEFT | RIGHT)) && StarShipPtr->RaceDescPtr->ship_info.energy_level >= (BYTE)(StarShipPtr->RaceDescPtr->ship_info.max_energy >> 1)) StarShipPtr->ship_input_state |= SPECIAL; else StarShipPtr->ship_input_state &= ~SPECIAL; } static void vux_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0 && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { ProcessSound (SetAbsSoundIndex ( /* LAUNCH_LIMPET */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); spawn_limpets (ElementPtr); StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } static void vux_preprocess (PELEMENT ElementPtr) { if (ElementPtr->state_flags & APPEARING) { COUNT facing; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); facing = StarShipPtr->ShipFacing; if (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER && TrackShip (ElementPtr, &facing) >= 0) { ELEMENTPTR OtherShipPtr; LockElement (ElementPtr->hTarget, &OtherShipPtr); do { // Originally, the warp distance was: // DISPLAY_TO_WORLD (SPACE_HEIGHT << 1) // where SPACE_HEIGHT = SCREEN_HEIGHT - (SAFE_Y * 2) // But in reality this should be relative to the laser-range #define MAXX_ENTRY_DIST DISPLAY_TO_WORLD ((LASER_BASE + VUX_OFFSET + WARP_OFFSET) << 1) #define MAXY_ENTRY_DIST DISPLAY_TO_WORLD ((LASER_BASE + VUX_OFFSET + WARP_OFFSET) << 1) SIZE dx, dy; ElementPtr->current.location.x = (OtherShipPtr->current.location.x - (MAXX_ENTRY_DIST >> 1)) + ((COUNT)TFB_Random () % MAXX_ENTRY_DIST); ElementPtr->current.location.y = (OtherShipPtr->current.location.y - (MAXY_ENTRY_DIST >> 1)) + ((COUNT)TFB_Random () % MAXY_ENTRY_DIST); dx = OtherShipPtr->current.location.x - ElementPtr->current.location.x; dy = OtherShipPtr->current.location.y - ElementPtr->current.location.y; facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (dx, dy)) ); ElementPtr->current.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, facing); ElementPtr->current.location.x = WRAP_X (DISPLAY_ALIGN (ElementPtr->current.location.x)); ElementPtr->current.location.y = WRAP_Y (DISPLAY_ALIGN (ElementPtr->current.location.y)); } while (CalculateGravity (ElementPtr) || TimeSpaceMatterConflict (ElementPtr)); UnlockElement (ElementPtr->hTarget); ElementPtr->hTarget = 0; ElementPtr->next = ElementPtr->current; InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); InitIntersectFrame (ElementPtr); StarShipPtr->ShipFacing = facing; } StarShipPtr->RaceDescPtr->preprocess_func = 0; } } RACE_DESCPTR init_vux (void) { RACE_DESCPTR RaceDescPtr; vux_desc.preprocess_func = vux_preprocess; vux_desc.postprocess_func = vux_postprocess; vux_desc.init_weapon_func = initialize_horrific_laser; vux_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) vux_intelligence; RaceDescPtr = &vux_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/vux/restypes.h0000600000175000017500000000024110543202060017573 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/vux/igfxres.h0000600000175000017500000000070110543202060017365 0ustar joeyjoey#define VUX_ICON_MASK_PMAP_ANIM 0x00200002L #define VUX_MICON_MASK_PMAP_ANIM 0x00200102L #define VUX_BIG_MASK_PMAP_ANIM 0x00400202L #define VUX_MED_MASK_PMAP_ANIM 0x00400302L #define VUX_SML_MASK_PMAP_ANIM 0x00400402L #define LIMPETS_BIG_MASK_PMAP_ANIM 0x00400502L #define LIMPETS_MED_MASK_PMAP_ANIM 0x00400602L #define LIMPETS_SML_MASK_PMAP_ANIM 0x00400702L #define SLIME_MASK_PMAP_ANIM 0x00400802L #define VUX_CAPTAIN_MASK_PMAP_ANIM 0x00400902L uqm-0.6.2/sc2/src/sc2code/ships/vux/isndres.h0000600000175000017500000000004610543202060017367 0ustar joeyjoey#define VUX_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/vux/istrtab.h0000600000175000017500000000004710543202060017371 0ustar joeyjoey#define VUX_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/vux/imusicre.h0000600000175000017500000000004710543202060017541 0ustar joeyjoey#define VUX_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/vux/icode.h0000600000175000017500000000003710543202060017003 0ustar joeyjoey#define VUX_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/vux/Makeinfo0000600000175000017500000000002310543202060017216 0ustar joeyjoeyuqm_CFILES="vux.c" uqm-0.6.2/sc2/src/sc2code/ships/vux/respkg.h0000600000175000017500000000005710543202060017215 0ustar joeyjoeyenum { VUX_CODE_PACKAGE = 1, VUX_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/vux/vux.res0000600000175000017500000000127010543202060017104 0ustar joeyjoeyINCLUDE ../star3do.typ PATH vux PACKAGE VUX_CODE_PACKAGE vux.shp CODE VUX_CODE vux.cod GFXRES VUX_ICON_MASK_PMAP_ANIM vuxicons.ani GFXRES VUX_MICON_MASK_PMAP_ANIM vuxmicon.ani STRTAB VUX_RACE_STRINGS vuxtext.txt PACKAGE VUX_PACKAGE vux.shp GFXRES VUX_BIG_MASK_PMAP_ANIM vux.big GFXRES VUX_MED_MASK_PMAP_ANIM vux.med GFXRES VUX_SML_MASK_PMAP_ANIM vux.sml GFXRES LIMPETS_BIG_MASK_PMAP_ANIM limpets.big GFXRES LIMPETS_MED_MASK_PMAP_ANIM limpets.med GFXRES LIMPETS_SML_MASK_PMAP_ANIM limpets.sml GFXRES SLIME_MASK_PMAP_ANIM slime.ani GFXRES VUX_CAPTAIN_MASK_PMAP_ANIM vuxcap.ani SNDRES VUX_SHIP_SOUNDS vuxsound.snd MUSICRES VUX_VICTORY_SONG vuxditty.mod uqm-0.6.2/sc2/src/sc2code/ships/vux/resinst.h0000600000175000017500000000015010543202060017403 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/slylandr/0000755000175000017500000000000010552600274016576 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/slylandr/restypes.h0000600000175000017500000000024110543202061020602 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/slylandr/slylandr.c0000600000175000017500000002544210543202061020561 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/slylandr/resinst.h" #include "globdata.h" #include "libs/mathlib.h" #define MAX_CREW 12 #define MAX_ENERGY 20 #define ENERGY_REGENERATION 0 #define WEAPON_ENERGY_COST 2 #define SPECIAL_ENERGY_COST 0 #define ENERGY_WAIT 10 #define MAX_THRUST 60 #define THRUST_INCREMENT MAX_THRUST #define TURN_WAIT 0 #define THRUST_WAIT 0 #define WEAPON_WAIT 17 #define SPECIAL_WAIT 20 #define SHIP_MASS 1 #define SLYLANDRO_OFFSET 9 static RACE_DESC slylandro_desc = { { SEEKING_WEAPON | CREW_IMMUNE, 17, /* Super Melee cost */ ~0, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 333, 9812, }, (STRING)SLYLANDRO_RACE_STRINGS, (FRAME)SLYLANDRO_ICON_MASK_PMAP_ANIM, (FRAME)SLYLANDRO_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)SLYLANDRO_BIG_MASK_PMAP_ANIM, (FRAME)SLYLANDRO_MED_MASK_PMAP_ANIM, (FRAME)SLYLANDRO_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)SLYLANDRO_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)SLYLANDRO_VICTORY_SONG, (SOUND)SLYLANDRO_SHIP_SOUNDS, }, { 0, CLOSE_RANGE_WEAPON << 1, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static COUNT initialize_lightning (PELEMENT ElementPtr, HELEMENT LaserArray[]); static void lightning_postprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait && !(ElementPtr->state_flags & COLLISION)) { HELEMENT Lightning; initialize_lightning (ElementPtr, &Lightning); if (Lightning) PutElement (Lightning); } } static void lightning_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr0, &StarShipPtr); if (StarShipPtr->weapon_counter > WEAPON_WAIT >> 1) StarShipPtr->weapon_counter = WEAPON_WAIT - StarShipPtr->weapon_counter; StarShipPtr->weapon_counter -= ElementPtr0->turn_wait; ElementPtr0->turn_wait = 0; weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); } static COUNT initialize_lightning (PELEMENT ElementPtr, HELEMENT LaserArray[]) { LASER_BLOCK LaserBlock; LaserBlock.cx = ElementPtr->next.location.x; LaserBlock.cy = ElementPtr->next.location.y; LaserBlock.ex = 0; LaserBlock.ey = 0; LaserBlock.sender = (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; LaserBlock.face = 0; LaserBlock.pixoffs = 0; LaserArray[0] = initialize_laser (&LaserBlock); if (LaserArray[0]) { SIZE delta; COUNT angle, facing; DWORD rand_val; ELEMENTPTR LaserPtr; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (LaserArray[0], &LaserPtr); LaserPtr->postprocess_func = lightning_postprocess; LaserPtr->collision_func = lightning_collision; rand_val = TFB_Random (); if (!(ElementPtr->state_flags & PLAYER_SHIP)) { angle = GetVelocityTravelAngle (&ElementPtr->velocity); facing = NORMALIZE_FACING (ANGLE_TO_FACING (angle)); delta = TrackShip (ElementPtr, &facing); LaserPtr->turn_wait = ElementPtr->turn_wait - 1; SetPrimColor (&(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], GetPrimColor (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex])); } else { facing = StarShipPtr->ShipFacing; ElementPtr->hTarget = 0; delta = TrackShip (ElementPtr, &facing); ElementPtr->hTarget = 0; angle = FACING_TO_ANGLE (facing); if ((LaserPtr->turn_wait = StarShipPtr->weapon_counter) == 0) LaserPtr->turn_wait = WEAPON_WAIT; if (LaserPtr->turn_wait > WEAPON_WAIT >> 1) LaserPtr->turn_wait = WEAPON_WAIT - LaserPtr->turn_wait; switch (HIBYTE (LOWORD (rand_val)) & 3) { case 0: SetPrimColor ( &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) ); break; case 1: SetPrimColor ( &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], BUILD_COLOR (MAKE_RGB15 (0x16, 0x17, 0x1F), 0x42) ); break; case 2: SetPrimColor ( &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], BUILD_COLOR (MAKE_RGB15 (0x06, 0x07, 0x1F), 0x4A) ); break; case 3: SetPrimColor ( &(GLOBAL (DisplayArray))[LaserPtr->PrimIndex], BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x18), 0x50) ); break; } } if (delta == -1 || delta == ANGLE_TO_FACING (HALF_CIRCLE)) angle += LOWORD (rand_val); else if (delta == 0) angle += LOWORD (rand_val) & 1 ? -1 : 1; else if (delta < ANGLE_TO_FACING (HALF_CIRCLE)) angle += LOWORD (rand_val) & (QUADRANT - 1); else angle -= LOWORD (rand_val) & (QUADRANT - 1); #define LASER_RANGE 32 delta = WORLD_TO_VELOCITY ( DISPLAY_TO_WORLD ((HIWORD (rand_val) & (LASER_RANGE - 1)) + 4) ); SetVelocityComponents (&LaserPtr->velocity, COSINE (angle, delta), SINE (angle, delta)); SetElementStarShip (LaserPtr, StarShipPtr); UnlockElement (LaserArray[0]); } return (1); } static void slylandro_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { PEVALUATE_DESC lpEvalDesc; STARSHIPPTR StarShipPtr; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER) /* no dodging in role playing game */ ObjectsOfConcern[ENEMY_WEAPON_INDEX].ObjectPtr = 0; lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->special_counter == 0 && StarShipPtr->RaceDescPtr->ship_info.energy_level == 0 && ObjectsOfConcern[GRAVITY_MASS_INDEX].ObjectPtr == 0) ConcernCounter = FIRST_EMPTY_INDEX + 1; if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == PURSUE && lpEvalDesc->which_turn <= 6) lpEvalDesc->MoveState = ENTICE; ++ShipPtr->thrust_wait; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); --ShipPtr->thrust_wait; if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 14) StarShipPtr->ship_input_state |= WEAPON; else StarShipPtr->ship_input_state &= ~WEAPON; StarShipPtr->ship_input_state &= ~SPECIAL; if (StarShipPtr->RaceDescPtr->ship_info.energy_level < StarShipPtr->RaceDescPtr->ship_info.max_energy) { lpEvalDesc = &ObjectsOfConcern[FIRST_EMPTY_INDEX]; if (lpEvalDesc->ObjectPtr && lpEvalDesc->which_turn <= 14) StarShipPtr->ship_input_state |= SPECIAL; } } static BOOLEAN harvest_space_junk (PELEMENT ElementPtr) { BOOLEAN retval; HELEMENT hElement, hNextElement; retval = FALSE; for (hElement = GetHeadElement (); hElement; hElement = hNextElement) { ELEMENTPTR ObjPtr; LockElement (hElement, &ObjPtr); hNextElement = GetSuccElement (ObjPtr); if (!(ObjPtr->state_flags & (APPEARING | GOOD_GUY | BAD_GUY | PLAYER_SHIP | FINITE_LIFE)) && !GRAVITY_MASS (ObjPtr->mass_points) && CollisionPossible (ObjPtr, ElementPtr)) { //HARVEST_RANGE was originally (SPACE_HEIGHT * 3 / 8) #define HARVEST_RANGE (208 * 3 / 8) SIZE dx, dy; if ((dx = ObjPtr->next.location.x - ElementPtr->next.location.x) < 0) dx = -dx; if ((dy = ObjPtr->next.location.y - ElementPtr->next.location.y) < 0) dy = -dy; dx = WORLD_TO_DISPLAY (dx); dy = WORLD_TO_DISPLAY (dy); if (dx <= HARVEST_RANGE && dy <= HARVEST_RANGE && dx * dx + dy * dy <= HARVEST_RANGE * HARVEST_RANGE) { ObjPtr->life_span = 0; ObjPtr->state_flags |= NONSOLID; if (!retval) { STARSHIPPTR StarShipPtr; retval = TRUE; GetElementStarShip (ElementPtr, &StarShipPtr); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); DeltaEnergy (ElementPtr, MAX_ENERGY); } } } UnlockElement (hElement); } return (retval); } static void slylandro_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->weapon_counter && StarShipPtr->weapon_counter < WEAPON_WAIT) { HELEMENT Lightning; initialize_lightning (ElementPtr, &Lightning); if (Lightning) PutElement (Lightning); } if (StarShipPtr->special_counter == 0 && (StarShipPtr->cur_status_flags & SPECIAL) && harvest_space_junk (ElementPtr)) { StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } static void slylandro_preprocess (PELEMENT ElementPtr) { if (!(ElementPtr->state_flags & (APPEARING | NONSOLID))) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & THRUST) && !(StarShipPtr->old_status_flags & THRUST)) StarShipPtr->ShipFacing += ANGLE_TO_FACING (HALF_CIRCLE); if (ElementPtr->turn_wait == 0) { ElementPtr->turn_wait += StarShipPtr->RaceDescPtr->characteristics.turn_wait + 1; if (StarShipPtr->cur_status_flags & LEFT) --StarShipPtr->ShipFacing; else if (StarShipPtr->cur_status_flags & RIGHT) ++StarShipPtr->ShipFacing; } StarShipPtr->ShipFacing = NORMALIZE_FACING (StarShipPtr->ShipFacing); if (ElementPtr->thrust_wait == 0) { ElementPtr->thrust_wait += StarShipPtr->RaceDescPtr->characteristics.thrust_wait + 1; SetVelocityVector (&ElementPtr->velocity, StarShipPtr->RaceDescPtr->characteristics.max_thrust, StarShipPtr->ShipFacing); StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED; StarShipPtr->cur_status_flags &= ~SHIP_IN_GRAVITY_WELL; } ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->next.image.frame); ElementPtr->state_flags |= CHANGING; } } RACE_DESCPTR init_slylandro (void) { RACE_DESCPTR RaceDescPtr; slylandro_desc.preprocess_func = slylandro_preprocess; slylandro_desc.postprocess_func = slylandro_postprocess; slylandro_desc.init_weapon_func = initialize_lightning; slylandro_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) slylandro_intelligence; RaceDescPtr = &slylandro_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/slylandr/igfxres.h0000600000175000017500000000045710543202061020404 0ustar joeyjoey#define SLYLANDRO_ICON_MASK_PMAP_ANIM 0x00200002L #define SLYLANDRO_MICON_MASK_PMAP_ANIM 0x00200102L #define SLYLANDRO_BIG_MASK_PMAP_ANIM 0x00400202L #define SLYLANDRO_MED_MASK_PMAP_ANIM 0x00400302L #define SLYLANDRO_SML_MASK_PMAP_ANIM 0x00400402L #define SLYLANDRO_CAPTAIN_MASK_PMAP_ANIM 0x00400502L uqm-0.6.2/sc2/src/sc2code/ships/slylandr/isndres.h0000600000175000017500000000005410543202061020375 0ustar joeyjoey#define SLYLANDRO_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/slylandr/slylandr.res0000600000175000017500000000114410543202061021121 0ustar joeyjoeyINCLUDE ../star3do.typ PATH slylandr PACKAGE SLYLANDRO_CODE_PACKAGE slylandr.shp CODE SLYLANDRO_CODE slylandr.cod GFXRES SLYLANDRO_ICON_MASK_PMAP_ANIM slyicons.ani GFXRES SLYLANDRO_MICON_MASK_PMAP_ANIM slymicon.ani STRTAB SLYLANDRO_RACE_STRINGS slytext.txt PACKAGE SLYLANDRO_PACKAGE slylandr.shp GFXRES SLYLANDRO_BIG_MASK_PMAP_ANIM slylandr.big GFXRES SLYLANDRO_MED_MASK_PMAP_ANIM slylandr.med GFXRES SLYLANDRO_SML_MASK_PMAP_ANIM slylandr.sml GFXRES SLYLANDRO_CAPTAIN_MASK_PMAP_ANIM slycap.ani SNDRES SLYLANDRO_SHIP_SOUNDS slysound.snd MUSICRES SLYLANDRO_VICTORY_SONG slyditty.mod uqm-0.6.2/sc2/src/sc2code/ships/slylandr/istrtab.h0000600000175000017500000000005510543202061020377 0ustar joeyjoey#define SLYLANDRO_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/slylandr/imusicre.h0000600000175000017500000000005510543202061020547 0ustar joeyjoey#define SLYLANDRO_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/slylandr/icode.h0000600000175000017500000000004510543202061020011 0ustar joeyjoey#define SLYLANDRO_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/slylandr/Makeinfo0000600000175000017500000000003010543202061020223 0ustar joeyjoeyuqm_CFILES="slylandr.c" uqm-0.6.2/sc2/src/sc2code/ships/slylandr/respkg.h0000600000175000017500000000007310543202061020222 0ustar joeyjoeyenum { SLYLANDRO_CODE_PACKAGE = 1, SLYLANDRO_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/slylandr/resinst.h0000600000175000017500000000015010543202061020412 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/pkunk/0000755000175000017500000000000010552600274016076 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/pkunk/pkunk.res0000600000175000017500000000124310543202061017721 0ustar joeyjoeyINCLUDE ../star3do.typ PATH pkunk PACKAGE PKUNK_CODE_PACKAGE pkunk.shp CODE PKUNK_CODE pkunk.cod GFXRES PKUNK_ICON_MASK_PMAP_ANIM pkuicons.ani GFXRES PKUNK_MICON_MASK_PMAP_ANIM pkumicon.ani STRTAB PKUNK_RACE_STRINGS pkutext.txt PACKAGE PKUNK_PACKAGE pkunk.shp GFXRES PKUNK_BIG_MASK_PMAP_ANIM pkunk.big GFXRES PKUNK_MED_MASK_PMAP_ANIM pkunk.med GFXRES PKUNK_SML_MASK_PMAP_ANIM pkunk.sml GFXRES BUG_BIG_MASK_PMAP_ANIM bugbig.ani GFXRES BUG_MED_MASK_PMAP_ANIM bugmed.ani GFXRES BUG_SML_MASK_PMAP_ANIM bugsml.ani GFXRES PKUNK_CAPTAIN_MASK_PMAP_ANIM pkucap.ani SNDRES PKUNK_SHIP_SOUNDS pkusound.snd MUSICRES PKUNK_VICTORY_SONG pkuditty.mod uqm-0.6.2/sc2/src/sc2code/ships/pkunk/pkunk.c0000600000175000017500000003620510543202061017360 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/pkunk/resinst.h" #include "globdata.h" #include "libs/mathlib.h" #define MAX_CREW 8 #define MAX_ENERGY 12 #define ENERGY_REGENERATION 0 #define WEAPON_ENERGY_COST 1 #define SPECIAL_ENERGY_COST 2 #define ENERGY_WAIT 0 #define MAX_THRUST 64 #define THRUST_INCREMENT 16 #define TURN_WAIT 0 #define THRUST_WAIT 0 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 16 #define SHIP_MASS 1 #define MISSILE_SPEED DISPLAY_TO_WORLD (24) #define MISSILE_LIFE 5 static RACE_DESC pkunk_desc = { { FIRES_FORE | FIRES_LEFT | FIRES_RIGHT, 20, /* Super Melee cost */ 666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 502, 401, }, (STRING)PKUNK_RACE_STRINGS, (FRAME)PKUNK_ICON_MASK_PMAP_ANIM, (FRAME)PKUNK_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, 0, /* SPECIAL_WAIT */ SHIP_MASS, }, { { (FRAME)PKUNK_BIG_MASK_PMAP_ANIM, (FRAME)PKUNK_MED_MASK_PMAP_ANIM, (FRAME)PKUNK_SML_MASK_PMAP_ANIM, }, { (FRAME)BUG_BIG_MASK_PMAP_ANIM, (FRAME)BUG_MED_MASK_PMAP_ANIM, (FRAME)BUG_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)PKUNK_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)PKUNK_VICTORY_SONG, (SOUND)PKUNK_SHIP_SOUNDS, }, { 0, CLOSE_RANGE_WEAPON + 1, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static void animate (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = ElementPtr->next_turn; } } static COUNT initialize_bug_missile (PELEMENT ShipPtr, HELEMENT MissileArray[]) { #define PKUNK_OFFSET 15 #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 1 COUNT i; STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.index = 0; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = PKUNK_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; for (i = 0; i < 3; ++i) { MissileBlock.face = StarShipPtr->ShipFacing + (ANGLE_TO_FACING (QUADRANT) * i); if (i == 2) MissileBlock.face += ANGLE_TO_FACING (QUADRANT); MissileBlock.face = NORMALIZE_FACING (MissileBlock.face); if ((MissileArray[i] = initialize_missile (&MissileBlock))) { SIZE dx, dy; ELEMENTPTR MissilePtr; LockElement (MissileArray[i], &MissilePtr); GetCurrentVelocityComponents (&ShipPtr->velocity, &dx, &dy); DeltaVelocityComponents (&MissilePtr->velocity, dx, dy); MissilePtr->current.location.x -= VELOCITY_TO_WORLD (dx); MissilePtr->current.location.y -= VELOCITY_TO_WORLD (dy); MissilePtr->preprocess_func = animate; UnlockElement (MissileArray[i]); } } return (3); } static HELEMENT hPhoenix = 0; static void pkunk_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); if (hPhoenix && StarShipPtr->special_counter) { RemoveElement (hPhoenix); FreeElement (hPhoenix); hPhoenix = 0; } if (StarShipPtr->RaceDescPtr->ship_info.energy_level < StarShipPtr->RaceDescPtr->ship_info.max_energy && (StarShipPtr->special_counter == 0 || (BYTE)TFB_Random () < 20)) StarShipPtr->ship_input_state |= SPECIAL; else StarShipPtr->ship_input_state &= ~SPECIAL; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); } static void pkunk_preprocess (PELEMENT ElementPtr); static void pkunk_postprocess (PELEMENT ElementPtr); static void new_pkunk (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (!(ElementPtr->state_flags & PLAYER_SHIP)) { ELEMENTPTR ShipPtr; LockElement (StarShipPtr->hShip, &ShipPtr); ShipPtr->death_func = new_pkunk; UnlockElement (StarShipPtr->hShip); } else { ElementPtr->state_flags = APPEARING | PLAYER_SHIP | IGNORE_SIMILAR | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); ElementPtr->mass_points = SHIP_MASS; ElementPtr->preprocess_func = StarShipPtr->RaceDescPtr->preprocess_func; ElementPtr->postprocess_func = StarShipPtr->RaceDescPtr->postprocess_func; ElementPtr->death_func = (void (*) (PELEMENT ElementPtr)) StarShipPtr->RaceDescPtr->init_weapon_func; StarShipPtr->RaceDescPtr->preprocess_func = pkunk_preprocess; StarShipPtr->RaceDescPtr->postprocess_func = pkunk_postprocess; StarShipPtr->RaceDescPtr->init_weapon_func = initialize_bug_missile; StarShipPtr->RaceDescPtr->ship_info.crew_level = MAX_CREW; StarShipPtr->RaceDescPtr->ship_info.energy_level = MAX_ENERGY; /* fix vux impairment */ StarShipPtr->RaceDescPtr->characteristics.max_thrust = MAX_THRUST; StarShipPtr->RaceDescPtr->characteristics.thrust_increment = THRUST_INCREMENT; StarShipPtr->RaceDescPtr->characteristics.turn_wait = TURN_WAIT; StarShipPtr->RaceDescPtr->characteristics.thrust_wait = THRUST_WAIT; StarShipPtr->RaceDescPtr->characteristics.special_wait = 0; StarShipPtr->ship_input_state = 0; StarShipPtr->cur_status_flags = StarShipPtr->old_status_flags = 0; StarShipPtr->energy_counter = StarShipPtr->weapon_counter = StarShipPtr->special_counter = 0; ElementPtr->crew_level = ElementPtr->turn_wait = ElementPtr->thrust_wait = 0; ElementPtr->life_span = NORMAL_LIFE; StarShipPtr->ShipFacing = NORMALIZE_FACING (TFB_Random ()); ElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; ElementPtr->current.image.frame = SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], StarShipPtr->ShipFacing); SetPrimType (&(GLOBAL (DisplayArray))[ ElementPtr->PrimIndex ], STAMP_PRIM); do { ElementPtr->current.location.x = WRAP_X (DISPLAY_ALIGN_X (TFB_Random ())); ElementPtr->current.location.y = WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ())); } while (CalculateGravity (ElementPtr) || TimeSpaceMatterConflict (ElementPtr)); ElementPtr->hTarget = StarShipPtr->hShip; } } static void intercept_pkunk_death (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; ElementPtr->state_flags &= ~DISAPPEARING; ElementPtr->life_span = 1; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->RaceDescPtr->ship_info.crew_level == 0) { ELEMENTPTR ShipPtr; LockElement (StarShipPtr->hShip, &ShipPtr); if (GRAVITY_MASS (ShipPtr->mass_points + 1)) { ElementPtr->state_flags |= DISAPPEARING; ElementPtr->life_span = 0; } else { ShipPtr->mass_points = MAX_SHIP_MASS + 1; StarShipPtr->RaceDescPtr->preprocess_func = ShipPtr->preprocess_func; StarShipPtr->RaceDescPtr->postprocess_func = ShipPtr->postprocess_func; StarShipPtr->RaceDescPtr->init_weapon_func = (COUNT (*) (PELEMENT ElementPtr, HELEMENT Weapon[])) ShipPtr->death_func; ElementPtr->death_func = new_pkunk; } UnlockElement (StarShipPtr->hShip); } } #define START_PHOENIX_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A) #define TRANSITION_LIFE 1 void spawn_phoenix_trail (PELEMENT ElementPtr) { static const COLOR color_tab[] = { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x2a), BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2b), BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2c), BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2d), BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2e), BUILD_COLOR (MAKE_RGB15 (0x0B, 0x00, 0x00), 0x2f), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7a), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7b), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7c), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7d), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7e), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7f), }; #define NUM_TAB_COLORS (sizeof (color_tab) / sizeof (color_tab[0])) COUNT color_index = 0; COLOR Color; Color = COLOR_256 ( GetPrimColor (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex]) ); if (Color != 0x2F) { ElementPtr->life_span = TRANSITION_LIFE; ++Color; if (Color > 0x7F) Color = 0x2A; if (Color <= 0x2f && Color >= 0x2a) color_index = (COUNT)Color - 0x2a; else /* color is between 0x7a and 0x7f */ color_index = (COUNT)(Color - 0x7a) + (NUM_TAB_COLORS >> 1); SetPrimColor ( &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], color_tab[color_index] ); ElementPtr->state_flags &= ~DISAPPEARING; ElementPtr->state_flags |= CHANGING; } } #define PHOENIX_LIFE 12 void phoenix_transition (PELEMENT ElementPtr) { HELEMENT hShipImage; ELEMENTPTR ShipImagePtr; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ShipImagePtr); if (!(ShipImagePtr->state_flags & NONSOLID)) { ElementPtr->preprocess_func = NULL_PTR; } else if ((hShipImage = AllocElement ())) { #define TRANSITION_SPEED DISPLAY_TO_WORLD (20) COUNT angle; PutElement (hShipImage); LockElement (hShipImage, &ShipImagePtr); ShipImagePtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; ShipImagePtr->life_span = TRANSITION_LIFE; SetPrimType (&(GLOBAL (DisplayArray))[ShipImagePtr->PrimIndex], STAMPFILL_PRIM); SetPrimColor ( &(GLOBAL (DisplayArray))[ShipImagePtr->PrimIndex], START_PHOENIX_COLOR ); ShipImagePtr->current.image = ElementPtr->current.image; ShipImagePtr->current.location = ElementPtr->current.location; if (!(ElementPtr->state_flags & PLAYER_SHIP)) { angle = ElementPtr->mass_points; ShipImagePtr->current.location.x += COSINE (angle, TRANSITION_SPEED); ShipImagePtr->current.location.y += SINE (angle, TRANSITION_SPEED); ElementPtr->preprocess_func = NULL_PTR; } else { angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); ShipImagePtr->current.location.x -= COSINE (angle, TRANSITION_SPEED) * (ElementPtr->life_span - 1); ShipImagePtr->current.location.y -= SINE (angle, TRANSITION_SPEED) * (ElementPtr->life_span - 1); ShipImagePtr->current.location.x = WRAP_X (ShipImagePtr->current.location.x); ShipImagePtr->current.location.y = WRAP_Y (ShipImagePtr->current.location.y); } ShipImagePtr->mass_points = (BYTE)angle; ShipImagePtr->preprocess_func = phoenix_transition; ShipImagePtr->death_func = spawn_phoenix_trail; SetElementStarShip (ShipImagePtr, StarShipPtr); UnlockElement (hShipImage); } UnlockElement (StarShipPtr->hShip); } static void pkunk_preprocess (ElementPtr) PELEMENT ElementPtr; { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (ElementPtr->state_flags & APPEARING) { ELEMENTPTR PhoenixPtr; if (((BYTE)TFB_Random () & 1) && (hPhoenix = AllocElement ())) { LockElement (hPhoenix, &PhoenixPtr); PhoenixPtr->state_flags = FINITE_LIFE | NONSOLID | IGNORE_SIMILAR | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); PhoenixPtr->life_span = 1; PhoenixPtr->death_func = intercept_pkunk_death; SetElementStarShip (PhoenixPtr, StarShipPtr); UnlockElement (hPhoenix); InsertElement (hPhoenix, GetHeadElement ()); } if (ElementPtr->hTarget == 0) StarShipPtr->RaceDescPtr->preprocess_func = 0; else { COUNT angle, facing; ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1 ), ElementPtr); ElementPtr->life_span = PHOENIX_LIFE; SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; facing = StarShipPtr->ShipFacing; for (angle = OCTANT; angle < FULL_CIRCLE; angle += QUADRANT) { StarShipPtr->ShipFacing = NORMALIZE_FACING ( facing + ANGLE_TO_FACING (angle) ); phoenix_transition (ElementPtr); } StarShipPtr->ShipFacing = facing; } } if (StarShipPtr->RaceDescPtr->preprocess_func) { StarShipPtr->cur_status_flags &= ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL); if (ElementPtr->life_span == NORMAL_LIFE) { ElementPtr->current.image.frame = ElementPtr->next.image.frame = SetEquFrameIndex ( ElementPtr->current.image.farray[0], ElementPtr->current.image.frame); SetPrimType (&(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], STAMP_PRIM); InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); InitIntersectFrame (ElementPtr); ZeroVelocityComponents (&((ELEMENTPTR)ElementPtr)->velocity); ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE); ElementPtr->state_flags |= CHANGING; StarShipPtr->RaceDescPtr->preprocess_func = 0; } } } static void pkunk_postprocess (ElementPtr) PELEMENT ElementPtr; { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->RaceDescPtr->characteristics.special_wait) --StarShipPtr->RaceDescPtr->characteristics.special_wait; else if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->RaceDescPtr->ship_info.energy_level < StarShipPtr->RaceDescPtr->ship_info.max_energy) { COUNT CurSound; static COUNT LastSound = 0; do { CurSound = 2 + ((COUNT)TFB_Random () % (GetSoundCount (StarShipPtr->RaceDescPtr->ship_data.ship_sounds) - 2)); } while (CurSound == LastSound); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, CurSound ), ElementPtr); LastSound = CurSound; DeltaEnergy (ElementPtr, SPECIAL_ENERGY_COST); StarShipPtr->RaceDescPtr->characteristics.special_wait = SPECIAL_WAIT; } } RACE_DESCPTR init_pkunk (void) { RACE_DESCPTR RaceDescPtr; pkunk_desc.preprocess_func = pkunk_preprocess; pkunk_desc.postprocess_func = pkunk_postprocess; pkunk_desc.init_weapon_func = initialize_bug_missile; pkunk_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) pkunk_intelligence; RaceDescPtr = &pkunk_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/pkunk/restypes.h0000600000175000017500000000024110543202061020102 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/pkunk/igfxres.h0000600000175000017500000000063010543202061017675 0ustar joeyjoey#define PKUNK_ICON_MASK_PMAP_ANIM 0x00200002L #define PKUNK_MICON_MASK_PMAP_ANIM 0x00200102L #define PKUNK_BIG_MASK_PMAP_ANIM 0x00400202L #define PKUNK_MED_MASK_PMAP_ANIM 0x00400302L #define PKUNK_SML_MASK_PMAP_ANIM 0x00400402L #define BUG_BIG_MASK_PMAP_ANIM 0x00400502L #define BUG_MED_MASK_PMAP_ANIM 0x00400602L #define BUG_SML_MASK_PMAP_ANIM 0x00400702L #define PKUNK_CAPTAIN_MASK_PMAP_ANIM 0x00400802L uqm-0.6.2/sc2/src/sc2code/ships/pkunk/isndres.h0000600000175000017500000000005010543202061017671 0ustar joeyjoey#define PKUNK_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/pkunk/istrtab.h0000600000175000017500000000005110543202061017673 0ustar joeyjoey#define PKUNK_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/pkunk/imusicre.h0000600000175000017500000000005110543202061020043 0ustar joeyjoey#define PKUNK_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/pkunk/icode.h0000600000175000017500000000004110543202061017305 0ustar joeyjoey#define PKUNK_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/pkunk/Makeinfo0000600000175000017500000000002510543202061017527 0ustar joeyjoeyuqm_CFILES="pkunk.c" uqm-0.6.2/sc2/src/sc2code/ships/pkunk/respkg.h0000600000175000017500000000006310543202061017521 0ustar joeyjoeyenum { PKUNK_CODE_PACKAGE = 1, PKUNK_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/pkunk/resinst.h0000600000175000017500000000015010543202061017712 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/Makeinfo0000600000175000017500000000033310543202075016406 0ustar joeyjoeyuqm_SUBDIRS="androsyn arilou blackurq chenjesu chmmr druuge human ilwrath lastbat melnorme mmrnmhrm mycon orz pkunk probe shofixti sis_ship slylandr spathi supox syreen thradd umgah urquan utwig vux yehat zoqfot" uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/0000755000175000017500000000000010552600274016603 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/mmrnmhrm.res0000600000175000017500000000153410543202064021141 0ustar joeyjoeyINCLUDE ../star3do.typ PATH mmrnmhrm PACKAGE MMRNMHRM_CODE_PACKAGE mmrnmhrm.shp CODE MMRNMHRM_CODE mmrnmhrm.cod GFXRES MMRNMHRM_ICON_MASK_PMAP_ANIM mmricons.ani GFXRES MMRNMHRM_MICON_MASK_PMAP_ANIM mmrmicon.ani STRTAB MMRNMHRM_RACE_STRINGS mmrtext.txt PACKAGE MMRNMHRM_PACKAGE mmrnmhrm.shp GFXRES MMRNMHRM_BIG_MASK_PMAP_ANIM mmrnmhrm.big GFXRES MMRNMHRM_MED_MASK_PMAP_ANIM mmrnmhrm.med GFXRES MMRNMHRM_SML_MASK_PMAP_ANIM mmrnmhrm.sml GFXRES TORP_BIG_MASK_PMAP_ANIM torp.big GFXRES TORP_MED_MASK_PMAP_ANIM torp.med GFXRES TORP_SML_MASK_PMAP_ANIM torp.sml GFXRES YWING_BIG_MASK_PMAP_ANIM ywing.big GFXRES YWING_MED_MASK_PMAP_ANIM ywing.med GFXRES YWING_SML_MASK_PMAP_ANIM ywing.sml GFXRES MMRNMHRM_CAPTAIN_MASK_PMAP_ANIM mmrcap.ani SNDRES MMRNMHRM_SHIP_SOUNDS mmrsound.snd MUSICRES MMRNMHRM_VICTORY_SONG mmrditty.mod uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/restypes.h0000600000175000017500000000024110543202064020612 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/mmrnmhrm.c0000600000175000017500000003240210543202064020570 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/mmrnmhrm/resinst.h" #include "init.h" #define MAX_CREW 20 #define MAX_ENERGY 10 #define ENERGY_REGENERATION 2 #define WEAPON_ENERGY_COST 1 #define SPECIAL_ENERGY_COST MAX_ENERGY #define ENERGY_WAIT 6 #define MAX_THRUST 20 #define THRUST_INCREMENT 5 #define TURN_WAIT 2 #define THRUST_WAIT 1 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 0 #define YWING_ENERGY_REGENERATION 1 #define YWING_WEAPON_ENERGY_COST 1 #define YWING_SPECIAL_ENERGY_COST MAX_ENERGY #define YWING_ENERGY_WAIT 6 #define YWING_MAX_THRUST 50 #define YWING_THRUST_INCREMENT 10 #define YWING_TURN_WAIT 14 #define YWING_THRUST_WAIT 0 #define YWING_WEAPON_WAIT 20 #define YWING_SPECIAL_WAIT 0 #define SHIP_MASS 3 #define MMRNMHRM_OFFSET 16 #define LASER_RANGE DISPLAY_TO_WORLD (125 + MMRNMHRM_OFFSET) static CHARACTERISTIC_STUFF otherwing_desc[NUM_SIDES]; static RACE_DESC mmrnmhrm_desc = { { FIRES_FORE | IMMEDIATE_WEAPON, 19, /* Super Melee cost */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 0, 0, }, (STRING)MMRNMHRM_RACE_STRINGS, (FRAME)MMRNMHRM_ICON_MASK_PMAP_ANIM, (FRAME)MMRNMHRM_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)MMRNMHRM_BIG_MASK_PMAP_ANIM, (FRAME)MMRNMHRM_MED_MASK_PMAP_ANIM, (FRAME)MMRNMHRM_SML_MASK_PMAP_ANIM, }, { (FRAME)TORP_BIG_MASK_PMAP_ANIM, (FRAME)TORP_MED_MASK_PMAP_ANIM, (FRAME)TORP_SML_MASK_PMAP_ANIM, }, { (FRAME)YWING_BIG_MASK_PMAP_ANIM, (FRAME)YWING_MED_MASK_PMAP_ANIM, (FRAME)YWING_SML_MASK_PMAP_ANIM, }, { (FRAME)MMRNMHRM_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)MMRNMHRM_VICTORY_SONG, (SOUND)MMRNMHRM_SHIP_SOUNDS, }, { 0, CLOSE_RANGE_WEAPON, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; #define MISSILE_SPEED DISPLAY_TO_WORLD (20) #define TRACK_WAIT 5 static void missile_preprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { COUNT facing; facing = GetFrameIndex (ElementPtr->next.image.frame); if (TrackShip (ElementPtr, &facing) > 0) { ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->next.image.frame, facing); ElementPtr->state_flags |= CHANGING; SetVelocityVector (&ElementPtr->velocity, MISSILE_SPEED, facing); } ElementPtr->turn_wait = TRACK_WAIT; } } static void mmrnmhrm_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { BOOLEAN CanTransform; PEVALUATE_DESC lpEvalDesc; STARSHIPPTR StarShipPtr, EnemyStarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); CanTransform = (BOOLEAN)(StarShipPtr->special_counter == 0 && StarShipPtr->RaceDescPtr->ship_info.energy_level >= StarShipPtr->RaceDescPtr->characteristics.special_energy_cost); lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (lpEvalDesc->ObjectPtr) { GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); StarShipPtr->ship_input_state &= ~SPECIAL; if (CanTransform && lpEvalDesc->ObjectPtr && !(StarShipPtr->ship_input_state & WEAPON)) { SIZE delta_x, delta_y; COUNT travel_angle, direction_angle; GetCurrentVelocityComponents (&lpEvalDesc->ObjectPtr->velocity, &delta_x, &delta_y); if (delta_x == 0 && delta_y == 0) direction_angle = travel_angle = 0; else { delta_x = lpEvalDesc->ObjectPtr->current.location.x - ShipPtr->current.location.x; delta_y = lpEvalDesc->ObjectPtr->current.location.y - ShipPtr->current.location.y; direction_angle = ARCTAN (-delta_x, -delta_y); travel_angle = GetVelocityTravelAngle ( &lpEvalDesc->ObjectPtr->velocity ); } if (ShipPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) { if (lpEvalDesc->which_turn > 8) { if (MANEUVERABILITY (&EnemyStarShipPtr->RaceDescPtr->cyborg_control) <= SLOW_SHIP || NORMALIZE_ANGLE ( direction_angle - travel_angle + QUADRANT ) > HALF_CIRCLE) StarShipPtr->ship_input_state |= SPECIAL; } } else { SIZE ship_delta_x, ship_delta_y; GetCurrentVelocityComponents (&ShipPtr->velocity, &ship_delta_x, &ship_delta_y); delta_x -= ship_delta_x; delta_y -= ship_delta_y; travel_angle = ARCTAN (delta_x, delta_y); if (lpEvalDesc->which_turn < 16) { if (lpEvalDesc->which_turn <= 8 || NORMALIZE_ANGLE ( direction_angle - travel_angle + OCTANT ) <= QUADRANT) StarShipPtr->ship_input_state |= SPECIAL; } else if (lpEvalDesc->which_turn > 32 && NORMALIZE_ANGLE ( direction_angle - travel_angle + QUADRANT ) > HALF_CIRCLE) StarShipPtr->ship_input_state |= SPECIAL; } } if (ShipPtr->current.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) { if (!(StarShipPtr->ship_input_state & SPECIAL) && lpEvalDesc->ObjectPtr) StarShipPtr->ship_input_state |= WEAPON; else StarShipPtr->ship_input_state &= ~WEAPON; } } static void twin_laser_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if (!(ElementPtr1->state_flags & PLAYER_SHIP) || !(ElementPtr0->state_flags & ElementPtr1->state_flags & (GOOD_GUY | BAD_GUY))) weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); } static COUNT initialize_dual_weapons (PELEMENT ShipPtr, HELEMENT WeaponArray[]) { #define CENTER_OFFS DISPLAY_TO_WORLD (4) COORD cx, cy; COUNT facing, angle; SIZE offs_x, offs_y; STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); facing = StarShipPtr->ShipFacing; angle = FACING_TO_ANGLE (facing); cx = ShipPtr->next.location.x + COSINE (angle, CENTER_OFFS); cy = ShipPtr->next.location.y + SINE (angle, CENTER_OFFS); if (ShipPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) { #define WING_OFFS DISPLAY_TO_WORLD (10) COORD ex, ey; LASER_BLOCK LaserBlock; ELEMENTPTR LaserPtr; LaserBlock.sender = ShipPtr->state_flags & (GOOD_GUY | BAD_GUY); LaserBlock.pixoffs = 0; LaserBlock.color = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C); LaserBlock.face = facing; ex = cx + COSINE (angle, LASER_RANGE); ey = cy + SINE (angle, LASER_RANGE); offs_x = -SINE (angle, WING_OFFS); offs_y = COSINE (angle, WING_OFFS); LaserBlock.cx = cx + offs_x; LaserBlock.cy = cy + offs_y; LaserBlock.ex = ex - LaserBlock.cx; LaserBlock.ey = ey - LaserBlock.cy; if ((WeaponArray[0] = initialize_laser (&LaserBlock))) { LockElement (WeaponArray[0], &LaserPtr); LaserPtr->collision_func = twin_laser_collision; UnlockElement (WeaponArray[0]); } LaserBlock.cx = cx - offs_x; LaserBlock.cy = cy - offs_y; LaserBlock.ex = ex - LaserBlock.cx; LaserBlock.ey = ey - LaserBlock.cy; if ((WeaponArray[1] = initialize_laser (&LaserBlock))) { LockElement (WeaponArray[1], &LaserPtr); LaserPtr->collision_func = twin_laser_collision; UnlockElement (WeaponArray[1]); } } else { #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 0 #define MISSILE_LIFE 40 #define LAUNCH_OFFS DISPLAY_TO_WORLD (4) MISSILE_BLOCK TorpBlock; ELEMENTPTR TorpPtr; TorpBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; TorpBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; TorpBlock.pixoffs = 0; TorpBlock.speed = MISSILE_SPEED; TorpBlock.hit_points = MISSILE_HITS; TorpBlock.damage = MISSILE_DAMAGE; TorpBlock.life = MISSILE_LIFE; TorpBlock.preprocess_func = missile_preprocess; TorpBlock.blast_offs = MISSILE_OFFSET; TorpBlock.face = TorpBlock.index = NORMALIZE_FACING (facing - 1); offs_x = -SINE (FACING_TO_ANGLE (TorpBlock.face), LAUNCH_OFFS); offs_y = COSINE (FACING_TO_ANGLE (TorpBlock.face), LAUNCH_OFFS); TorpBlock.cx = cx + offs_x; TorpBlock.cy = cy + offs_y; if ((WeaponArray[0] = initialize_missile (&TorpBlock))) { LockElement (WeaponArray[0], &TorpPtr); TorpPtr->turn_wait = TRACK_WAIT; UnlockElement (WeaponArray[0]); } TorpBlock.face = TorpBlock.index = NORMALIZE_FACING (facing + 1); TorpBlock.cx = cx - offs_x; TorpBlock.cy = cy - offs_y; if ((WeaponArray[1] = initialize_missile (&TorpBlock))) { LockElement (WeaponArray[1], &TorpPtr); TorpPtr->turn_wait = TRACK_WAIT; UnlockElement (WeaponArray[1]); } } return (2); } static void mmrnmhrm_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); /* take care of transform effect */ if (ElementPtr->next.image.farray != ElementPtr->current.image.farray) { CHARACTERISTIC_STUFF t; ProcessSound (SetAbsSoundIndex ( /* TRANSFORM */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); DeltaEnergy (ElementPtr, -StarShipPtr->RaceDescPtr->characteristics.special_energy_cost); StarShipPtr->weapon_counter = 0; t = otherwing_desc[WHICH_SIDE(ElementPtr->state_flags)]; otherwing_desc[WHICH_SIDE(ElementPtr->state_flags)] = StarShipPtr->RaceDescPtr->characteristics; StarShipPtr->RaceDescPtr->characteristics = t; StarShipPtr->RaceDescPtr->cyborg_control.ManeuverabilityIndex = 0; if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special) { StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = LONG_RANGE_WEAPON - 1; StarShipPtr->RaceDescPtr->ship_info.ship_flags &= ~IMMEDIATE_WEAPON; StarShipPtr->RaceDescPtr->ship_info.ship_flags |= SEEKING_WEAPON; StarShipPtr->RaceDescPtr->ship_data.ship_sounds = SetAbsSoundIndex (StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); } else { StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = CLOSE_RANGE_WEAPON; StarShipPtr->RaceDescPtr->ship_info.ship_flags &= ~SEEKING_WEAPON; StarShipPtr->RaceDescPtr->ship_info.ship_flags |= IMMEDIATE_WEAPON; StarShipPtr->RaceDescPtr->ship_data.ship_sounds = SetAbsSoundIndex (StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 0); if (StarShipPtr->cur_status_flags & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) StarShipPtr->cur_status_flags |= SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED; } } } static void mmrnmhrm_preprocess (PELEMENT ElementPtr) { if (ElementPtr->state_flags & APPEARING) { COUNT i; i = WHICH_SIDE (ElementPtr->state_flags); otherwing_desc[i].max_thrust = YWING_MAX_THRUST; otherwing_desc[i].thrust_increment = YWING_THRUST_INCREMENT; otherwing_desc[i].energy_regeneration = YWING_ENERGY_REGENERATION; otherwing_desc[i].weapon_energy_cost = YWING_WEAPON_ENERGY_COST; otherwing_desc[i].special_energy_cost = YWING_SPECIAL_ENERGY_COST; otherwing_desc[i].energy_wait = YWING_ENERGY_WAIT; otherwing_desc[i].turn_wait = YWING_TURN_WAIT; otherwing_desc[i].thrust_wait = YWING_THRUST_WAIT; otherwing_desc[i].weapon_wait = YWING_WEAPON_WAIT; otherwing_desc[i].special_wait = YWING_SPECIAL_WAIT; otherwing_desc[i].ship_mass = SHIP_MASS; } else { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0) { if (StarShipPtr->RaceDescPtr->ship_info.energy_level < StarShipPtr->RaceDescPtr->characteristics.special_energy_cost) DeltaEnergy (ElementPtr, -StarShipPtr->RaceDescPtr->characteristics.special_energy_cost); /* so text will flash */ else { if (ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.ship) ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; else ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; ElementPtr->next.image.frame = SetEquFrameIndex (ElementPtr->next.image.farray[0], ElementPtr->next.image.frame); ElementPtr->state_flags |= CHANGING; StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } } } RACE_DESCPTR init_mmrnmhrm (void) { RACE_DESCPTR RaceDescPtr; mmrnmhrm_desc.preprocess_func = mmrnmhrm_preprocess; mmrnmhrm_desc.postprocess_func = mmrnmhrm_postprocess; mmrnmhrm_desc.init_weapon_func = initialize_dual_weapons; mmrnmhrm_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) mmrnmhrm_intelligence; RaceDescPtr = &mmrnmhrm_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/igfxres.h0000600000175000017500000000106410543202064020407 0ustar joeyjoey#define MMRNMHRM_ICON_MASK_PMAP_ANIM 0x00200002L #define MMRNMHRM_MICON_MASK_PMAP_ANIM 0x00200102L #define MMRNMHRM_BIG_MASK_PMAP_ANIM 0x00400202L #define MMRNMHRM_MED_MASK_PMAP_ANIM 0x00400302L #define MMRNMHRM_SML_MASK_PMAP_ANIM 0x00400402L #define TORP_BIG_MASK_PMAP_ANIM 0x00400502L #define TORP_MED_MASK_PMAP_ANIM 0x00400602L #define TORP_SML_MASK_PMAP_ANIM 0x00400702L #define YWING_BIG_MASK_PMAP_ANIM 0x00400802L #define YWING_MED_MASK_PMAP_ANIM 0x00400902L #define YWING_SML_MASK_PMAP_ANIM 0x00400a02L #define MMRNMHRM_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/isndres.h0000600000175000017500000000005310543202064020404 0ustar joeyjoey#define MMRNMHRM_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/istrtab.h0000600000175000017500000000005410543202064020406 0ustar joeyjoey#define MMRNMHRM_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/imusicre.h0000600000175000017500000000005410543202064020556 0ustar joeyjoey#define MMRNMHRM_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/icode.h0000600000175000017500000000004410543202064020020 0ustar joeyjoey#define MMRNMHRM_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/Makeinfo0000600000175000017500000000003010543202064020233 0ustar joeyjoeyuqm_CFILES="mmrnmhrm.c" uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/respkg.h0000600000175000017500000000007110543202063020227 0ustar joeyjoeyenum { MMRNMHRM_CODE_PACKAGE = 1, MMRNMHRM_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/mmrnmhrm/resinst.h0000600000175000017500000000015010543202064020422 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/utwig/0000755000175000017500000000000010552600274016105 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/utwig/restypes.h0000600000175000017500000000024110543202066020116 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/utwig/utwig.c0000600000175000017500000002306510543202066017403 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/utwig/resinst.h" #include "globdata.h" #include "libs/mathlib.h" #define MAX_CREW 20 #define MAX_ENERGY 20 #define ENERGY_REGENERATION 0 #define WEAPON_ENERGY_COST 0 #define SPECIAL_ENERGY_COST 1 #define ENERGY_WAIT 255 #define MAX_THRUST 36 #define THRUST_INCREMENT 6 #define TURN_WAIT 1 #define THRUST_WAIT 6 #define WEAPON_WAIT 7 #define SPECIAL_WAIT 12 #define SHIP_MASS 8 #define UTWIG_OFFSET 9 #define MISSILE_SPEED DISPLAY_TO_WORLD (30) #define MISSILE_LIFE 10 static RACE_DESC utwig_desc = { { FIRES_FORE | POINT_DEFENSE | SHIELD_DEFENSE, 22, /* Super Melee cost */ 666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY >> 1, MAX_ENERGY, { 8534, 8797, }, (STRING)UTWIG_RACE_STRINGS, (FRAME)UTWIG_ICON_MASK_PMAP_ANIM, (FRAME)UTWIG_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)UTWIG_BIG_MASK_PMAP_ANIM, (FRAME)UTWIG_MED_MASK_PMAP_ANIM, (FRAME)UTWIG_SML_MASK_PMAP_ANIM, }, { (FRAME)LANCE_BIG_MASK_PMAP_ANIM, (FRAME)LANCE_MED_MASK_PMAP_ANIM, (FRAME)LANCE_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)UTWIG_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)UTWIG_VICTORY_SONG, (SOUND)UTWIG_SHIP_SOUNDS, }, { 0, CLOSE_RANGE_WEAPON, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static COUNT initialize_lance (PELEMENT ShipPtr, HELEMENT WeaponArray[]) { #define LAUNCH_XOFFS0 DISPLAY_TO_WORLD (5) #define LAUNCH_YOFFS0 -DISPLAY_TO_WORLD (18) #define LAUNCH_XOFFS1 DISPLAY_TO_WORLD (13) #define LAUNCH_YOFFS1 -DISPLAY_TO_WORLD (9) #define LAUNCH_XOFFS2 DISPLAY_TO_WORLD (17) #define LAUNCH_YOFFS2 -DISPLAY_TO_WORLD (4) #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 1 COUNT i; STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; MissileBlock.pixoffs = 0; for (i = 0; i < 3; ++i) { COUNT angle; SIZE sin0, cos0; SIZE sin1sin0, cos1sin0, cos1cos0, sin1cos0; switch (i) { case 0: cos0 = LAUNCH_XOFFS0; sin0 = LAUNCH_YOFFS0; break; case 1: cos0 = LAUNCH_XOFFS1; sin0 = LAUNCH_YOFFS1; break; case 2: cos0 = LAUNCH_XOFFS2; sin0 = LAUNCH_YOFFS2; break; } angle = FACING_TO_ANGLE (MissileBlock.face) + QUADRANT; cos1cos0 = COSINE (angle, cos0); sin1sin0 = SINE (angle, sin0); sin1cos0 = SINE (angle, cos0); cos1sin0 = COSINE (angle, sin0); cos0 = cos1cos0 - sin1sin0; sin0 = sin1cos0 + cos1sin0; MissileBlock.cx = ShipPtr->next.location.x + cos0; MissileBlock.cy = ShipPtr->next.location.y + sin0; WeaponArray[(i << 1)] = initialize_missile (&MissileBlock); cos0 = -cos1cos0 - sin1sin0; sin0 = -sin1cos0 + cos1sin0; MissileBlock.cx = ShipPtr->next.location.x + cos0; MissileBlock.cy = ShipPtr->next.location.y + sin0; WeaponArray[(i << 1) + 1] = initialize_missile (&MissileBlock); } return (6); } static void utwig_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { SIZE ShieldStatus; STARSHIPPTR StarShipPtr; PEVALUATE_DESC lpEvalDesc; GetElementStarShip (ShipPtr, &StarShipPtr); lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (StarShipPtr->RaceDescPtr->ship_info.energy_level == 0) ShieldStatus = 0; else { ShieldStatus = -1; if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) { ShieldStatus = 0; if (!(lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE)) lpEvalDesc->MoveState = PURSUE; else if (lpEvalDesc->ObjectPtr->mass_points || (lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) { if ((lpEvalDesc->which_turn >>= 1) == 0) lpEvalDesc->which_turn = 1; if (lpEvalDesc->ObjectPtr->mass_points) lpEvalDesc->ObjectPtr = 0; else lpEvalDesc->MoveState = PURSUE; ShieldStatus = 1; } } } if (StarShipPtr->special_counter == 0) { StarShipPtr->ship_input_state &= ~SPECIAL; if (ShieldStatus) { if ((ShieldStatus > 0 || lpEvalDesc->ObjectPtr) && lpEvalDesc->which_turn <= 2 && (ShieldStatus > 0 || (lpEvalDesc->ObjectPtr->state_flags & PLAYER_SHIP) /* means IMMEDIATE WEAPON */ || PlotIntercept (lpEvalDesc->ObjectPtr, ShipPtr, 2, 0)) && (TFB_Random () & 3)) { StarShipPtr->ship_input_state |= SPECIAL; StarShipPtr->ship_input_state &= ~WEAPON; } lpEvalDesc->ObjectPtr = 0; } } if (StarShipPtr->RaceDescPtr->ship_info.energy_level && (lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX])->ObjectPtr) { STARSHIPPTR EnemyStarShipPtr; GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if (!(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & IMMEDIATE_WEAPON)) lpEvalDesc->MoveState = PURSUE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); } static void utwig_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if (ElementPtr0->life_span > NORMAL_LIFE && (ElementPtr1->state_flags & FINITE_LIFE) && ElementPtr1->mass_points) ElementPtr0->life_span += ElementPtr1->mass_points; collision (ElementPtr0, pPt0, ElementPtr1, pPt1); } static void utwig_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; PPRIMITIVE lpPrim; if (ElementPtr->state_flags & APPEARING) { ElementPtr->collision_func = utwig_collision; } GetElementStarShip (ElementPtr, &StarShipPtr); if (ElementPtr->life_span > (NORMAL_LIFE + 1)) { DeltaEnergy (ElementPtr, ElementPtr->life_span - (NORMAL_LIFE + 1)); ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); } if (!(StarShipPtr->cur_status_flags & SPECIAL)) StarShipPtr->special_counter = 0; else if (StarShipPtr->special_counter % (SPECIAL_WAIT >> 1) == 0) { if (!DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) StarShipPtr->RaceDescPtr->ship_info.ship_flags &= ~(POINT_DEFENSE | SHIELD_DEFENSE); else if (StarShipPtr->special_counter == 0) { StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; ProcessSound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 2), ElementPtr); } } lpPrim = &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex]; if (StarShipPtr->special_counter == 0) { SetPrimColor (lpPrim, BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78)); ElementPtr->life_span = NORMAL_LIFE; SetPrimType (lpPrim, STAMP_PRIM); } else { static const COLOR color_tab[] = { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x2a), BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2b), BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2c), BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2d), BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2e), BUILD_COLOR (MAKE_RGB15 (0x0B, 0x00, 0x00), 0x2f), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7a), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7b), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7c), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7d), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7e), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7f), }; #define NUM_TAB_COLORS (sizeof (color_tab) / sizeof (color_tab[0])) COUNT color_index = 0; COLOR c; if (StarShipPtr->weapon_counter == 0) ++StarShipPtr->weapon_counter; c = COLOR_256 (GetPrimColor (lpPrim)); if (c >= 0x78) { if ((c += 2) > 0x7E) c = 0x2A; } else if (c < 0x2E) { if (++c == 0x2B) c = 0x2C; } else c = 0x7a; if (c <= 0x2f && c >= 0x2a) color_index = (COUNT)c - 0x2a; else /* color is between 0x7a and 0x7f */ color_index = (COUNT)(c - 0x7a) + (NUM_TAB_COLORS >> 1); SetPrimColor (lpPrim, color_tab[color_index]); ElementPtr->life_span = NORMAL_LIFE + 1; SetPrimType (lpPrim, STAMPFILL_PRIM); } } RACE_DESCPTR init_utwig (void) { RACE_DESCPTR RaceDescPtr; utwig_desc.preprocess_func = utwig_preprocess; utwig_desc.init_weapon_func = initialize_lance; utwig_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) utwig_intelligence; RaceDescPtr = &utwig_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/utwig/igfxres.h0000600000175000017500000000063610543202066017717 0ustar joeyjoey#define UTWIG_ICON_MASK_PMAP_ANIM 0x00200002L #define UTWIG_MICON_MASK_PMAP_ANIM 0x00200102L #define UTWIG_BIG_MASK_PMAP_ANIM 0x00400202L #define UTWIG_MED_MASK_PMAP_ANIM 0x00400302L #define UTWIG_SML_MASK_PMAP_ANIM 0x00400402L #define LANCE_BIG_MASK_PMAP_ANIM 0x00400502L #define LANCE_MED_MASK_PMAP_ANIM 0x00400602L #define LANCE_SML_MASK_PMAP_ANIM 0x00400702L #define UTWIG_CAPTAIN_MASK_PMAP_ANIM 0x00400802L uqm-0.6.2/sc2/src/sc2code/ships/utwig/utwig.res0000600000175000017500000000124610543202066017747 0ustar joeyjoeyINCLUDE ../star3do.typ PATH utwig PACKAGE UTWIG_CODE_PACKAGE utwig.shp CODE UTWIG_CODE utwig.cod GFXRES UTWIG_ICON_MASK_PMAP_ANIM utwicons.ani GFXRES UTWIG_MICON_MASK_PMAP_ANIM utwmicon.ani STRTAB UTWIG_RACE_STRINGS utwtext.txt PACKAGE UTWIG_PACKAGE utwig.shp GFXRES UTWIG_BIG_MASK_PMAP_ANIM utwig.big GFXRES UTWIG_MED_MASK_PMAP_ANIM utwig.med GFXRES UTWIG_SML_MASK_PMAP_ANIM utwig.sml GFXRES LANCE_BIG_MASK_PMAP_ANIM lanbig.ani GFXRES LANCE_MED_MASK_PMAP_ANIM lanmed.ani GFXRES LANCE_SML_MASK_PMAP_ANIM lansml.ani GFXRES UTWIG_CAPTAIN_MASK_PMAP_ANIM utwcap.ani SNDRES UTWIG_SHIP_SOUNDS utwsound.snd MUSICRES UTWIG_VICTORY_SONG utwditty.mod uqm-0.6.2/sc2/src/sc2code/ships/utwig/isndres.h0000600000175000017500000000005010543202066017705 0ustar joeyjoey#define UTWIG_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/utwig/istrtab.h0000600000175000017500000000005110543202066017707 0ustar joeyjoey#define UTWIG_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/utwig/imusicre.h0000600000175000017500000000005110543202066020057 0ustar joeyjoey#define UTWIG_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/utwig/icode.h0000600000175000017500000000004110543202066017321 0ustar joeyjoey#define UTWIG_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/utwig/Makeinfo0000600000175000017500000000002510543202066017543 0ustar joeyjoeyuqm_CFILES="utwig.c" uqm-0.6.2/sc2/src/sc2code/ships/utwig/respkg.h0000600000175000017500000000006310543202066017535 0ustar joeyjoeyenum { UTWIG_CODE_PACKAGE = 1, UTWIG_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/utwig/resinst.h0000600000175000017500000000015010543202066017726 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/umgah/0000755000175000017500000000000010552600274016047 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/umgah/restypes.h0000600000175000017500000000024110543202066020060 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/umgah/umgah.res0000600000175000017500000000127510543202066017655 0ustar joeyjoeyINCLUDE ../star3do.typ PATH umgah PACKAGE UMGAH_CODE_PACKAGE umgah.shp CODE UMGAH_CODE umgah.cod GFXRES UMGAH_ICON_MASK_PMAP_ANIM umgicons.ani GFXRES UMGAH_MICON_MASK_PMAP_ANIM umgmicon.ani STRTAB UMGAH_RACE_STRINGS umgtext.txt PACKAGE UMGAH_PACKAGE umgah.shp GFXRES UMGAH_BIG_MASK_PMAP_ANIM umgah.big GFXRES UMGAH_MED_MASK_PMAP_ANIM umgah.med GFXRES UMGAH_SML_MASK_PMAP_ANIM umgah.sml GFXRES SPRITZ_MASK_PMAP_ANIM spritz.ani GFXRES CONE_BIG_MASK_ANIM cone.big GFXRES CONE_MED_MASK_ANIM cone.med GFXRES CONE_SML_MASK_ANIM cone.sml GFXRES UMGAH_CAPTAIN_MASK_PMAP_ANIM umgcap.ani SNDRES UMGAH_SHIP_SOUNDS umgsound.snd MUSICRES UMGAH_VICTORY_SONG umgditty.mod uqm-0.6.2/sc2/src/sc2code/ships/umgah/igfxres.h0000600000175000017500000000066610543202066017664 0ustar joeyjoey#define UMGAH_ICON_MASK_PMAP_ANIM 0x00200002L #define UMGAH_MICON_MASK_PMAP_ANIM 0x00200102L #define UMGAH_BIG_MASK_PMAP_ANIM 0x00400202L #define UMGAH_MED_MASK_PMAP_ANIM 0x00400302L #define UMGAH_SML_MASK_PMAP_ANIM 0x00400402L #define SPRITZ_MASK_PMAP_ANIM 0x00400502L #define CONE_BIG_MASK_ANIM 0x00400602L #define CONE_MED_MASK_ANIM 0x00400702L #define CONE_SML_MASK_ANIM 0x00400802L #define UMGAH_CAPTAIN_MASK_PMAP_ANIM 0x00400902L uqm-0.6.2/sc2/src/sc2code/ships/umgah/isndres.h0000600000175000017500000000005010543202066017647 0ustar joeyjoey#define UMGAH_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/umgah/istrtab.h0000600000175000017500000000005110543202066017651 0ustar joeyjoey#define UMGAH_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/umgah/imusicre.h0000600000175000017500000000005110543202066020021 0ustar joeyjoey#define UMGAH_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/umgah/icode.h0000600000175000017500000000004110543202066017263 0ustar joeyjoey#define UMGAH_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/umgah/Makeinfo0000600000175000017500000000002510543202066017505 0ustar joeyjoeyuqm_CFILES="umgah.c" uqm-0.6.2/sc2/src/sc2code/ships/umgah/respkg.h0000600000175000017500000000006310543202066017477 0ustar joeyjoeyenum { UMGAH_CODE_PACKAGE = 1, UMGAH_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/umgah/umgah.c0000600000175000017500000002371510543202066017311 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/umgah/resinst.h" #include "libs/mathlib.h" #define MAX_CREW 10 #define MAX_ENERGY 30 #define ENERGY_REGENERATION MAX_ENERGY #define WEAPON_ENERGY_COST 0 #define SPECIAL_ENERGY_COST 1 #define ENERGY_WAIT 150 #define MAX_THRUST /* DISPLAY_TO_WORLD (5) */ 18 #define THRUST_INCREMENT /* DISPLAY_TO_WORLD (2) */ 6 #define TURN_WAIT 4 #define THRUST_WAIT 3 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 2 #define SHIP_MASS 1 static FRAME LastShipFrame[2]; static RACE_DESC umgah_desc = { { FIRES_FORE | IMMEDIATE_WEAPON, 7, /* Super Melee cost */ 833 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 1798, 6000, }, (STRING)UMGAH_RACE_STRINGS, (FRAME)UMGAH_ICON_MASK_PMAP_ANIM, (FRAME)UMGAH_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)UMGAH_BIG_MASK_PMAP_ANIM, (FRAME)UMGAH_MED_MASK_PMAP_ANIM, (FRAME)UMGAH_SML_MASK_PMAP_ANIM, }, { (FRAME)SPRITZ_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, }, { (FRAME)CONE_BIG_MASK_ANIM, (FRAME)CONE_MED_MASK_ANIM, (FRAME)CONE_SML_MASK_ANIM, }, { (FRAME)UMGAH_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)UMGAH_VICTORY_SONG, (SOUND)UMGAH_SHIP_SOUNDS, }, { 0, (LONG_RANGE_WEAPON << 2), NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static void cone_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); StarShipPtr->RaceDescPtr->ship_data.special[0] = SetRelFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], ANGLE_TO_FACING (FULL_CIRCLE)); ElementPtr->state_flags |= APPEARING; } static void cone_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { HELEMENT hBlastElement; hBlastElement = weapon_collision (ElementPtr0, pPt0, ElementPtr1, pPt1); if (hBlastElement) { RemoveElement (hBlastElement); FreeElement (hBlastElement); ElementPtr0->state_flags &= ~DISAPPEARING; } } #define JUMP_DIST DISPLAY_TO_WORLD (40) static void umgah_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { PEVALUATE_DESC lpEvalDesc; STARSHIPPTR StarShipPtr, EnemyStarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) { if (lpEvalDesc->which_turn > 3 || (StarShipPtr->old_status_flags & SPECIAL)) lpEvalDesc->ObjectPtr = 0; else if ((lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE) && !(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) lpEvalDesc->MoveState = AVOID; else lpEvalDesc->MoveState = PURSUE; } lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->special_counter || ObjectsOfConcern[GRAVITY_MASS_INDEX].ObjectPtr || lpEvalDesc->ObjectPtr == 0) { StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = CLOSE_RANGE_WEAPON; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (lpEvalDesc->which_turn < 16) StarShipPtr->ship_input_state |= WEAPON; StarShipPtr->ship_input_state &= ~SPECIAL; } else { BYTE this_turn; SIZE delta_x, delta_y; BOOLEAN EnemyBehind, EnoughJuice; if (lpEvalDesc->which_turn >= 0xFF + 1) this_turn = 0xFF; else this_turn = (BYTE)lpEvalDesc->which_turn; EnoughJuice = (BOOLEAN)(WORLD_TO_TURN ( JUMP_DIST * StarShipPtr->RaceDescPtr->ship_info.energy_level / SPECIAL_ENERGY_COST ) > this_turn); delta_x = lpEvalDesc->ObjectPtr->next.location.x - ShipPtr->next.location.x; delta_y = lpEvalDesc->ObjectPtr->next.location.y - ShipPtr->next.location.y; EnemyBehind = (BOOLEAN)(NORMALIZE_ANGLE ( ARCTAN (delta_x, delta_y) - (FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE) + (OCTANT + (OCTANT >> 2)) ) <= ((OCTANT + (OCTANT >> 2)) << 1)); GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if (EnoughJuice && ((StarShipPtr->old_status_flags & SPECIAL) || EnemyBehind || (this_turn > 6 && MANEUVERABILITY ( &EnemyStarShipPtr->RaceDescPtr->cyborg_control ) <= SLOW_SHIP) || (this_turn >= 16 && this_turn <= 24))) StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = (LONG_RANGE_WEAPON << 3); else StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange = CLOSE_RANGE_WEAPON; ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (StarShipPtr->RaceDescPtr->cyborg_control.WeaponRange == CLOSE_RANGE_WEAPON) StarShipPtr->ship_input_state &= ~SPECIAL; else { BOOLEAN LinedUp; StarShipPtr->ship_input_state &= ~THRUST; LinedUp = (BOOLEAN)(ShipPtr->turn_wait == 0 && !(StarShipPtr->old_status_flags & (LEFT | RIGHT))); if (((StarShipPtr->old_status_flags & SPECIAL) && this_turn <= StarShipPtr->RaceDescPtr->characteristics.special_wait) || (!(StarShipPtr->old_status_flags & SPECIAL) && EnemyBehind && (LinedUp || this_turn < 16))) { StarShipPtr->ship_input_state |= SPECIAL; StarShipPtr->RaceDescPtr->characteristics.special_wait = this_turn; /* don't want him backing straight into ship */ if (this_turn <= 8 && LinedUp) { if (TFB_Random () & 1) StarShipPtr->ship_input_state |= LEFT; else StarShipPtr->ship_input_state |= RIGHT; } } else if (StarShipPtr->old_status_flags & SPECIAL) { StarShipPtr->ship_input_state &= ~(SPECIAL | LEFT | RIGHT); StarShipPtr->ship_input_state |= THRUST; } } if (this_turn < 16 && !EnemyBehind) StarShipPtr->ship_input_state |= WEAPON; } if (!(StarShipPtr->ship_input_state & SPECIAL)) StarShipPtr->RaceDescPtr->characteristics.special_wait = 0xFF; } static COUNT initialize_cone (PELEMENT ShipPtr, HELEMENT ConeArray[]) { #define UMGAH_OFFSET 0 #define MISSILE_SPEED 0 #define MISSILE_HITS 100 #define MISSILE_DAMAGE 1 #define MISSILE_LIFE 1 #define MISSILE_OFFSET 0 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.special; MissileBlock.face = StarShipPtr->ShipFacing; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = UMGAH_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = cone_preprocess; MissileBlock.blast_offs = MISSILE_OFFSET; if (ShipPtr->next.image.frame != LastShipFrame[WHICH_SIDE(ShipPtr->state_flags)]) { LastShipFrame[WHICH_SIDE(ShipPtr->state_flags)] = ShipPtr->next.image.frame; StarShipPtr->RaceDescPtr->ship_data.special[0] = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_data.special[0], StarShipPtr->ShipFacing ); } MissileBlock.index = GetFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0]); ConeArray[0] = initialize_missile (&MissileBlock); if (ConeArray[0]) { ELEMENTPTR ConePtr; LockElement (ConeArray[0], &ConePtr); ConePtr->collision_func = cone_collision; ConePtr->state_flags &= ~APPEARING; ConePtr->next = ConePtr->current; InitIntersectStartPoint (ConePtr); InitIntersectEndPoint (ConePtr); ConePtr->IntersectControl.IntersectStamp.frame = StarShipPtr->RaceDescPtr->ship_data.special[0]; UnlockElement (ConeArray[0]); } return (1); } static void umgah_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr->special_counter > 0) { StarShipPtr->special_counter = 0; ZeroVelocityComponents (&ElementPtr->velocity); } } static void umgah_preprocess (PELEMENT ElementPtr) { if (ElementPtr->state_flags & APPEARING) LastShipFrame[WHICH_SIDE(ElementPtr->state_flags)] = 0; else { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (ElementPtr->thrust_wait == 0 && (StarShipPtr->cur_status_flags & SPECIAL) && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST)) { COUNT facing; ProcessSound (SetAbsSoundIndex ( /* ZIP_BACKWARDS */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); facing = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; DeltaVelocityComponents (&ElementPtr->velocity, COSINE (facing, WORLD_TO_VELOCITY (JUMP_DIST)), SINE (facing, WORLD_TO_VELOCITY (JUMP_DIST))); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); StarShipPtr->special_counter = SPECIAL_WAIT; } } } RACE_DESCPTR init_umgah (void) { RACE_DESCPTR RaceDescPtr; umgah_desc.preprocess_func = umgah_preprocess; umgah_desc.postprocess_func = umgah_postprocess; umgah_desc.init_weapon_func = initialize_cone; umgah_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) umgah_intelligence; RaceDescPtr = &umgah_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/umgah/resinst.h0000600000175000017500000000015010543202066017670 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/supox/0000755000175000017500000000000010552600274016124 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/supox/restypes.h0000600000175000017500000000024110543202074020134 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/supox/supox.res0000600000175000017500000000124310543202074020001 0ustar joeyjoeyINCLUDE ../star3do.typ PATH supox PACKAGE SUPOX_CODE_PACKAGE supox.shp CODE SUPOX_CODE supox.cod GFXRES SUPOX_ICON_MASK_PMAP_ANIM supicons.ani GFXRES SUPOX_MICON_MASK_PMAP_ANIM supmicon.ani STRTAB SUPOX_RACE_STRINGS suptext.txt PACKAGE SUPOX_PACKAGE supox.shp GFXRES SUPOX_BIG_MASK_PMAP_ANIM supox.big GFXRES SUPOX_MED_MASK_PMAP_ANIM supox.med GFXRES SUPOX_SML_MASK_PMAP_ANIM supox.sml GFXRES GOB_BIG_MASK_PMAP_ANIM gobbig.ani GFXRES GOB_MED_MASK_PMAP_ANIM gobmed.ani GFXRES GOB_SML_MASK_PMAP_ANIM gobsml.ani GFXRES SUPOX_CAPTAIN_MASK_PMAP_ANIM supcap.ani SNDRES SUPOX_SHIP_SOUNDS supsound.snd MUSICRES SUPOX_VICTORY_SONG supditty.mod uqm-0.6.2/sc2/src/sc2code/ships/supox/igfxres.h0000600000175000017500000000063010543202074017727 0ustar joeyjoey#define SUPOX_ICON_MASK_PMAP_ANIM 0x00200002L #define SUPOX_MICON_MASK_PMAP_ANIM 0x00200102L #define SUPOX_BIG_MASK_PMAP_ANIM 0x00400202L #define SUPOX_MED_MASK_PMAP_ANIM 0x00400302L #define SUPOX_SML_MASK_PMAP_ANIM 0x00400402L #define GOB_BIG_MASK_PMAP_ANIM 0x00400502L #define GOB_MED_MASK_PMAP_ANIM 0x00400602L #define GOB_SML_MASK_PMAP_ANIM 0x00400702L #define SUPOX_CAPTAIN_MASK_PMAP_ANIM 0x00400802L uqm-0.6.2/sc2/src/sc2code/ships/supox/supox.c0000600000175000017500000001546410543202074017444 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/supox/resinst.h" #include "libs/mathlib.h" #define MAX_CREW 12 #define MAX_ENERGY 16 #define ENERGY_REGENERATION 1 #define WEAPON_ENERGY_COST 1 #define SPECIAL_ENERGY_COST 1 #define ENERGY_WAIT 4 #define MAX_THRUST 40 #define THRUST_INCREMENT 8 #define TURN_WAIT 1 #define THRUST_WAIT 0 #define WEAPON_WAIT 2 #define SPECIAL_WAIT 0 #define SHIP_MASS 4 #define MISSILE_SPEED DISPLAY_TO_WORLD (30) #define MISSILE_LIFE 10 static RACE_DESC supox_desc = { { FIRES_FORE, 16, /* Super Melee cost */ 333 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 7468, 9246, }, (STRING)SUPOX_RACE_STRINGS, (FRAME)SUPOX_ICON_MASK_PMAP_ANIM, (FRAME)SUPOX_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)SUPOX_BIG_MASK_PMAP_ANIM, (FRAME)SUPOX_MED_MASK_PMAP_ANIM, (FRAME)SUPOX_SML_MASK_PMAP_ANIM, }, { (FRAME)GOB_BIG_MASK_PMAP_ANIM, (FRAME)GOB_MED_MASK_PMAP_ANIM, (FRAME)GOB_SML_MASK_PMAP_ANIM, }, { (FRAME)0, (FRAME)0, (FRAME)0, }, { (FRAME)SUPOX_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)SUPOX_VICTORY_SONG, (SOUND)SUPOX_SHIP_SOUNDS, }, { 0, (MISSILE_SPEED * MISSILE_LIFE) >> 1, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static void supox_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { STARSHIPPTR StarShipPtr; PEVALUATE_DESC lpEvalDesc; GetElementStarShip (ShipPtr, &StarShipPtr); lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX]; if (StarShipPtr->special_counter || lpEvalDesc->ObjectPtr == 0) StarShipPtr->ship_input_state &= ~SPECIAL; else { BOOLEAN LinedUp; COUNT direction_angle; SIZE delta_x, delta_y; delta_x = lpEvalDesc->ObjectPtr->next.location.x - ShipPtr->next.location.x; delta_y = lpEvalDesc->ObjectPtr->next.location.y - ShipPtr->next.location.y; direction_angle = ARCTAN (delta_x, delta_y); LinedUp = (BOOLEAN)(NORMALIZE_ANGLE (NORMALIZE_ANGLE (direction_angle - FACING_TO_ANGLE (StarShipPtr->ShipFacing)) + QUADRANT) <= HALF_CIRCLE); if (!LinedUp || lpEvalDesc->which_turn > 20 || NORMALIZE_ANGLE ( lpEvalDesc->facing - (FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE) + OCTANT ) > QUADRANT) StarShipPtr->ship_input_state &= ~SPECIAL; else if (LinedUp && lpEvalDesc->which_turn <= 12) StarShipPtr->ship_input_state |= SPECIAL; if (StarShipPtr->ship_input_state & SPECIAL) lpEvalDesc->MoveState = PURSUE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); if (StarShipPtr->ship_input_state & SPECIAL) StarShipPtr->ship_input_state |= THRUST | WEAPON; lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (StarShipPtr->special_counter == 0 && lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == AVOID && ShipPtr->turn_wait == 0) { StarShipPtr->ship_input_state &= ~THRUST; StarShipPtr->ship_input_state |= SPECIAL; if (!(StarShipPtr->cur_status_flags & (LEFT | RIGHT))) StarShipPtr->ship_input_state |= 1 << ((BYTE)TFB_Random () & 1); else StarShipPtr->ship_input_state |= StarShipPtr->cur_status_flags & (LEFT | RIGHT); } } static COUNT initialize_horn (PELEMENT ShipPtr, HELEMENT HornArray[]) { #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 2 #define SUPOX_OFFSET 23 STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.cx = ShipPtr->next.location.x; MissileBlock.cy = ShipPtr->next.location.y; MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = SUPOX_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; HornArray[0] = initialize_missile (&MissileBlock); return (1); } static void supox_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((StarShipPtr->cur_status_flags & SPECIAL) /* && DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST) */ ) { SIZE add_facing; add_facing = 0; if (StarShipPtr->cur_status_flags & THRUST) { if (ElementPtr->thrust_wait == 0) ++ElementPtr->thrust_wait; add_facing = ANGLE_TO_FACING (HALF_CIRCLE); } if (StarShipPtr->cur_status_flags & LEFT) { if (ElementPtr->turn_wait == 0) ++ElementPtr->turn_wait; if (add_facing) add_facing += ANGLE_TO_FACING (OCTANT); else add_facing = -ANGLE_TO_FACING (QUADRANT); } else if (StarShipPtr->cur_status_flags & RIGHT) { if (ElementPtr->turn_wait == 0) ++ElementPtr->turn_wait; if (add_facing) add_facing -= ANGLE_TO_FACING (OCTANT); else add_facing = ANGLE_TO_FACING (QUADRANT); } if (add_facing) { COUNT facing; UWORD thrust_status; facing = StarShipPtr->ShipFacing; StarShipPtr->ShipFacing = NORMALIZE_FACING ( facing + add_facing ); thrust_status = inertial_thrust (ElementPtr); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED | SHIP_IN_GRAVITY_WELL); StarShipPtr->cur_status_flags |= thrust_status; StarShipPtr->ShipFacing = facing; } } } RACE_DESCPTR init_supox (void) { RACE_DESCPTR RaceDescPtr; supox_desc.preprocess_func = supox_preprocess; supox_desc.init_weapon_func = initialize_horn; supox_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) supox_intelligence; RaceDescPtr = &supox_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/supox/isndres.h0000600000175000017500000000005010543202074017723 0ustar joeyjoey#define SUPOX_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/supox/istrtab.h0000600000175000017500000000005110543202075017726 0ustar joeyjoey#define SUPOX_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/supox/imusicre.h0000600000175000017500000000005110543202074020075 0ustar joeyjoey#define SUPOX_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/supox/icode.h0000600000175000017500000000004110543202074017337 0ustar joeyjoey#define SUPOX_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/supox/Makeinfo0000600000175000017500000000002510543202074017561 0ustar joeyjoeyuqm_CFILES="supox.c" uqm-0.6.2/sc2/src/sc2code/ships/supox/respkg.h0000600000175000017500000000006310543202074017553 0ustar joeyjoeyenum { SUPOX_CODE_PACKAGE = 1, SUPOX_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/supox/resinst.h0000600000175000017500000000015010543202075017745 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/ships/yehat/0000755000175000017500000000000010552600274016060 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/ships/yehat/restypes.h0000600000175000017500000000024110543202073020067 0ustar joeyjoey#ifndef _RESTYPES_H #define _RESTYPES_H enum { KEY_CONFIG = 1, GFXRES, FONTRES, STRTAB, SNDRES, MUSICRES, RES_INDEX, CODE }; #endif /* _RESTYPES_H */ uqm-0.6.2/sc2/src/sc2code/ships/yehat/yehat.res0000600000175000017500000000147510543202073017677 0ustar joeyjoeyINCLUDE ../star3do.typ PATH yehat PACKAGE YEHAT_CODE_PACKAGE yehat.shp CODE YEHAT_CODE yehat.cod GFXRES YEHAT_ICON_MASK_PMAP_ANIM yehicons.ani GFXRES YEHAT_MICON_MASK_PMAP_ANIM yehmicon.ani STRTAB YEHAT_RACE_STRINGS yehtext.txt PACKAGE YEHAT_PACKAGE yehat.shp GFXRES YEHAT_BIG_MASK_PMAP_ANIM yehat.big GFXRES YEHAT_MED_MASK_PMAP_ANIM yehat.med GFXRES YEHAT_SML_MASK_PMAP_ANIM yehat.sml GFXRES YEHAT_CANNON_BIG_MASK_PMAP_ANIM missile.big GFXRES YEHAT_CANNON_MED_MASK_PMAP_ANIM missile.med GFXRES YEHAT_CANNON_SML_MASK_PMAP_ANIM missile.sml GFXRES SHIELD_BIG_MASK_ANIM shield.big GFXRES SHIELD_MED_MASK_ANIM shield.med GFXRES SHIELD_SML_MASK_ANIM shield.sml GFXRES YEHAT_CAPTAIN_MASK_PMAP_ANIM yehcap.ani SNDRES YEHAT_SHIP_SOUNDS yehsound.snd MUSICRES YEHAT_VICTORY_SONG yehditty.mod uqm-0.6.2/sc2/src/sc2code/ships/yehat/igfxres.h0000600000175000017500000000105610543202073017665 0ustar joeyjoey#define YEHAT_ICON_MASK_PMAP_ANIM 0x00200002L #define YEHAT_MICON_MASK_PMAP_ANIM 0x00200102L #define YEHAT_BIG_MASK_PMAP_ANIM 0x00400202L #define YEHAT_MED_MASK_PMAP_ANIM 0x00400302L #define YEHAT_SML_MASK_PMAP_ANIM 0x00400402L #define YEHAT_CANNON_BIG_MASK_PMAP_ANIM 0x00400502L #define YEHAT_CANNON_MED_MASK_PMAP_ANIM 0x00400602L #define YEHAT_CANNON_SML_MASK_PMAP_ANIM 0x00400702L #define SHIELD_BIG_MASK_ANIM 0x00400802L #define SHIELD_MED_MASK_ANIM 0x00400902L #define SHIELD_SML_MASK_ANIM 0x00400a02L #define YEHAT_CAPTAIN_MASK_PMAP_ANIM 0x00400b02L uqm-0.6.2/sc2/src/sc2code/ships/yehat/isndres.h0000600000175000017500000000005010543202073017656 0ustar joeyjoey#define YEHAT_SHIP_SOUNDS 0x00400005L uqm-0.6.2/sc2/src/sc2code/ships/yehat/istrtab.h0000600000175000017500000000005110543202073017660 0ustar joeyjoey#define YEHAT_RACE_STRINGS 0x00200004L uqm-0.6.2/sc2/src/sc2code/ships/yehat/imusicre.h0000600000175000017500000000005110543202073020030 0ustar joeyjoey#define YEHAT_VICTORY_SONG 0x00400006L uqm-0.6.2/sc2/src/sc2code/ships/yehat/icode.h0000600000175000017500000000004110543202073017272 0ustar joeyjoey#define YEHAT_CODE 0x00200008L uqm-0.6.2/sc2/src/sc2code/ships/yehat/Makeinfo0000600000175000017500000000002510543202073017514 0ustar joeyjoeyuqm_CFILES="yehat.c" uqm-0.6.2/sc2/src/sc2code/ships/yehat/respkg.h0000600000175000017500000000006310543202073017506 0ustar joeyjoeyenum { YEHAT_CODE_PACKAGE = 1, YEHAT_PACKAGE }; uqm-0.6.2/sc2/src/sc2code/ships/yehat/yehat.c0000600000175000017500000002337110543202073017327 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ships/ship.h" #include "ships/yehat/resinst.h" #include "libs/mathlib.h" #define MAX_CREW 20 #define MAX_ENERGY 10 #define ENERGY_REGENERATION 2 #define WEAPON_ENERGY_COST 1 #define SPECIAL_ENERGY_COST 3 #define ENERGY_WAIT 6 #define MAX_THRUST 30 #define THRUST_INCREMENT 6 #define TURN_WAIT 2 #define THRUST_WAIT 2 #define WEAPON_WAIT 0 #define SPECIAL_WAIT 2 #define SHIP_MASS 3 #define MISSILE_SPEED DISPLAY_TO_WORLD (20) #define MISSILE_LIFE 10 static RACE_DESC yehat_desc = { { FIRES_FORE | SHIELD_DEFENSE, 23, /* Super Melee cost */ 750 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ MAX_CREW, MAX_CREW, MAX_ENERGY, MAX_ENERGY, { 4970, 40, }, (STRING)YEHAT_RACE_STRINGS, (FRAME)YEHAT_ICON_MASK_PMAP_ANIM, (FRAME)YEHAT_MICON_MASK_PMAP_ANIM, }, { MAX_THRUST, THRUST_INCREMENT, ENERGY_REGENERATION, WEAPON_ENERGY_COST, SPECIAL_ENERGY_COST, ENERGY_WAIT, TURN_WAIT, THRUST_WAIT, WEAPON_WAIT, SPECIAL_WAIT, SHIP_MASS, }, { { (FRAME)YEHAT_BIG_MASK_PMAP_ANIM, (FRAME)YEHAT_MED_MASK_PMAP_ANIM, (FRAME)YEHAT_SML_MASK_PMAP_ANIM, }, { (FRAME)YEHAT_CANNON_BIG_MASK_PMAP_ANIM, (FRAME)YEHAT_CANNON_MED_MASK_PMAP_ANIM, (FRAME)YEHAT_CANNON_SML_MASK_PMAP_ANIM, }, { (FRAME)SHIELD_BIG_MASK_ANIM, (FRAME)SHIELD_MED_MASK_ANIM, (FRAME)SHIELD_SML_MASK_ANIM, }, { (FRAME)YEHAT_CAPTAIN_MASK_PMAP_ANIM, (FRAME)0, (FRAME)0, (FRAME)0, (FRAME)0, }, (SOUND)YEHAT_VICTORY_SONG, (SOUND)YEHAT_SHIP_SOUNDS, }, { 0, MISSILE_SPEED * MISSILE_LIFE / 3, NULL_PTR, }, (UNINIT_FUNC *) NULL, (PREPROCESS_FUNC *) NULL, (POSTPROCESS_FUNC *) NULL, (INIT_WEAPON_FUNC *) NULL, 0, }; static COUNT initialize_standard_missiles (PELEMENT ShipPtr, HELEMENT MissileArray[]) { #define YEHAT_OFFSET 16 #define LAUNCH_OFFS DISPLAY_TO_WORLD (8) #define MISSILE_HITS 1 #define MISSILE_DAMAGE 1 #define MISSILE_OFFSET 1 SIZE offs_x, offs_y; STARSHIPPTR StarShipPtr; MISSILE_BLOCK MissileBlock; GetElementStarShip (ShipPtr, &StarShipPtr); MissileBlock.farray = StarShipPtr->RaceDescPtr->ship_data.weapon; MissileBlock.face = MissileBlock.index = StarShipPtr->ShipFacing; MissileBlock.sender = (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY)) | IGNORE_SIMILAR; MissileBlock.pixoffs = YEHAT_OFFSET; MissileBlock.speed = MISSILE_SPEED; MissileBlock.hit_points = MISSILE_HITS; MissileBlock.damage = MISSILE_DAMAGE; MissileBlock.life = MISSILE_LIFE; MissileBlock.preprocess_func = NULL_PTR; MissileBlock.blast_offs = MISSILE_OFFSET; offs_x = -SINE (FACING_TO_ANGLE (MissileBlock.face), LAUNCH_OFFS); offs_y = COSINE (FACING_TO_ANGLE (MissileBlock.face), LAUNCH_OFFS); MissileBlock.cx = ShipPtr->next.location.x + offs_x; MissileBlock.cy = ShipPtr->next.location.y + offs_y; MissileArray[0] = initialize_missile (&MissileBlock); MissileBlock.cx = ShipPtr->next.location.x - offs_x; MissileBlock.cy = ShipPtr->next.location.y - offs_y; MissileArray[1] = initialize_missile (&MissileBlock); return (2); } static void yehat_intelligence (PELEMENT ShipPtr, PEVALUATE_DESC ObjectsOfConcern, COUNT ConcernCounter) { SIZE ShieldStatus; STARSHIPPTR StarShipPtr; PEVALUATE_DESC lpEvalDesc; ShieldStatus = -1; lpEvalDesc = &ObjectsOfConcern[ENEMY_WEAPON_INDEX]; if (lpEvalDesc->ObjectPtr && lpEvalDesc->MoveState == ENTICE) { ShieldStatus = 0; if (!(lpEvalDesc->ObjectPtr->state_flags & (FINITE_LIFE | CREW_OBJECT))) lpEvalDesc->MoveState = PURSUE; else if (lpEvalDesc->ObjectPtr->mass_points || (lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) { if (!(lpEvalDesc->ObjectPtr->state_flags & FINITE_LIFE)) lpEvalDesc->which_turn <<= 1; else { if ((lpEvalDesc->which_turn >>= 1) == 0) lpEvalDesc->which_turn = 1; if (lpEvalDesc->ObjectPtr->mass_points) lpEvalDesc->ObjectPtr = 0; else lpEvalDesc->MoveState = PURSUE; } ShieldStatus = 1; } } GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->special_counter == 0) { StarShipPtr->ship_input_state &= ~SPECIAL; if (ShieldStatus) { if (ShipPtr->life_span <= NORMAL_LIFE + 1 && (ShieldStatus > 0 || lpEvalDesc->ObjectPtr) && lpEvalDesc->which_turn <= 2 && (ShieldStatus > 0 || (lpEvalDesc->ObjectPtr->state_flags & PLAYER_SHIP) /* means IMMEDIATE WEAPON */ || PlotIntercept (lpEvalDesc->ObjectPtr, ShipPtr, 2, 0)) && (TFB_Random () & 3)) StarShipPtr->ship_input_state |= SPECIAL; if (lpEvalDesc->ObjectPtr && !(lpEvalDesc->ObjectPtr->state_flags & CREW_OBJECT)) lpEvalDesc->ObjectPtr = 0; } } if ((lpEvalDesc = &ObjectsOfConcern[ENEMY_SHIP_INDEX])->ObjectPtr) { STARSHIPPTR EnemyStarShipPtr; GetElementStarShip (lpEvalDesc->ObjectPtr, &EnemyStarShipPtr); if (!(EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & IMMEDIATE_WEAPON)) lpEvalDesc->MoveState = PURSUE; } ship_intelligence (ShipPtr, ObjectsOfConcern, ConcernCounter); /* if (StarShipPtr->RaceDescPtr->ship_info.energy_level <= SPECIAL_ENERGY_COST) StarShipPtr->ship_input_state &= ~WEAPON; */ } static void yehat_postprocess (PELEMENT ElementPtr) { if (!(ElementPtr->state_flags & NONSOLID)) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); /* take care of shield effect */ if (StarShipPtr->special_counter > 0) { if (ElementPtr->life_span == NORMAL_LIFE) StarShipPtr->special_counter = 0; else { #ifdef OLD SetPrimColor ( &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) ); SetPrimType ( &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], STAMPFILL_PRIM ); #endif /* OLD */ ProcessSound (SetAbsSoundIndex ( /* YEHAT_SHIELD_ON */ StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), ElementPtr); DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST); } } #ifdef OLD if (ElementPtr->life_span > NORMAL_LIFE) { HELEMENT hShipElement; if (hShipElement = AllocElement ()) { ELEMENTPTR ShipElementPtr; InsertElement (hShipElement, GetSuccElement (ElementPtr)); LockElement (hShipElement, &ShipElementPtr); ShipElementPtr->state_flags = /* in place of APPEARING */ (CHANGING | PRE_PROCESS | POST_PROCESS) | FINITE_LIFE | NONSOLID | (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); SetPrimType ( &(GLOBAL (DisplayArray))[ShipElementPtr->PrimIndex], STAMP_PRIM ); ShipElementPtr->life_span = 0; /* because preprocessing * will not be done */ ShipElementPtr->current.location = ElementPtr->next.location; ShipElementPtr->current.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; ShipElementPtr->current.image.frame = SetAbsFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], StarShipPtr->ShipFacing); ShipElementPtr->next = ShipElementPtr->current; ShipElementPtr->preprocess_func = ShipElementPtr->postprocess_func = ShipElementPtr->death_func = NULL_PTR; ZeroVelocityComponents (&ShipElementPtr->velocity); UnlockElement (hShipElement); } } #endif /* OLD */ } } static void yehat_preprocess (PELEMENT ElementPtr) { if (!(ElementPtr->state_flags & APPEARING)) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if ((ElementPtr->life_span > NORMAL_LIFE /* take care of shield effect */ && --ElementPtr->life_span == NORMAL_LIFE) || (ElementPtr->life_span == NORMAL_LIFE && ElementPtr->next.image.farray == StarShipPtr->RaceDescPtr->ship_data.special)) { #ifdef NEVER SetPrimType ( &(GLOBAL (DisplayArray))[ElementPtr->PrimIndex], STAMP_PRIM ); #endif /* NEVER */ ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.ship; ElementPtr->next.image.frame = SetEquFrameIndex (StarShipPtr->RaceDescPtr->ship_data.ship[0], ElementPtr->next.image.frame); ElementPtr->state_flags |= CHANGING; } if ((StarShipPtr->cur_status_flags & SPECIAL) && StarShipPtr->special_counter == 0) { if (StarShipPtr->RaceDescPtr->ship_info.energy_level < SPECIAL_ENERGY_COST) DeltaEnergy (ElementPtr, -SPECIAL_ENERGY_COST); /* so text will flash */ else { #define SHIELD_LIFE 10 ElementPtr->life_span = SHIELD_LIFE + NORMAL_LIFE; ElementPtr->next.image.farray = StarShipPtr->RaceDescPtr->ship_data.special; ElementPtr->next.image.frame = SetEquFrameIndex (StarShipPtr->RaceDescPtr->ship_data.special[0], ElementPtr->next.image.frame); ElementPtr->state_flags |= CHANGING; StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->characteristics.special_wait; } } } } RACE_DESCPTR init_yehat (void) { RACE_DESCPTR RaceDescPtr; yehat_desc.preprocess_func = yehat_preprocess; yehat_desc.postprocess_func = yehat_postprocess; yehat_desc.init_weapon_func = initialize_standard_missiles; yehat_desc.cyborg_control.intelligence_func = (void (*) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter)) yehat_intelligence; RaceDescPtr = &yehat_desc; return (RaceDescPtr); } uqm-0.6.2/sc2/src/sc2code/ships/yehat/resinst.h0000600000175000017500000000015010543202073017677 0ustar joeyjoey#include "igfxres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "icode.h" uqm-0.6.2/sc2/src/sc2code/setupmenu.h0000600000175000017500000000413710543202101015776 0ustar joeyjoey// Copyright Michael Martin, 2004. /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SETUPMENU_H #define _SETUPMENU_H #include "controls.h" typedef enum { OPTVAL_DISABLED, OPTVAL_ENABLED } OPT_ENABLABLE; typedef enum { OPTVAL_PC, OPTVAL_3DO } OPT_CONSOLETYPE; typedef enum { OPTVAL_NO_SCALE, OPTVAL_BILINEAR_SCALE, OPTVAL_BIADAPT_SCALE, OPTVAL_BIADV_SCALE, OPTVAL_TRISCAN_SCALE, OPTVAL_HQXX_SCALE, } OPT_SCALETYPE; typedef enum { OPTVAL_320_240, OPTVAL_640_480, OPTVAL_800_600, OPTVAL_1024_768, OPTVAL_CUSTOM } OPT_RESTYPE; typedef enum { OPTVAL_PURE_IF_POSSIBLE, OPTVAL_ALWAYS_GL } OPT_DRIVERTYPE; typedef enum { OPTVAL_SILENCE, OPTVAL_MIXSDL, OPTVAL_OPENAL } OPT_ADRIVERTYPE; typedef enum { OPTVAL_LOW, OPTVAL_MEDIUM, OPTVAL_HIGH } OPT_AQUALITYTYPE; /* At the moment, CONTROL_TEMPLATE is directly in this structure. If * CONTROL_TEMPLATE and the options available diverge, this will need * to change */ typedef struct globalopts_struct { OPT_SCALETYPE scaler; OPT_RESTYPE res; OPT_DRIVERTYPE driver; OPT_ADRIVERTYPE adriver; OPT_AQUALITYTYPE aquality; OPT_ENABLABLE fullscreen, subtitles, scanlines, fps, stereo; OPT_CONSOLETYPE music, menu, text, cscan, scroll, intro, meleezoom, shield; CONTROL_TEMPLATE player1, player2; int speechvol, musicvol, sfxvol; } GLOBALOPTS; void SetupMenu (void); void GetGlobalOptions (GLOBALOPTS *opts); void SetGlobalOptions (GLOBALOPTS *opts); #endif // _SETUPMENU_H uqm-0.6.2/sc2/src/sc2code/oscill.h0000600000175000017500000000232710543202101015235 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _OSCILL_H #define _OSCILL_H #include "libs/compiler.h" #include "libs/gfxlib.h" extern BOOLEAN sliderDisabled; extern BOOLEAN oscillDisabled; extern void InitOscilloscope (DWORD x, DWORD y, DWORD width, DWORD height, FRAME f); extern void Oscilloscope (DWORD grab_data); extern void UninitOscilloscope (void); extern void InitSlider (int x, int y, int width, int height, int bwidth, int bheight, FRAME f); extern void SetSliderImage (FRAME f); void Slider (void); #endif /* _OSCILL_H */ uqm-0.6.2/sc2/src/sc2code/ship.c0000600000175000017500000003447710543202101014721 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "collide.h" #include "colors.h" #include "globdata.h" #include "intel.h" #include "races.h" #include "setup.h" #include "sounds.h" #include "libs/mathlib.h" void animation_preprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { ElementPtr->next.image.frame = IncFrameIndex (ElementPtr->current.image.frame); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = ElementPtr->next_turn; } } UWORD inertial_thrust (ELEMENTPTR ElementPtr) { #define MAX_ALLOWED_SPEED WORLD_TO_VELOCITY (DISPLAY_TO_WORLD (18)) #define MAX_ALLOWED_SPEED_SQR ((DWORD)MAX_ALLOWED_SPEED * MAX_ALLOWED_SPEED) COUNT CurrentAngle, TravelAngle; COUNT max_thrust, thrust_increment; VELOCITYPTR VelocityPtr; STARSHIPPTR StarShipPtr; VelocityPtr = &ElementPtr->velocity; GetElementStarShip (ElementPtr, &StarShipPtr); CurrentAngle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); TravelAngle = GetVelocityTravelAngle (VelocityPtr); thrust_increment = StarShipPtr->RaceDescPtr->characteristics.thrust_increment; max_thrust = StarShipPtr->RaceDescPtr->characteristics.max_thrust; if (thrust_increment == max_thrust) { // inertialess acceleration (Skiff) SetVelocityVector (VelocityPtr, max_thrust, StarShipPtr->ShipFacing); return (SHIP_AT_MAX_SPEED); } else if (TravelAngle == CurrentAngle && (StarShipPtr->cur_status_flags & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) && !(StarShipPtr->cur_status_flags & SHIP_IN_GRAVITY_WELL)) { // already maxed-out acceleration return (StarShipPtr->cur_status_flags & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)); } else { SIZE delta_x, delta_y; SIZE cur_delta_x, cur_delta_y; DWORD desired_speed, max_speed; DWORD current_speed; thrust_increment = WORLD_TO_VELOCITY (thrust_increment); GetCurrentVelocityComponents (VelocityPtr, &cur_delta_x, &cur_delta_y); current_speed = VelocitySquared (cur_delta_x, cur_delta_y); delta_x = cur_delta_x + COSINE (CurrentAngle, thrust_increment); delta_y = cur_delta_y + SINE (CurrentAngle, thrust_increment); desired_speed = VelocitySquared (delta_x, delta_y); max_speed = VelocitySquared (WORLD_TO_VELOCITY (max_thrust), 0); if (desired_speed <= max_speed) { // normal acceleration SetVelocityComponents (VelocityPtr, delta_x, delta_y); } else if (((StarShipPtr->cur_status_flags & SHIP_IN_GRAVITY_WELL) && desired_speed <= MAX_ALLOWED_SPEED_SQR) || desired_speed < current_speed) { // acceleration in a gravity well within max allowed // deceleration after gravity whip SetVelocityComponents (VelocityPtr, delta_x, delta_y); return (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); } else if (TravelAngle == CurrentAngle) { // normal max acceleration, same vector if (current_speed <= max_speed) SetVelocityVector (VelocityPtr, max_thrust, StarShipPtr->ShipFacing); return (SHIP_AT_MAX_SPEED); } else { // maxed-out acceleration at an angle to current travel vector // thrusting at an angle while at max velocity only changes // the travel vector, but does not really change the velocity VELOCITY_DESC v = *VelocityPtr; DeltaVelocityComponents (&v, COSINE (CurrentAngle, thrust_increment >> 1) - COSINE (TravelAngle, thrust_increment), SINE (CurrentAngle, thrust_increment >> 1) - SINE (TravelAngle, thrust_increment)); GetCurrentVelocityComponents (&v, &cur_delta_x, &cur_delta_y); desired_speed = VelocitySquared (cur_delta_x, cur_delta_y); if (desired_speed > max_speed) { if (desired_speed < current_speed) *VelocityPtr = v; return (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); } *VelocityPtr = v; } return (0); } } void ship_preprocess (PELEMENT ElementPtr) { ELEMENT_FLAGS cur_status_flags; STARSHIPPTR StarShipPtr; RACE_DESCPTR RDPtr; GetElementStarShip (ElementPtr, &StarShipPtr); RDPtr = StarShipPtr->RaceDescPtr; cur_status_flags = StarShipPtr->cur_status_flags & ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL); if (!(ElementPtr->state_flags & APPEARING)) cur_status_flags |= StarShipPtr->ship_input_state & (LEFT | RIGHT | THRUST | WEAPON | SPECIAL); else { ElementPtr->crew_level = RDPtr->ship_info.crew_level; if ((ElementPtr->state_flags & BAD_GUY) && LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) { STAMP s; CONTEXT OldContext; OldContext = SetContext (StatusContext); s.origin.x = s.origin.y = 0; s.frame = RDPtr->ship_data.captain_control.background; DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); RDPtr->ship_data.captain_control.background = 0; SetContext (OldContext); } else if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER) { CONTEXT OldContext; InitShipStatus (StarShipPtr, NULL_PTR); OldContext = SetContext (StatusContext); DrawCaptainsWindow (StarShipPtr); SetContext (OldContext); if (RDPtr->preprocess_func) (*RDPtr->preprocess_func) (ElementPtr); if (ElementPtr->hTarget == 0) { extern void ship_transition (PELEMENT ElementPtr); ship_transition (ElementPtr); } else { extern BOOLEAN OpponentAlive (STARSHIPPTR TestStarShipPtr); ElementPtr->hTarget = 0; if (!PLRPlaying ((MUSIC_REF)~0) && OpponentAlive (StarShipPtr)) BattleSong (TRUE); } return; } else { ElementPtr->current.location.x = LOG_SPACE_WIDTH >> 1; ElementPtr->current.location.y = LOG_SPACE_HEIGHT >> 1; ElementPtr->next.location = ElementPtr->current.location; InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); UnlockMutex (GraphicsLock); ResumeGameClock (); SetGameClockRate (HYPERSPACE_CLOCK_RATE); LockMutex (GraphicsLock); if (hyper_transition (ElementPtr)) return; } } StarShipPtr->cur_status_flags = cur_status_flags; if (StarShipPtr->energy_counter) --StarShipPtr->energy_counter; else if (RDPtr->ship_info.energy_level < (BYTE)RDPtr->ship_info.max_energy || (SBYTE)RDPtr->characteristics.energy_regeneration < 0) DeltaEnergy ((ELEMENTPTR)ElementPtr, (SBYTE)RDPtr->characteristics.energy_regeneration); if (RDPtr->preprocess_func) { (*RDPtr->preprocess_func) (ElementPtr); cur_status_flags = StarShipPtr->cur_status_flags; } if (ElementPtr->turn_wait) --ElementPtr->turn_wait; else if (cur_status_flags & (LEFT | RIGHT)) { if (cur_status_flags & LEFT) StarShipPtr->ShipFacing = NORMALIZE_FACING (StarShipPtr->ShipFacing - 1); else StarShipPtr->ShipFacing = NORMALIZE_FACING (StarShipPtr->ShipFacing + 1); ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->next.image.frame, StarShipPtr->ShipFacing); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = RDPtr->characteristics.turn_wait; } if (ElementPtr->thrust_wait) --ElementPtr->thrust_wait; else if (cur_status_flags & THRUST) { UWORD thrust_status; thrust_status = inertial_thrust ((ELEMENTPTR)ElementPtr); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED | SHIP_IN_GRAVITY_WELL); StarShipPtr->cur_status_flags |= thrust_status; ElementPtr->thrust_wait = RDPtr->characteristics.thrust_wait; if (!OBJECT_CLOAKED (ElementPtr) && LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER) { extern void spawn_ion_trail (PELEMENT ElementPtr); spawn_ion_trail (ElementPtr); } } if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER) PreProcessStatus (ElementPtr); } void ship_postprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; RACE_DESCPTR RDPtr; if (ElementPtr->crew_level == 0) return; GetElementStarShip (ElementPtr, &StarShipPtr); RDPtr = StarShipPtr->RaceDescPtr; if (StarShipPtr->weapon_counter) --StarShipPtr->weapon_counter; else if ((StarShipPtr->cur_status_flags & WEAPON) && DeltaEnergy ((ELEMENTPTR)ElementPtr, -RDPtr->characteristics.weapon_energy_cost)) { COUNT num_weapons; HELEMENT Weapon[6]; num_weapons = (*RDPtr->init_weapon_func) (ElementPtr, Weapon); if (num_weapons) { HELEMENT *WeaponPtr; STARSHIPPTR StarShipPtr; BOOLEAN played_sfx = FALSE; GetElementStarShip (ElementPtr, &StarShipPtr); WeaponPtr = &Weapon[0]; do { HELEMENT w; w = *WeaponPtr++; if (w) { ELEMENTPTR EPtr; LockElement (w, &EPtr); SetElementStarShip (EPtr, StarShipPtr); if (!played_sfx) { ProcessSound (RDPtr->ship_data.ship_sounds, EPtr); played_sfx = TRUE; } UnlockElement (w); PutElement (w); } } while (--num_weapons); if (!played_sfx) ProcessSound (RDPtr->ship_data.ship_sounds, ElementPtr); } StarShipPtr->weapon_counter = RDPtr->characteristics.weapon_wait; } if (StarShipPtr->special_counter) --StarShipPtr->special_counter; if (RDPtr->postprocess_func) (*RDPtr->postprocess_func) (ElementPtr); if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER) PostProcessStatus (ElementPtr); } void collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if (!(ElementPtr1->state_flags & FINITE_LIFE)) { ElementPtr0->state_flags |= COLLISION; if (GRAVITY_MASS (ElementPtr1->mass_points)) { // Collision with a planet. SIZE damage; damage = ElementPtr0->hit_points >> 2; if (damage == 0) damage = 1; do_damage ((ELEMENTPTR)ElementPtr0, damage); damage = TARGET_DAMAGED_FOR_1_PT + (damage >> 1); if (damage > TARGET_DAMAGED_FOR_6_PLUS_PT) damage = TARGET_DAMAGED_FOR_6_PLUS_PT; ProcessSound (SetAbsSoundIndex (GameSounds, damage), ElementPtr0); } } (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } static BOOLEAN spawn_ship (STARSHIPPTR StarShipPtr) { HELEMENT hShip; RACE_DESCPTR RDPtr; if (!load_ship (StarShipPtr, TRUE)) return (FALSE); RDPtr = StarShipPtr->RaceDescPtr; RDPtr->ship_info.var2 = (BYTE)StarShipPtr->ShipFacing; StarShipPtr->ship_input_state = 0; StarShipPtr->cur_status_flags = 0; StarShipPtr->old_status_flags = 0; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER || LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) { if (StarShipPtr->special_counter == 0) { // SIS, already handled from sis_ship.c. // RDPtr->ship_info.crew_level = GLOBAL_SIS (CrewEnlisted); } else RDPtr->ship_info.crew_level = StarShipPtr->special_counter; if (RDPtr->ship_info.crew_level > RDPtr->ship_info.max_crew) RDPtr->ship_info.crew_level = RDPtr->ship_info.max_crew; } StarShipPtr->energy_counter = 0; StarShipPtr->weapon_counter = 0; StarShipPtr->special_counter = 0; hShip = StarShipPtr->hShip; if (hShip == 0) { hShip = AllocElement (); if (hShip != 0) InsertElement (hShip, GetHeadElement ()); } StarShipPtr->hShip = hShip; if (StarShipPtr->hShip != 0) { // Construct an ELEMENT for the STARSHIP ELEMENTPTR ShipElementPtr; LockElement (hShip, &ShipElementPtr); ShipElementPtr->crew_level = 0; ShipElementPtr->mass_points = RDPtr->characteristics.ship_mass; ShipElementPtr->state_flags = APPEARING | PLAYER_SHIP | IGNORE_SIMILAR | (RDPtr->ship_info.ship_flags & (GOOD_GUY | BAD_GUY)); ShipElementPtr->turn_wait = ShipElementPtr->thrust_wait = 0; ShipElementPtr->life_span = NORMAL_LIFE; SetPrimType (&DisplayArray[ShipElementPtr->PrimIndex], STAMP_PRIM); ShipElementPtr->current.image.farray = RDPtr->ship_data.ship; if ((ShipElementPtr->state_flags & BAD_GUY) && LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) { // This is the Sa-Matra StarShipPtr->ShipFacing = 0; ShipElementPtr->current.image.frame = SetAbsFrameIndex (RDPtr->ship_data.ship[0], StarShipPtr->ShipFacing); ShipElementPtr->current.location.x = LOG_SPACE_WIDTH >> 1; ShipElementPtr->current.location.y = LOG_SPACE_HEIGHT >> 1; ++ShipElementPtr->life_span; } else { StarShipPtr->ShipFacing = NORMALIZE_FACING (TFB_Random ()); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { COUNT facing; facing = LOWORD (GLOBAL (ShipStamp.frame)); if (facing > 0) --facing; GLOBAL (ShipStamp.frame) = (FRAME)MAKE_DWORD ( StarShipPtr->ShipFacing + 1, 0); StarShipPtr->ShipFacing = facing; } ShipElementPtr->current.image.frame = SetAbsFrameIndex (RDPtr->ship_data.ship[0], StarShipPtr->ShipFacing); do { ShipElementPtr->current.location.x = WRAP_X (DISPLAY_ALIGN_X (TFB_Random ())); ShipElementPtr->current.location.y = WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ())); } while (CalculateGravity (ShipElementPtr) || TimeSpaceMatterConflict (ShipElementPtr)); } ShipElementPtr->preprocess_func = ship_preprocess; ShipElementPtr->postprocess_func = ship_postprocess; ShipElementPtr->death_func = ship_death; ShipElementPtr->collision_func = collision; ZeroVelocityComponents (&ShipElementPtr->velocity); SetElementStarShip (ShipElementPtr, StarShipPtr); ShipElementPtr->hTarget = 0; UnlockElement (hShip); } return (hShip != 0); } BOOLEAN GetNextStarShip (STARSHIPPTR LastStarShipPtr, COUNT which_side) { HSTARSHIP hBattleShip; cur_player = which_side; CyborgDescPtr = 0; hBattleShip = GetEncounterStarShip (LastStarShipPtr, which_side); if (hBattleShip) { STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip (&race_q[which_side], hBattleShip); if (LastStarShipPtr) { if (StarShipPtr == LastStarShipPtr) LastStarShipPtr = 0; else StarShipPtr->hShip = LastStarShipPtr->hShip; } if (!spawn_ship (StarShipPtr)) { UnlockStarShip (&race_q[which_side], hBattleShip); return (FALSE); } UnlockStarShip (&race_q[which_side], hBattleShip); } if (LastStarShipPtr) LastStarShipPtr->hShip = 0; return (hBattleShip != 0); } uqm-0.6.2/sc2/src/sc2code/weapon.h0000600000175000017500000000341610543202101015241 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _WEAPON_H #define _WEAPON_H #include "element.h" #include "libs/gfxlib.h" typedef struct { COORD cx, cy, ex, ey; ELEMENT_FLAGS sender; SIZE pixoffs; COUNT face; COLOR color; } LASER_BLOCK; typedef LASER_BLOCK *PLASER_BLOCK; typedef struct { COORD cx, cy; ELEMENT_FLAGS sender; SIZE pixoffs, speed, hit_points, damage; COUNT face, index, life; PFRAME farray; void (*preprocess_func) (PELEMENT ElementPtr); SIZE blast_offs; } MISSILE_BLOCK; typedef MISSILE_BLOCK *PMISSILE_BLOCK; extern HELEMENT initialize_laser (PLASER_BLOCK pLaserBlock); extern HELEMENT initialize_missile (PMISSILE_BLOCK pMissileBlock); extern HELEMENT weapon_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1); extern SIZE TrackShip (ELEMENTPTR Tracker, PCOUNT pfacing); extern void Untarget (ELEMENTPTR ElementPtr); #define MODIFY_IMAGE (1 << 0) #define MODIFY_SWAP (1 << 1) extern FRAME ModifySilhouette (ELEMENTPTR ElementPtr, PSTAMP modify_stamp, BYTE modify_flags); #endif /* _WEAPON_H */ uqm-0.6.2/sc2/src/sc2code/pickship.c0000600000175000017500000003346310543202103015564 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "colors.h" #include "controls.h" #include "pickmele.h" #include "races.h" #include "resinst.h" #include "nameref.h" #include "settings.h" #include "setup.h" #include "sounds.h" #include "libs/mathlib.h" #define NUM_PICK_SHIP_ROWS 2 #define NUM_PICK_SHIP_COLUMNS 6 #define ICON_WIDTH 16 #define ICON_HEIGHT 16 #define FLAGSHIP_X_OFFS 65 #define FLAGSHIP_Y_OFFS 4 #define FLAGSHIP_WIDTH 22 #define FLAGSHIP_HEIGHT 48 static BOOLEAN DoPickBattleShip (PMENU_STATE pMS) { if (GLOBAL (CurrentActivity) & CHECK_ABORT) { pMS->CurFrame = 0; return (FALSE); } SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); if (!pMS->Initialized) { pMS->Initialized = TRUE; pMS->InputFunc = DoPickBattleShip; LockMutex (GraphicsLock); goto ChangeSelection; } else if (PulsedInputState.menu[KEY_MENU_SELECT]) { if ((HSTARSHIP)pMS->CurFrame) { PlayMenuSound (MENU_SOUND_SUCCESS); return (FALSE); } } else { COORD new_row, new_col; int dx = 0, dy = 0; if (PulsedInputState.menu[KEY_MENU_RIGHT]) dx = 1; if (PulsedInputState.menu[KEY_MENU_LEFT]) dx = -1; if (PulsedInputState.menu[KEY_MENU_UP]) dy = -1; if (PulsedInputState.menu[KEY_MENU_DOWN]) dy = 1; new_col = pMS->first_item.x + dx; new_row = pMS->first_item.y + dy; if (new_row != pMS->first_item.y || new_col != pMS->first_item.x) { RECT r; TEXT t; COUNT crew_level, max_crew; COUNT ship_index; HSTARSHIP hBattleShip, hNextShip; STARSHIPPTR StarShipPtr; if (new_col < 0) new_col = NUM_PICK_SHIP_COLUMNS; else if (new_col > NUM_PICK_SHIP_COLUMNS) new_col = 0; if (new_row < 0) new_row = NUM_PICK_SHIP_ROWS - 1; else if (new_row == NUM_PICK_SHIP_ROWS) new_row = 0; PlayMenuSound (MENU_SOUND_MOVE); LockMutex (GraphicsLock); #ifdef NEVER SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x1D)); DrawRectangle (&pMS->flash_rect0); #endif /* NEVER */ pMS->first_item.y = new_row; pMS->first_item.x = new_col; ChangeSelection: if (pMS->first_item.x == (NUM_PICK_SHIP_COLUMNS >> 1)) { pMS->flash_rect0.corner.x = pMS->flash_rect1.corner.x - 2 + FLAGSHIP_X_OFFS; pMS->flash_rect0.corner.y = pMS->flash_rect1.corner.y - 2 + FLAGSHIP_Y_OFFS; pMS->flash_rect0.extent.width = FLAGSHIP_WIDTH + 4; pMS->flash_rect0.extent.height = FLAGSHIP_HEIGHT + 4; hBattleShip = GetTailLink (&race_q[0]); /* Flagship */ } else { new_col = pMS->first_item.x; pMS->flash_rect0.corner.x = 5 + pMS->flash_rect1.corner.x - 2 + ((ICON_WIDTH + 4) * new_col); if (new_col > (NUM_PICK_SHIP_COLUMNS >> 1)) { --new_col; pMS->flash_rect0.corner.x += FLAGSHIP_WIDTH - ICON_WIDTH; } pMS->flash_rect0.corner.y = 16 + pMS->flash_rect1.corner.y - 2 + ((ICON_HEIGHT + 4) * pMS->first_item.y); pMS->flash_rect0.extent.width = ICON_WIDTH + 4; pMS->flash_rect0.extent.height = ICON_HEIGHT + 4; ship_index = (pMS->first_item.y * NUM_PICK_SHIP_COLUMNS) + new_col; for (hBattleShip = GetHeadLink (&race_q[0]); hBattleShip != GetTailLink (&race_q[0]); hBattleShip = hNextShip) { StarShipPtr = LockStarShip (&race_q[0], hBattleShip); if ((COUNT)LONIBBLE ( StarShipPtr->RaceDescPtr->ship_info.var2 ) == ship_index && StarShipPtr->RaceResIndex) { UnlockStarShip (&race_q[0], hBattleShip); break; } hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (&race_q[0], hBattleShip); } if (hBattleShip == GetTailLink (&race_q[0])) hBattleShip = 0; } pMS->CurFrame = (FRAME)hBattleShip; SetContextForeGroundColor (BLACK_COLOR); r.corner.x = pMS->flash_rect1.corner.x + 6; r.corner.y = pMS->flash_rect1.corner.y + 5; r.extent.width = ((ICON_WIDTH + 4) * 3) - 4; r.extent.height = 7; DrawFilledRectangle (&r); if (hBattleShip == 0) { crew_level = 0; max_crew = 0; // Satisfy compiler. } else { SetContextFont (TinyFont); t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.y = r.corner.y + (r.extent.height - 1); t.align = ALIGN_CENTER; StarShipPtr = LockStarShip (&race_q[0], hBattleShip); if (StarShipPtr->captains_name_index == 0) { t.pStr = GLOBAL_SIS (CommanderName); t.CharCount = (COUNT)~0; crew_level = GLOBAL_SIS (CrewEnlisted); max_crew = GetCPodCapacity (NULL_PTR); } else { STRING locString; locString = SetAbsStringTableIndex ( StarShipPtr->RaceDescPtr->ship_info.race_strings, StarShipPtr->captains_name_index); t.pStr = (UNICODE *)GetStringAddress (locString); t.CharCount = GetStringLength (locString); crew_level = StarShipPtr->RaceDescPtr->ship_info.crew_level; max_crew = StarShipPtr->RaceDescPtr->ship_info.max_crew; } UnlockStarShip (&race_q[0], hBattleShip); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x14, 0x0A, 0x00), 0x0C)); font_DrawText (&t); SetContextForeGroundColor (BLACK_COLOR); } r.corner.x += (ICON_WIDTH + 4) * ((NUM_PICK_SHIP_COLUMNS >> 1) + 1) + FLAGSHIP_WIDTH - ICON_WIDTH; DrawFilledRectangle (&r); if (crew_level) { char buf[80]; t.baseline.x = r.corner.x + (r.extent.width >> 1); t.pStr = buf; t.CharCount = (COUNT)~0; if (crew_level >= max_crew) sprintf (buf, "%u", crew_level); else sprintf (buf, "%u/%u", crew_level, max_crew); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02)); font_DrawText (&t); } SetFlashRect (NULL_PTR, (FRAME)0); SetFlashRect (&pMS->flash_rect0, (FRAME)0); UnlockMutex (GraphicsLock); } } return (TRUE); } static HSTARSHIP GetArmadaStarShip (void) { RECT pick_r; CONTEXT OldContext; HSTARSHIP hBattleShip; if (HIBYTE (battle_counter) == 0) { return (0); } // MenuSounds = CaptureSound (LoadSound (MENU_SOUNDS)); OldContext = SetContext (SpaceContext); DrawArmadaPickShip (FALSE, &pick_r); { MENU_STATE MenuState; MenuState.InputFunc = DoPickBattleShip; MenuState.Initialized = FALSE; MenuState.first_item.x = NUM_PICK_SHIP_COLUMNS >> 1; MenuState.first_item.y = 0; MenuState.flash_task = 0; MenuState.CurFrame = 0; MenuState.flash_rect1.corner = pick_r.corner; MenuState.flash_rect1.extent.width = 0; UnlockMutex (GraphicsLock); pMenuState = &MenuState; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); DoInput ((PVOID)&MenuState, FALSE); pMenuState = 0; LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); hBattleShip = (HSTARSHIP)MenuState.CurFrame; } if (hBattleShip) { if (hBattleShip == GetTailLink (&race_q[0])) battle_counter = MAKE_WORD (1, HIBYTE (battle_counter)); WaitForSoundEnd (0); } // DestroySound (ReleaseSound (MenuSounds)); SetContext (OldContext); return (hBattleShip); } HSTARSHIP GetEncounterStarShip (STARSHIPPTR LastStarShipPtr, COUNT which_player) { HSTARSHIP hBattleShip; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) // Get the next ship from the battle group. hBattleShip = GetHeadLink (&race_q[which_player]); else if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE) { // Let the player chose his own ship. (May be a computer player). hBattleShip = GetMeleeStarShip (LastStarShipPtr, which_player); } else { HSTARSHIP hStarShip; STARSHIPPTR SPtr; SHIP_FRAGMENTPTR FragPtr; if (LastStarShipPtr == 0) { if (which_player == 0 && LOBYTE (battle_counter) > 1) hBattleShip = GetArmadaStarShip (); else { hBattleShip = GetHeadLink (&race_q[which_player]); if (which_player == 1) { hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); if (FragPtr->ShipInfo.crew_level == INFINITE_FLEET) { // Infinite number of ships. battle_counter += MAKE_WORD (0, 1); } UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } } } else { PQUEUE pQueue; HSTARSHIP hNextShip; if (which_player == 0) pQueue = &GLOBAL (built_ship_q); else pQueue = &GLOBAL (npc_built_ship_q); hBattleShip = GetHeadLink (&race_q[which_player]); for (hStarShip = GetHeadLink (pQueue); hStarShip != 0; hStarShip = hNextShip) { SPtr = LockStarShip (&race_q[which_player], hBattleShip); hNextShip = _GetSuccLink (SPtr); UnlockStarShip (&race_q[which_player], hBattleShip); hBattleShip = hNextShip; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); if (SPtr == LastStarShipPtr) { if (FragPtr->ShipInfo.crew_level != INFINITE_FLEET) { FragPtr->ShipInfo.crew_level = SPtr->special_counter; SPtr->RaceDescPtr = (RACE_DESCPTR)&FragPtr->ShipInfo; if (GLOBAL (CurrentActivity) & IN_BATTLE) SPtr->RaceResIndex = 0; } else /* if infinite ships */ { hBattleShip = GetTailLink (&race_q[which_player]); SPtr->special_counter = FragPtr->ShipInfo.max_crew; SPtr->cur_status_flags = 1 << which_player; SPtr->captains_name_index = PickCaptainName (); battle_counter += MAKE_WORD (0, 1); } UnlockStarShip (pQueue, hStarShip); break; } hNextShip = _GetSuccLink (FragPtr); UnlockStarShip (pQueue, hStarShip); } if (which_player == 0) { if (LOBYTE (battle_counter)) hBattleShip = GetArmadaStarShip (); else /* last ship was flagship */ { #define RUN_AWAY_FUEL_COST (5 * FUEL_TANK_SCALE) hBattleShip = 0; if (LastStarShipPtr->special_counter == 0) /* died in the line of duty */ GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; else if (GLOBAL_SIS (FuelOnBoard) > RUN_AWAY_FUEL_COST) GLOBAL_SIS (FuelOnBoard) -= RUN_AWAY_FUEL_COST; else GLOBAL_SIS (FuelOnBoard) = 0; } } } if (hBattleShip) { SPtr = LockStarShip (&race_q[which_player], hBattleShip); OwnStarShip (SPtr, SPtr->cur_status_flags, SPtr->captains_name_index); UnlockStarShip (&race_q[which_player], hBattleShip); } } return (hBattleShip); } void DrawArmadaPickShip (BOOLEAN draw_salvage_frame, PRECT pPickRect) { #define PICK_NAME_HEIGHT 6 //COUNT i; HSTARSHIP hBattleShip, hNextShip; STARSHIPPTR StarShipPtr; RECT r, pick_r; STAMP s; TEXT t; CONTEXT OldContext; MEM_HANDLE hLastIndex; FRAME PickFrame; hLastIndex = SetResourceIndex (hResIndex); OldContext = SetContext (SpaceContext); PickFrame = CaptureDrawable (LoadGraphic (SC2_PICK_PMAP_ANIM)); BatchGraphics (); s.frame = PickFrame; SetFrameHot (s.frame, MAKE_HOT_SPOT (0, 0)); GetFrameRect (s.frame, &pick_r); GetContextClipRect (&r); pick_r.corner.x = (r.extent.width >> 1) - (pick_r.extent.width >> 1); pick_r.corner.y = (r.extent.height >> 1) - (pick_r.extent.height >> 1); if (!draw_salvage_frame) *pPickRect = pick_r; else { s.origin.x = r.extent.width >> 1; s.frame = IncFrameIndex (s.frame); SetFrameHot (s.frame, MAKE_HOT_SPOT (0, 0)); GetFrameRect (s.frame, &r); s.origin.x -= r.extent.width >> 1; s.origin.y = pick_r.corner.y - (r.extent.height >> 1); DrawStamp (&s); s.frame = DecFrameIndex (s.frame); pick_r.corner.y = s.origin.y + r.extent.height; r.corner.x = pick_r.corner.x; r.corner.y = s.origin.y; *pPickRect = r; } s.origin = pick_r.corner; DrawStamp (&s); t.baseline.x = pick_r.corner.x + (pick_r.extent.width >> 1); t.baseline.y = pick_r.corner.y + pick_r.extent.height - 5; t.align = ALIGN_CENTER; t.pStr = GLOBAL_SIS (ShipName); t.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x12, 0x12, 0x12), 0x17)); SetContextFont (StarConFont); font_DrawText (&t); r.extent.width = ICON_WIDTH; r.extent.height = ICON_HEIGHT; for (hBattleShip = GetHeadLink (&race_q[0]); hBattleShip != 0; hBattleShip = hNextShip) { StarShipPtr = LockStarShip (&race_q[0], hBattleShip); if (StarShipPtr->captains_name_index) { COUNT ship_index; ship_index = (COUNT)LONIBBLE ( StarShipPtr->RaceDescPtr->ship_info.var2); s.origin.x = pick_r.corner.x + (5 + ((ICON_WIDTH + 4) * (ship_index % NUM_PICK_SHIP_COLUMNS))); if ((ship_index % NUM_PICK_SHIP_COLUMNS) >= (NUM_PICK_SHIP_COLUMNS >> 1)) s.origin.x += FLAGSHIP_WIDTH + 4; s.origin.y = pick_r.corner.y + (16 + ((ICON_HEIGHT + 4) * (ship_index / NUM_PICK_SHIP_COLUMNS))); s.frame = StarShipPtr->RaceDescPtr->ship_info.icons; r.corner = s.origin; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); if (StarShipPtr->RaceResIndex || StarShipPtr->RaceDescPtr->ship_info.crew_level == 0) { DrawStamp (&s); if (StarShipPtr->RaceResIndex == 0) { /* Dead ship - mark with an X. */ s.origin.x -= 1; s.frame = SetAbsFrameIndex (StatusFrame, 3); DrawStamp (&s); } } else { /* Ship ran away */ SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); DrawFilledStamp (&s); } } hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (&race_q[0], hBattleShip); } UnbatchGraphics (); DestroyDrawable (ReleaseDrawable (PickFrame)); SetContext (OldContext); SetResourceIndex (hLastIndex); } uqm-0.6.2/sc2/src/sc2code/restart.c0000600000175000017500000002313410543202103015430 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "restart.h" #include "colors.h" #include "controls.h" #include "credits.h" #include "encount.h" #include "fmv.h" #include "globdata.h" #include "intel.h" #include "melee.h" #include "resinst.h" #include "nameref.h" #include "settings.h" #include "load.h" #include "setup.h" #include "sounds.h" #include "setupmenu.h" #include "util.h" #include "starcon.h" #include "uqmversion.h" #include "libs/graphics/gfx_common.h" #include "libs/inplib.h" enum { START_NEW_GAME = 0, LOAD_SAVED_GAME, PLAY_SUPER_MELEE, SETUP_GAME, QUIT_GAME }; static void DrawRestartMenuGraphic (PMENU_STATE pMS) { RECT r; STAMP s; s.frame = CaptureDrawable ( LoadGraphic (RESTART_PMAP_ANIM) ); pMS->CurFrame = s.frame; GetFrameRect (s.frame, &r); s.origin.x = (SCREEN_WIDTH - r.extent.width) >> 1; s.origin.y = (SCREEN_HEIGHT - r.extent.height) >> 1; SetContextBackGroundColor (BLACK_COLOR); BatchGraphics (); ClearDrawable (); FlushColorXForms (); LockMutex (GraphicsLock); DrawStamp (&s); UnlockMutex (GraphicsLock); UnbatchGraphics (); } static void DrawRestartMenu (BYTE OldState, BYTE NewState, FRAME f) { RECT r; TEXT t; UNICODE buf[64]; LockMutex (GraphicsLock); SetContext (ScreenContext); r.corner.x = r.corner.y = r.extent.width = r.extent.height = 0; SetContextClipRect (&r); r.corner.x = 0; r.corner.y = 0; r.extent.width = SCREEN_WIDTH; r.extent.height = SCREEN_HEIGHT; SetFlashRect (&r, SetAbsFrameIndex (f, NewState + 1)); // Put version number in the corner SetContextFont (TinyFont); t.pStr = buf; t.baseline.x = SCREEN_WIDTH - 3; t.baseline.y = SCREEN_HEIGHT - 2; t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; sprintf (buf, "v%d.%d.%d%s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION); SetContextForeGroundColor (WHITE_COLOR); font_DrawText (&t); UnlockMutex (GraphicsLock); (void) OldState; /* Satisfying compiler (unused parameter) */ } static BOOLEAN DoRestart (PMENU_STATE pMS) { static DWORD InTime; static DWORD InactTimeOut; /* Cancel any presses of the Pause key. */ GamePaused = FALSE; if (!pMS->Initialized) { if (pMS->hMusic) { StopMusic (); DestroyMusic (pMS->hMusic); pMS->hMusic = 0; } pMS->hMusic = LoadMusic (MAINMENU_MUSIC); InactTimeOut = (pMS->hMusic ? 120 : 20) * ONE_SECOND; PlayMusic (pMS->hMusic, TRUE, 1); DrawRestartMenu ((BYTE)~0, pMS->CurState, pMS->CurFrame); pMS->Initialized = TRUE; { BYTE clut_buf[] = {FadeAllToColor}; DWORD TimeOut = XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 2); while ((GetTimeCounter () <= TimeOut) && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) { UpdateInputState (); TaskSwitch (); } } } #ifdef TESTING else if (InputState & DEVICE_EXIT) return (FALSE); #endif /* TESTING */ else if (GLOBAL (CurrentActivity) & CHECK_ABORT) { return (FALSE); } else if (!(PulsedInputState.menu[KEY_MENU_UP] || PulsedInputState.menu[KEY_MENU_DOWN] || PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_RIGHT] || PulsedInputState.menu[KEY_MENU_SELECT] || MouseButtonDown)) { if (GetTimeCounter () - InTime < InactTimeOut) return (TRUE); SleepThreadUntil (FadeMusic (0, ONE_SECOND)); StopMusic (); FadeMusic (NORMAL_VOLUME, 0); GLOBAL (CurrentActivity) = (ACTIVITY)~0; return (FALSE); } else if (PulsedInputState.menu[KEY_MENU_SELECT]) { BYTE fade_buf[1]; switch (pMS->CurState) { case LOAD_SAVED_GAME: LastActivity = CHECK_LOAD; GLOBAL (CurrentActivity) = IN_INTERPLANETARY; break; case START_NEW_GAME: LastActivity = CHECK_LOAD | CHECK_RESTART; GLOBAL (CurrentActivity) = IN_INTERPLANETARY; break; case PLAY_SUPER_MELEE: GLOBAL (CurrentActivity) = SUPER_MELEE; break; case SETUP_GAME: LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); SetupMenu (); SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT); InTime = GetTimeCounter (); SetTransitionSource (NULL); BatchGraphics (); DrawRestartMenuGraphic (pMS); DrawRestartMenu ((BYTE)~0, pMS->CurState, pMS->CurFrame); ScreenTransition (3, NULL); UnbatchGraphics (); return TRUE; case QUIT_GAME: fade_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND / 2)); GLOBAL (CurrentActivity) = CHECK_ABORT; break; } LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); return (FALSE); } else { BYTE NewState; NewState = pMS->CurState; if (PulsedInputState.menu[KEY_MENU_UP]) { if (NewState-- == START_NEW_GAME) NewState = QUIT_GAME; } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { if (NewState++ == QUIT_GAME) NewState = START_NEW_GAME; } if (NewState != pMS->CurState) { BatchGraphics (); DrawRestartMenu (pMS->CurState, NewState, pMS->CurFrame); UnbatchGraphics (); pMS->CurState = NewState; } } if (MouseButtonDown) { LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); MouseError (); SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT); SetTransitionSource (NULL); BatchGraphics (); DrawRestartMenuGraphic (pMS); DrawRestartMenu ((BYTE)~0, pMS->CurState, pMS->CurFrame); ScreenTransition (3, NULL); UnbatchGraphics (); } InTime = GetTimeCounter (); return (TRUE); } static BOOLEAN RestartMenu (PMENU_STATE pMS) { DWORD TimeOut; BYTE black_buf[1]; ReinitQueue (&race_q[0]); ReinitQueue (&race_q[1]); black_buf[0] = FadeAllToBlack; SetContext (ScreenContext); GLOBAL (CurrentActivity) |= CHECK_ABORT; if (GLOBAL_SIS (CrewEnlisted) == (COUNT)~0 && GET_GAME_STATE (UTWIG_BOMB_ON_SHIP) && !GET_GAME_STATE (UTWIG_BOMB)) { // player blew himself up with Utwig bomb BYTE white_buf[] = {FadeAllToWhite}; SET_GAME_STATE (UTWIG_BOMB_ON_SHIP, 0); SleepThreadUntil (XFormColorMap ((COLORMAPPTR)white_buf, ONE_SECOND / 8) + ONE_SECOND / 60); SetContextBackGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); ClearDrawable (); FlushColorXForms (); TimeOut = ONE_SECOND / 8; } else { TimeOut = ONE_SECOND / 2; if (LOBYTE (LastActivity) == WON_LAST_BATTLE) { GLOBAL (CurrentActivity) = WON_LAST_BATTLE; Victory (); Credits (TRUE); FreeGameData (); TimeOut = ONE_SECOND / 2; GLOBAL (CurrentActivity) = CHECK_ABORT; } } LastActivity = NextActivity = 0; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)black_buf, TimeOut)); if (TimeOut == ONE_SECOND / 8) SleepThread (ONE_SECOND * 3); DrawRestartMenuGraphic (pMS); FlushInput (); GLOBAL (CurrentActivity) &= ~CHECK_ABORT; SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT); DoInput (pMS, TRUE); StopMusic (); if (pMS->hMusic) { DestroyMusic (pMS->hMusic); pMS->hMusic = 0; } LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); DestroyDrawable (ReleaseDrawable (pMS->CurFrame)); if (GLOBAL (CurrentActivity) == (ACTIVITY)~0) return (FALSE); // timed out if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); // quit TimeOut = XFormColorMap ((COLORMAPPTR)black_buf, ONE_SECOND / 2); SleepThreadUntil (TimeOut); FlushColorXForms (); SeedRandomNumbers (); return (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE); } static BOOLEAN TryStartGame (void) { MENU_STATE MenuState; LastActivity = GLOBAL (CurrentActivity); GLOBAL (CurrentActivity) = 0; memset (&MenuState, 0, sizeof (MenuState)); MenuState.InputFunc = DoRestart; while (!RestartMenu (&MenuState)) { // spin until a game is started or loaded if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) { FreeGameData (); Melee (); MenuState.Initialized = FALSE; } else if (GLOBAL (CurrentActivity) == (ACTIVITY)~0) { // timed out BYTE black_buf[] = {FadeAllToBlack}; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)black_buf, ONE_SECOND / 2)); return (FALSE); } else if (GLOBAL (CurrentActivity) & CHECK_ABORT) { // quit return (FALSE); } } return TRUE; } BOOLEAN StartGame (void) { do { while (!TryStartGame ()) { if (GLOBAL (CurrentActivity) == (ACTIVITY)~0) { // timed out GLOBAL (CurrentActivity) = 0; SplashScreen (0); Credits (FALSE); } if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); // quit } if (LastActivity & CHECK_RESTART) { // starting a new game Introduction (); } } while (GLOBAL (CurrentActivity) & CHECK_ABORT); { extern STAR_DESC starmap_array[]; extern const BYTE element_array[]; extern const PlanetFrame planet_array[]; star_array = starmap_array; Elements = element_array; PlanData = planet_array; } PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING; PlayerControl[1] = COMPUTER_CONTROL | AWESOME_RATING; SetPlayerInput (); return (TRUE); } uqm-0.6.2/sc2/src/sc2code/netplay/0000755000175000017500000000000010552600274015274 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/netplay/netstate.c0000600000175000017500000000276210543202057017263 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "netplay.h" #include "netstate.h" #include #include #define DEFINE_NETSTATEDATA(stateName) \ { \ /* .name = */ #stateName, \ } NetStateData netStateData[] = { DEFINE_NETSTATEDATA(unconnected), DEFINE_NETSTATEDATA(connecting), DEFINE_NETSTATEDATA(init), DEFINE_NETSTATEDATA(inSetup), DEFINE_NETSTATEDATA(preBattle), DEFINE_NETSTATEDATA(interBattle), DEFINE_NETSTATEDATA(selectShip), DEFINE_NETSTATEDATA(inBattle), DEFINE_NETSTATEDATA(endingBattle), DEFINE_NETSTATEDATA(endingBattle2), DEFINE_NETSTATEDATA(endMelee), }; void NetConnectionStateData_release(NetConnectionStateData *stateData) { assert(stateData->releaseFunction != NULL); stateData->releaseFunction(stateData); } uqm-0.6.2/sc2/src/sc2code/netplay/checksum.c0000600000175000017500000001642210543202056017233 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef NETPLAY #include "checksum.h" #include "netoptions.h" #ifdef NETPLAY_CHECKSUM #include "checkbuf.h" #include "crc.h" // for DUMP_CRC_OPS #include "netconnection.h" #include "netmelee.h" #include "libs/log.h" #include "libs/mathlib.h" #include "libs/misc.h" ChecksumBuffer localChecksumBuffer; void crc_processEXTENT(crc_State *state, const EXTENT *val) { #ifdef DUMP_CRC_OPS log_add(log_Debug, "START crc_processEXTENT()."); #endif crc_processCOORD(state, val->width); crc_processCOORD(state, val->height); #ifdef DUMP_CRC_OPS log_add(log_Debug, "END crc_processEXTENT()."); #endif } void crc_processVELOCITY_DESC(crc_State *state, const VELOCITY_DESC *val) { #ifdef DUMP_CRC_OPS log_add(log_Debug, "START crc_processVELOCITY_DESC()."); #endif crc_processCOUNT(state, val->TravelAngle); crc_processEXTENT(state, &val->vector); crc_processEXTENT(state, &val->fract); crc_processEXTENT(state, &val->error); crc_processEXTENT(state, &val->incr); #ifdef DUMP_CRC_OPS log_add(log_Debug, "END crc_processVELOCITY_DESC()."); #endif } void crc_processPOINT(crc_State *state, const POINT *val) { #ifdef DUMP_CRC_OPS log_add(log_Debug, "START crc_processPOINT()."); #endif crc_processCOORD(state, val->x); crc_processCOORD(state, val->y); #ifdef DUMP_CRC_OPS log_add(log_Debug, "END crc_processPOINT()."); #endif } #if 0 void crc_processSTAMP(crc_State *state, const STAMP *val) { #ifdef DUMP_CRC_OPS log_add(log_Debug, "START crc_processSTAMP()."); #endif crc_processPOINT(state, val->origin); crc_processFRAME(state, val->frame); #ifdef DUMP_CRC_OPS log_add(log_Debug, "END crc_processSTAMP()."); #endif } void crc_processINTERSECT_CONTROL(crc_State *state, const INTERSECT_CONTROL *val) { #ifdef DUMP_CRC_OPS log_add(log_Debug, "START crc_processINTERSECT_CONTROL()."); #endif crc_processTIME_VALUE(state, val->last_time_val); crc_processPOINT(state, &val->EndPoint); #ifdef DUMP_CRC_OPS log_add(log_Debug, "END crc_processINTERSECT_CONTROL()."); #endif } #endif void crc_processSTATE(crc_State *state, const STATE *val) { crc_processPOINT(state, &val->location); } void crc_processELEMENT(crc_State *state, const ELEMENT *val) { #ifdef DUMP_CRC_OPS log_add(log_Debug, "START crc_processELEMENT()."); #endif crc_processELEMENT_FLAGS(state, val->state_flags); crc_processCOUNT(state, val->life_span); crc_processCOUNT(state, val->crew_level); crc_processBYTE(state, val->mass_points); // HACK: when a ship is being destroyed, turn_wait is abused to store // the side this ship is on. This must be excluded from the checksum // as this does not have to be the same for both sides. { extern void new_ship(PELEMENT ElementPtr); BYTE turn_wait = val->turn_wait; if (val->preprocess_func == new_ship) turn_wait = 0; crc_processBYTE(state, turn_wait); } crc_processBYTE(state, val->thrust_wait); crc_processVELOCITY_DESC(state, &val->velocity); crc_processSTATE(state, &val->current); crc_processSTATE(state, &val->next); #ifdef DUMP_CRC_OPS log_add(log_Debug, "END crc_processELEMENT()."); #endif } void crc_processDispQueue(crc_State *state) { HELEMENT element; HELEMENT nextElement; #ifdef DUMP_CRC_OPS size_t i = 0; log_add(log_Debug, "START crc_processDispQueue()."); #endif for (element = GetHeadElement(); element != 0; element = nextElement) { ELEMENTPTR elementPtr; #ifdef DUMP_CRC_OPS log_add(log_Debug, "===== disp_q[%d]:", i); #endif LockElement(element, &elementPtr); crc_processELEMENT(state, element); nextElement = GetSuccElement(elementPtr); UnlockElement(element); #ifdef DUMP_CRC_OPS i++; #endif } #ifdef DUMP_CRC_OPS log_add(log_Debug, "END crc_processDispQueue()."); #endif } void crc_processRNG(crc_State *state) { DWORD seed; #ifdef DUMP_CRC_OPS log_add(log_Debug, "START crc_processRNG()."); #endif seed = TFB_SeedRandom(0); // This modifies the seed too. crc_processDWORD(state, seed); TFB_SeedRandom(seed); // Restore the old seed. #ifdef DUMP_CRC_OPS log_add(log_Debug, "END crc_processRNG()."); #endif } void crc_processState(crc_State *state) { #ifdef DUMP_CRC_OPS log_add(log_Debug, "--------------------\n" "START crc_processState() (frame %u).", battleFrameCount); #endif crc_processRNG(state); crc_processDispQueue(state); #ifdef DUMP_CRC_OPS log_add(log_Debug, "END crc_processState() (frame %u).", battleFrameCount); #endif } void initChecksumBuffers(void) { size_t player; for (player = 0; player < NETPLAY_NUM_PLAYERS; player++) { NetConnection *conn; ChecksumBuffer *cb; conn = netConnections[player]; if (conn == NULL) continue; cb = NetConnection_getChecksumBuffer(conn); ChecksumBuffer_init(cb, getBattleInputDelay(), NETPLAY_CHECKSUM_INTERVAL); } ChecksumBuffer_init(&localChecksumBuffer, getBattleInputDelay(), NETPLAY_CHECKSUM_INTERVAL); } void uninitChecksumBuffers(void) { size_t player; for (player = 0; player < NETPLAY_NUM_PLAYERS; player++) { NetConnection *conn; ChecksumBuffer *cb; conn = netConnections[player]; if (conn == NULL) continue; cb = NetConnection_getChecksumBuffer(conn); ChecksumBuffer_uninit(cb); } ChecksumBuffer_uninit(&localChecksumBuffer); } void addLocalChecksum(BattleFrameCounter frameNr, Checksum checksum) { assert(frameNr == battleFrameCount); ChecksumBuffer_addChecksum(&localChecksumBuffer, frameNr, checksum); } void addRemoteChecksum(NetConnection *conn, BattleFrameCounter frameNr, Checksum checksum) { ChecksumBuffer *cb; assert(frameNr <= battleFrameCount + getBattleInputDelay() + 1); assert(frameNr + getBattleInputDelay() >= battleFrameCount); cb = NetConnection_getChecksumBuffer(conn); ChecksumBuffer_addChecksum(cb, frameNr, checksum); } bool verifyChecksums(BattleFrameCounter frameNr) { Checksum localChecksum; size_t player; if (!ChecksumBuffer_getChecksum(&localChecksumBuffer, frameNr, &localChecksum)) { // Right now, we require that a checksum is present. // If/when we move to UDP, and packets may get lost, we may prefer // not to do any checks in this case. return false; } for (player = 0; player < NETPLAY_NUM_PLAYERS; player++) { NetConnection *conn; ChecksumBuffer *cb; Checksum remoteChecksum; conn = netConnections[player]; if (conn == NULL) continue; cb = NetConnection_getChecksumBuffer(conn); if (!ChecksumBuffer_getChecksum(cb, frameNr, &remoteChecksum)) return false; if (localChecksum != remoteChecksum) { log_add(log_Error, "Network connections have gone out of " "sync.\n"); return false; } } return true; } #endif /* NETPLAY_CHECKSUM */ #endif /* NETPLAY */ uqm-0.6.2/sc2/src/sc2code/netplay/netconnection.c0000600000175000017500000001762510543202056020305 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define NETCONNECTION_INTERNAL #include "netplay.h" #include "netconnection.h" #include "netrcv.h" #if defined(DEBUG) || defined(NETPLAY_DEBUG) # include "libs/log.h" #endif #include #include static void closeCallback(NetDescriptor *nd); static void NetConnection_doClose(NetConnection *conn); #include "nc_connect.ci" // Used as initial value for Agreement structures, by structure assignment. const Agreement Agreement_nothingAgreed; // The NetConnection keeps a pointer to the passed NetplayPeerOptions; // do not free it as long as the NetConnection exists. NetConnection * NetConnection_open(int player, const NetplayPeerOptions *options, NetConnection_ConnectCallback connectCallback, NetConnection_CloseCallback closeCallback, NetConnection_ErrorCallback errorCallback, NetConnection_DeleteCallback deleteCallback, void *extra) { NetConnection *conn; conn = malloc(sizeof (NetConnection)); conn->nd = NULL; conn->player = player; conn->state = NetState_unconnected; conn->options = options; conn->extra = extra; PacketQueue_init(&conn->queue); conn->connectCallback = connectCallback; conn->closeCallback = closeCallback; conn->errorCallback = errorCallback; conn->deleteCallback = deleteCallback; conn->readyCallback = NULL; conn->readyCallbackArg = NULL; conn->resetCallback = NULL; conn->resetCallbackArg = NULL; conn->readBuf = malloc(NETPLAY_READBUFSIZE); conn->readEnd = conn->readBuf; conn->stateData = NULL; conn->stateFlags.connected = false; conn->stateFlags.disconnected = false; conn->stateFlags.myTurn = false; conn->stateFlags.endingTurn = false; conn->stateFlags.pendingTurnChange = false; conn->stateFlags.discriminant = false; conn->stateFlags.handshake.localOk = false; conn->stateFlags.handshake.remoteOk = false; conn->stateFlags.handshake.canceling = false; conn->stateFlags.ready.localReady = false; conn->stateFlags.ready.remoteReady = false; conn->stateFlags.reset.localReset = false; conn->stateFlags.reset.remoteReset = false; conn->stateFlags.agreement = Agreement_nothingAgreed; conn->stateFlags.inputDelay = 0; #ifdef NETPLAY_CHECKSUM conn->stateFlags.checksumInterval = NETPLAY_CHECKSUM_INTERVAL; #endif #ifdef NETPLAY_STATISTICS { size_t i; conn->statistics.packetsReceived = 0; conn->statistics.packetsSent = 0; for (i = 0; i < PACKET_NUM; i++) { conn->statistics.packetTypeReceived[i] = 0; conn->statistics.packetTypeSent[i] = 0; } } #endif NetConnection_go(conn); return conn; } static void NetConnection_doDeleteCallback(NetConnection *conn) { if (conn->deleteCallback != NULL) { //NetConnection_incRef(conn); conn->deleteCallback(conn); //NetConnection_decRef(conn); } } static void NetConnection_delete(NetConnection *conn) { NetConnection_doDeleteCallback(conn); if (conn->stateData != NULL) { NetConnectionStateData_release(conn->stateData); conn->stateData = NULL; } free(conn->readBuf); PacketQueue_uninit(&conn->queue); free(conn); } static void Netplay_doCloseCallback(NetConnection *conn) { if (conn->closeCallback != NULL) { //NetConnection_incRef(conn); conn->closeCallback(conn); //NetConnection_decRef(conn); } } // Auxiliary function for closing, used by both closeCallback() and // NetConnection_close() static void NetConnection_doClose(NetConnection *conn) { conn->stateFlags.connected = false; conn->stateFlags.disconnected = true; // First the callback, so that it can still use the information // of what is the current state, and the stateData: Netplay_doCloseCallback(conn); NetConnection_setState(conn, NetState_unconnected); } // Called when the NetDescriptor is shut down. static void closeCallback(NetDescriptor *nd) { NetConnection *conn = (NetConnection *) NetDescriptor_getExtra(nd); if (conn == NULL) return; conn->nd = NULL; NetConnection_doClose(conn); } // Close and release a NetConnection. void NetConnection_close(NetConnection *conn) { if (conn->nd != NULL) { NetDescriptor_setCloseCallback(conn->nd, NULL); // We're not interested in the close callback of the // NetDescriptor anymore. NetDescriptor_close(conn->nd); // This would queue the close callback. conn->nd = NULL; } if (!conn->stateFlags.disconnected) NetConnection_doClose(conn); NetConnection_delete(conn); } void NetConnection_doErrorCallback(NetConnection *nd, int err) { NetConnectionError error; if (nd->errorCallback != NULL) { error.state = nd->state; error.err = err; } (*nd->errorCallback)(nd, &error); } void NetConnection_setStateData(NetConnection *conn, NetConnectionStateData *stateData) { conn->stateData = stateData; } NetConnectionStateData * NetConnection_getStateData(const NetConnection *conn) { return conn->stateData; } void NetConnection_setExtra(NetConnection *conn, void *extra) { conn->extra = extra; } void * NetConnection_getExtra(const NetConnection *conn) { return conn->extra; } void NetConnection_setReadyCallback(NetConnection *conn, NetConnection_ReadyCallback callback, void *arg) { conn->readyCallback = callback; conn->readyCallbackArg = arg; } NetConnection_ReadyCallback NetConnection_getReadyCallback(const NetConnection *conn) { return conn->readyCallback; } void * NetConnection_getReadyCallbackArg(const NetConnection *conn) { return conn->readyCallbackArg; } void NetConnection_setResetCallback(NetConnection *conn, NetConnection_ResetCallback callback, void *arg) { conn->resetCallback = callback; conn->resetCallbackArg = arg; } NetConnection_ResetCallback NetConnection_getResetCallback(const NetConnection *conn) { return conn->resetCallback; } void * NetConnection_getResetCallbackArg(const NetConnection *conn) { return conn->resetCallbackArg; } void NetConnection_setState(NetConnection *conn, NetState state) { #ifdef NETPLAY_DEBUG log_add(log_Debug, "NETPLAY: [%d] +/- Connection state changed to: " "%s.\n", conn->player, netStateData[state].name); #endif #ifdef DEBUG if (state == conn->state) { log_add(log_Warning, "NETPLAY: [%d] Connection state set to %s " "while already in that state.\n", conn->player, netStateData[state].name); } #endif conn->state = state; } NetState NetConnection_getState(const NetConnection *conn) { return conn->state; } bool NetConnection_getDiscriminant(const NetConnection *conn) { return conn->stateFlags.discriminant; } const NetplayPeerOptions * NetConnection_getPeerOptions(const NetConnection *conn) { return conn->options; } bool NetConnection_isConnected(const NetConnection *conn) { return conn->stateFlags.connected; } bool NetConnection_isMyTurn(const NetConnection *conn) { return conn->stateFlags.myTurn; } int NetConnection_getPlayerNr(const NetConnection *conn) { return conn->player; } size_t NetConnection_getInputDelay(const NetConnection *conn) { return conn->stateFlags.inputDelay; } #ifdef NETPLAY_CHECKSUM ChecksumBuffer * NetConnection_getChecksumBuffer(NetConnection *conn) { return &conn->checksumBuffer; } size_t NetConnection_getChecksumInterval(const NetConnection *conn) { return conn->stateFlags.checksumInterval; } #endif /* NETPLAY_CHECKSUM */ #ifdef NETPLAY_STATISTICS NetStatistics * NetConnection_getStatistics(NetConnection *conn) { return &conn->statistics; } #endif uqm-0.6.2/sc2/src/sc2code/netplay/netmisc.c0000600000175000017500000001123110543202057017065 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "netplay.h" #include "netmisc.h" #include "netmelee.h" #include "packetsenders.h" #include "proto/ready.h" #include "melee.h" // For feedback functions. #include static BattleStateData *BattleStateData_alloc(void); static void BattleStateData_free(BattleStateData *battleStateData); static inline BattleStateData *BattleStateData_new( struct melee_state *meleeState, struct battlestate_struct *battleState, struct getmelee_struct *getMeleeState); static void BattleStateData_delete(BattleStateData *battleStateData); static BattleStateData * BattleStateData_alloc(void) { return (BattleStateData *) malloc(sizeof (BattleStateData)); } static void BattleStateData_free(BattleStateData *battleStateData) { free(battleStateData); } static inline BattleStateData * BattleStateData_new(struct melee_state *meleeState, struct battlestate_struct *battleState, struct getmelee_struct *getMeleeState) { BattleStateData *battleStateData = BattleStateData_alloc(); battleStateData->releaseFunction = (NetConnectionStateData_ReleaseFunction) BattleStateData_delete; battleStateData->meleeState = meleeState; battleStateData->battleState = battleState; battleStateData->getMeleeState = getMeleeState; return battleStateData; } static void BattleStateData_delete(BattleStateData *battleStateData) { BattleStateData_free(battleStateData); } //////////////////////////////////////////////////////////////////////////// static void NetMelee_enterState_inSetup(NetConnection *conn, void *arg); // Called when a connection has been established. void NetMelee_connectCallback(NetConnection *conn) { BattleStateData *battleStateData; struct melee_state *meleeState; meleeState = (struct melee_state *) NetConnection_getExtra(conn); battleStateData = BattleStateData_new(meleeState, NULL, NULL); NetConnection_setStateData(conn, (void *) battleStateData); NetConnection_setExtra(conn, NULL); sendInit(conn); Netplay_localReady (conn, NetMelee_enterState_inSetup, NULL, false); } // Called when a connection is closed. void NetMelee_closeCallback(NetConnection *conn) { closeFeedback(conn); } // Called when a network error occurs during connect. void NetMelee_errorCallback(NetConnection *conn, const NetConnectionError *error) { errorFeedback(conn); (void) error; } // Callback function for when both sides have finished initialisation after // initial connect. static void NetMelee_enterState_inSetup(NetConnection *conn, void *arg) { BattleStateData *battleStateData; struct melee_state *meleeState; int player; NetConnection_setState(conn, NetState_inSetup); battleStateData = (BattleStateData *) NetConnection_getStateData(conn); meleeState = battleStateData->meleeState; player = NetConnection_getPlayerNr(conn); connectedFeedback(conn); entireFleetChanged(meleeState, player); teamStringChanged(meleeState, player); flushPacketQueues(); (void) arg; } // Callback function for when both sides have confirmed that the battle // has ended. void NetMelee_reenterState_inSetup(NetConnection *conn) { BattleStateData *battleStateData; struct melee_state *meleeState; NetConnection_setState(conn, NetState_inSetup); battleStateData = (BattleStateData *) NetConnection_getStateData(conn); meleeState = battleStateData->meleeState; // The player who entered the menu first should send his changes over // to the other side when the other player enters setup too. // As myTurn is set when a change is made, and will never be unset // until the other side makes a change, it can be used to determine // which side was first. In the case there were no changes made, myTurn // may be the second player, but in this case it doesn't matter // who sends what to whom. if (NetConnection_isMyTurn(conn)) { size_t side; for (side = 0; side < NUM_SIDES; side++) { entireFleetChanged(meleeState, side); teamStringChanged(meleeState, side); } flushPacketQueues(); } } uqm-0.6.2/sc2/src/sc2code/netplay/packet.h0000600000175000017500000001603710543202056016707 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _PACKET_H #define _PACKET_H typedef struct Packet Packet; typedef enum PacketType { PACKET_INIT, PACKET_PING, PACKET_ACK, PACKET_ENDTURN, PACKET_READY, PACKET_FLEET, PACKET_TEAMNAME, PACKET_HANDSHAKE0, PACKET_HANDSHAKE1, PACKET_HANDSHAKECANCEL, PACKET_HANDSHAKECANCELACK, PACKET_SEEDRANDOM, PACKET_INPUTDELAY, PACKET_SELECTSHIP, PACKET_BATTLEINPUT, PACKET_FRAMECOUNT, PACKET_CHECKSUM, PACKET_ABORT, PACKET_RESET, PACKET_NUM, /* Number of packet types */ } PacketType; // Sent before aborting the connection. typedef enum NetplayAbortReason { AbortReason_unspecified, AbortReason_versionMismatch, AbortReason_protocolError, // Network is in an inconsistent state. } NetplayAbortReason; // Sent before resetting the connection. A game in progress is terminated. typedef enum NetplayResetReason { ResetReason_unspecified, ResetReason_syncLoss, ResetReason_manualReset, } NetplayResetReason; #ifndef PACKET_H_STANDALONE #include "netconnection.h" #include "types.h" #include "libs/network/bytesex.h" /* NB: These handlers are expected not to modify the state if an * error occurs. * When a handler is called, it has already been validated that the * a complete packet has arrived. */ typedef int (*PacketHandler)(NetConnection *conn, const void *packet); typedef struct { size_t len; /* Minimal length of a packet of this type */ PacketHandler handler; const char *name; bool inTurn; /* Can only be sent if it's this party's turn. */ } PacketTypeData; extern PacketTypeData packetTypeData[]; #endif // When adding new packets, be sure to have all the fields properly aligned, // and that the size of a packet is a multiple of 4 bytes in length. // Fields should be no longer than 4 bytes in themselves, as larger // fields may require a larger alignment. typedef struct { uint16 len; uint16 type; /* Actually of type PacketType */ } PacketHeader; // "Base class" for all packets. struct Packet { PacketHeader header; }; static inline size_t packetLength(const Packet *packet) { return (size_t) ntoh16(packet->header.len); } static inline PacketType packetType(const Packet *packet) { return (PacketType) ntoh16(packet->header.type); } static inline bool validPacketType(PacketType type) { return type < PACKET_NUM; } typedef struct { PacketHeader header; struct { uint8 major; uint8 minor; } protoVersion; /* Protocol version */ uint16 padding0; /* Set to 0 */ struct { uint8 major; uint8 minor; uint8 patch; } uqmVersion; /* Protocol version */ uint8 padding1; /* Set to 0 */ } Packet_Init; typedef struct { PacketHeader header; uint32 id; } Packet_Ping; // Acknowldement of a Ping. typedef struct { PacketHeader header; uint32 id; } Packet_Ack; // Used to ask or confirm a turn change. typedef struct { PacketHeader header; // No contents. } Packet_EndTurn; // Used to signal that a party is ready to continue. typedef struct { PacketHeader header; // No contents. } Packet_Ready; typedef struct { PacketHeader header; uint32 seed; } Packet_SeedRandom; typedef struct { PacketHeader header; uint32 delay; } Packet_InputDelay; // This enum is used to indicate that a packet containing it relates to // either the local or the remote player, from the perspective of the // sender of the message; typedef enum { NetplaySide_local, NetplaySide_remote } NetplaySide; typedef struct { uint8 index; /* Position in the fleet */ uint8 ship; /* Ship type index */ } FleetEntry; // Structure describing an update to a player's fleet. // TODO: use strings as ship identifiers, instead of numbers, // so that adding of new ships doesn't break this. typedef struct { PacketHeader header; uint8 side; uint8 padding; uint16 numShips; FleetEntry ships[]; // Be sure to add padding to this structure to make it a multiple of // 4 bytes in length. } Packet_Fleet; typedef struct { PacketHeader header; uint8 side; uint8 padding; uint8 name[]; // '\0' terminated. // Be sure to add padding to this structure to make it a multiple of // 4 bytes in length. } Packet_TeamName; typedef struct { PacketHeader header; // No contents. } Packet_Handshake0; typedef struct { PacketHeader header; // No contents. } Packet_Handshake1; typedef struct { PacketHeader header; // No contents. } Packet_HandshakeCancel; typedef struct { PacketHeader header; // No contents. } Packet_HandshakeCancelAck; typedef struct { PacketHeader header; uint16 ship; // The value '(uint16) ~0' indicates random selection. uint16 padding; } Packet_SelectShip; typedef struct { PacketHeader header; uint8 state; /* Actually BATTLE_INPUT_STATE */ uint8 padding0; uint16 padding1; } Packet_BattleInput; typedef struct { PacketHeader header; uint32 frameCount; /* Actually BattleFrameCounter */ } Packet_FrameCount; typedef struct { PacketHeader header; uint32 frameNr; /* Actually BattleFrameCounter */ uint32 checksum; /* Actually Checksum */ } Packet_Checksum; typedef struct { PacketHeader header; uint16 reason; /* Actually NetplayAbortReason */ uint16 padding0; } Packet_Abort; typedef struct { PacketHeader header; uint16 reason; /* Actually NetplayResetReason */ uint16 padding0; } Packet_Reset; #ifndef PACKET_H_STANDALONE void Packet_delete(Packet *packet); Packet_Init *Packet_Init_create(void); Packet_Ping *Packet_Ping_create(uint32 id); Packet_Ack *Packet_Ack_create(uint32 id); Packet_EndTurn *Packet_EndTurn_create(void); Packet_Ready *Packet_Ready_create(void); Packet_Handshake0 *Packet_Handshake0_create(void); Packet_Handshake1 *Packet_Handshake1_create(void); Packet_HandshakeCancel *Packet_HandshakeCancel_create(void); Packet_HandshakeCancelAck *Packet_HandshakeCancelAck_create(void); Packet_SeedRandom *Packet_SeedRandom_create(uint32 seed); Packet_InputDelay *Packet_InputDelay_create(uint32 delay); Packet_Fleet *Packet_Fleet_create(NetplaySide side, size_t numShips); Packet_TeamName *Packet_TeamName_create(NetplaySide side, const char *name, size_t size); Packet_SelectShip *Packet_SelectShip_create(uint16 ship); Packet_BattleInput *Packet_BattleInput_create(uint8 state); Packet_FrameCount *Packet_FrameCount_create(uint32 frameCount); Packet_Checksum *Packet_Checksum_create(uint32 frameNr, uint32 checksum); Packet_Abort *Packet_Abort_create(uint16 reason); Packet_Reset *Packet_Reset_create(uint16 reason); #endif #endif /* _PACKET_H */ uqm-0.6.2/sc2/src/sc2code/netplay/nc_connect.ci0000644000175000017500000002211110545012100017702 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // This file is part of netconnection.c, from where it is #included. static inline ConnectStateData *ConnectStateData_alloc(void); static inline ConnectStateData *ConnectStateData_new(void); static inline void ConnectStateData_free(ConnectStateData *connectStateData); static void ConnectStateData_delete(ConnectStateData *connectStateData); static int NetConnection_go(NetConnection *conn); static ListenState *NetConnection_serverGo(NetConnection *conn); static ConnectState *NetConnection_clientGo(NetConnection *conn); static void NetConnection_connected(NetConnection *conn); static void NetConnection_connectedServerCallback(ListenState *listenState, NetDescriptor *listenNd, NetDescriptor *newNd, const struct sockaddr *addr, SOCKLEN_T addrLen); static void NetConnection_connectedClientCallback(ConnectState *connectState, NetDescriptor *newNd, const struct sockaddr *addr, SOCKLEN_T addrLen); static void NetConnection_connectedServerErrorCallback( ListenState *listenState, const ListenError *listenError); static void NetConnection_connectedClientErrorCallback( ConnectState *connectState, const ConnectError *connectError); //////////////////////////////////////////////////////////////////////////// static inline ConnectStateData * ConnectStateData_alloc(void) { return (ConnectStateData *) malloc(sizeof (ConnectStateData)); } static inline ConnectStateData * ConnectStateData_new(void) { ConnectStateData *connectStateData = ConnectStateData_alloc(); connectStateData->releaseFunction = (NetConnectionStateData_ReleaseFunction) ConnectStateData_delete; return connectStateData; } static inline void ConnectStateData_free(ConnectStateData *connectStateData) { free(connectStateData); } static void ConnectStateData_delete(ConnectStateData *connectStateData) { if (connectStateData->isServer) { ListenState *listenState = connectStateData->state.listenState; ListenState_close(listenState); } else { ConnectState *connectState = connectStateData->state.connectState; ConnectState_close(connectState); } ConnectStateData_free(connectStateData); } //////////////////////////////////////////////////////////////////////////// static int NetConnection_go(NetConnection *conn) { ConnectStateData *connectStateData; if (NetConnection_isConnected(conn)) return 0; if (conn->options->isServer) { ListenState *listenState; listenState = NetConnection_serverGo(conn); if (listenState == NULL) { // errno is set return -1; } connectStateData = ConnectStateData_new(); connectStateData->state.listenState = listenState; } else { ConnectState *connectState; connectState = NetConnection_clientGo(conn); if (connectState == NULL) { // errno is set return -1; } connectStateData = ConnectStateData_new(); connectStateData->state.connectState = connectState; } connectStateData->isServer = conn->options->isServer; NetConnection_setStateData(conn, (void *) connectStateData); return 0; } static ListenState * NetConnection_serverGo(NetConnection *conn) { ListenFlags listenFlags; ListenState *result; assert(conn->state == NetState_unconnected); assert(conn->options->isServer); NetConnection_setState(conn, NetState_connecting); memset (&listenFlags, 0, sizeof listenFlags); listenFlags.familyDemand = #if NETPLAY == NETPLAY_IPV4 PF_inet; #else PF_unspec; #endif listenFlags.familyPrefer = PF_unspec; listenFlags.backlog = NETPLAY_LISTEN_BACKLOG; result = listenPort(conn->options->port, IPProto_tcp, &listenFlags, NetConnection_connectedServerCallback, NetConnection_connectedServerErrorCallback, (void *) conn); return result; } static ConnectState * NetConnection_clientGo(NetConnection *conn) { ConnectFlags connectFlags; ConnectState *result; assert(conn->state == NetState_unconnected); assert(!conn->options->isServer); NetConnection_setState(conn, NetState_connecting); memset (&connectFlags, 0, sizeof connectFlags); connectFlags.familyDemand = #if NETPLAY == NETPLAY_IPV4 PF_inet; #else PF_unspec; #endif connectFlags.familyPrefer = PF_unspec; connectFlags.timeout = NETPLAY_CONNECTTIMEOUT; connectFlags.retryDelayMs = NETPLAY_RETRYDELAY; result = connectHostByName(conn->options->host, conn->options->port, IPProto_tcp, &connectFlags, NetConnection_connectedClientCallback, NetConnection_connectedClientErrorCallback, (void *) conn); return result; } // Called when an incoming connection has been established. // The caller gives up ownership of newNd static void NetConnection_connectedServerCallback(ListenState *listenState, NetDescriptor *listenNd, NetDescriptor *newNd, const struct sockaddr *addr, SOCKLEN_T addrLen) { NetConnection *conn = (NetConnection *) ListenState_getExtra(listenState); assert(conn->nd == NULL); conn->nd = newNd; // No incRef(); the caller gives up ownership. NetDescriptor_setExtra(conn->nd, (void *) conn); (void) Socket_setInteractive(NetDescriptor_getSocket(conn->nd)); // Ignore errors; it's not a big deal. In debug mode, a message // will already have been printed from the function itself. conn->stateFlags.myTurn = true; // The "server" may speak first. conn->stateFlags.discriminant = true; NetConnection_connected(conn); (void) listenNd; (void) addr; (void) addrLen; } // Called when an outgoing connection has been established. // The caller gives up ownership of newNd static void NetConnection_connectedClientCallback(ConnectState *connectState, NetDescriptor *newNd, const struct sockaddr *addr, SOCKLEN_T addrLen) { NetConnection *conn = (NetConnection *) ConnectState_getExtra(connectState); assert(conn->nd == NULL); conn->nd = newNd; // No incRef(); the caller gives up ownership. NetDescriptor_setExtra(conn->nd, (void *) conn); (void) Socket_setInteractive(NetDescriptor_getSocket(conn->nd)); // Ignore errors; it's not a big deal. In debug mode, a message // will already have been printed from the function itself. conn->stateFlags.myTurn = false; // The "server" may speak first. conn->stateFlags.discriminant = false; NetConnection_connected(conn); (void) addr; (void) addrLen; } // Called when a connection has been established. static void NetConnection_connected(NetConnection *conn) { ConnectStateData *connectStateData; conn->stateFlags.connected = true; NetConnection_setState(conn, NetState_init); connectStateData = (ConnectStateData *) NetConnection_getStateData(conn); ConnectStateData_delete(connectStateData); NetConnection_setStateData(conn, NULL); NetDescriptor_setReadCallback(conn->nd, dataReadyCallback); NetDescriptor_setCloseCallback(conn->nd, closeCallback); (*conn->connectCallback)(conn); } static void NetConnection_connectedServerErrorCallback(ListenState *listenState, const ListenError *listenError) { NetConnection *conn = (NetConnection *) ListenState_getExtra(listenState); NetConnectionError error; conn->stateFlags.connected = false; conn->stateFlags.disconnected = true; ListenState_close(listenState); NetConnection_setState(conn, NetState_unconnected); { ConnectStateData *connectStateData; connectStateData = (ConnectStateData *) NetConnection_getStateData(conn); ConnectStateData_free(connectStateData); NetConnection_setStateData(conn, NULL); } if (conn->errorCallback != NULL) { error.state = NetState_connecting; error.err = listenError->err; error.extra.listenError = listenError; //NetConnection_incRef(conn); (*conn->errorCallback)(conn, &error); //NetConnection_decRef(conn); } NetConnection_close(conn); } static void NetConnection_connectedClientErrorCallback(ConnectState *connectState, const ConnectError *connectError) { NetConnection *conn = (NetConnection *) ConnectState_getExtra(connectState); NetConnectionError error; conn->stateFlags.connected = false; conn->stateFlags.disconnected = true; ConnectState_close(connectState); NetConnection_setState(conn, NetState_unconnected); { ConnectStateData *connectStateData; connectStateData = (ConnectStateData *) NetConnection_getStateData(conn); ConnectStateData_free(connectStateData); NetConnection_setStateData(conn, NULL); } if (conn->errorCallback != NULL) { error.state = NetState_connecting; error.err = connectError->err; error.extra.connectError = connectError; //NetConnection_incRef(conn); (*conn->errorCallback)(conn, &error); //NetConnection_decRef(conn); } NetConnection_close(conn); } uqm-0.6.2/sc2/src/sc2code/netplay/netinput.c0000600000175000017500000000762710543202057017307 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PORT_WANT_ERRNO #include "port.h" #include "netplay.h" #include "netinput.h" #include "../intel.h" // for NETWORK_CONTROL #include "../setup.h" // For PlayerControl #include "libs/log.h" #include #include static BattleInputBuffer battleInputBuffers[NUM_PLAYERS]; static size_t BattleInput_inputDelay; // Call before initBattleInputBuffers() void setBattleInputDelay(size_t delay) { BattleInput_inputDelay = delay; } size_t getBattleInputDelay(void) { return BattleInput_inputDelay; } static void BattleInputBuffer_init(BattleInputBuffer *bib, size_t bufSize) { bib->buf = malloc(bufSize * sizeof (BATTLE_INPUT_STATE)); bib->maxSize = bufSize; bib->first = 0; bib->size = 0; } static void BattleInputBuffer_uninit(BattleInputBuffer *bib) { if (bib->buf != NULL) { free(bib->buf); bib->buf = NULL; } bib->maxSize = 0; bib->first = 0; bib->size = 0; } void initBattleInputBuffers(void) { size_t player; int bufSize = BattleInput_inputDelay * 2 + 2; // The input of frame n will be processed in frame 'n + delay'. // // In the worst case, side 1 processes frames 'n' through 'n + delay - 1', // then blocks in frame 'n + delay'. // Then side 2 receives all this input, and progresses to 'delay' frames // after the last frame the received input originated from, and blocks // in the frame after it. // So it sent input for frames 'n' through 'n + delay + delay + 1'. // The input for these '2*delay + 2' frames are still // unhandled by side 1, so it needs buffer space for this. // // Initially the buffer is filled with inputDelay zeroes, // so that a party can process at least that much frames. for (player = 0; player < NUM_PLAYERS; player++) { BattleInputBuffer *bib = &battleInputBuffers[player]; BattleInputBuffer_init(bib, bufSize); { // Initially a party must be able to process at least inputDelay // frames, so we fill the buffer with inputDelay zeros. size_t i; for (i = 0; i < BattleInput_inputDelay; i++) BattleInputBuffer_push(bib, (BATTLE_INPUT_STATE) 0); } } } void uninitBattleInputBuffers(void) { size_t player; for (player = 0; player < NUM_PLAYERS; player++) { BattleInputBuffer *bib; if (!(PlayerControl[player] & NETWORK_CONTROL)) continue; bib = &battleInputBuffers[player]; BattleInputBuffer_uninit(bib); } } // On error, returns false and sets errno. bool BattleInputBuffer_push(BattleInputBuffer *bib, BATTLE_INPUT_STATE input) { size_t next; if (bib->size == bib->maxSize) { // No more space. log_add(log_Error, "NETPLAY: battleInputBuffer full.\n"); errno = ENOBUFS; return false; } next = (bib->first + bib->size) % bib->maxSize; bib->buf[next] = input; bib->size++; return true; } // On error, returns false and sets errno, and *input remains unchanged. bool BattleInputBuffer_pop(BattleInputBuffer *bib, BATTLE_INPUT_STATE *input) { if (bib->size == 0) { // Buffer is empty. errno = EAGAIN; return false; } *input = bib->buf[bib->first]; bib->first = (bib->first + 1) % bib->maxSize; bib->size--; return true; } BattleInputBuffer * getBattleInputBuffer(size_t player) { return &battleInputBuffers[player]; } uqm-0.6.2/sc2/src/sc2code/netplay/packetsenders.h0000600000175000017500000000422610543202056020270 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _PACKETSENDERS_H #define _PACKETSENDERS_H #include "types.h" #include "netconnection.h" #include "packet.h" #include "controls.h" // for BATTLE_INPUT_STATE void sendInit(NetConnection *conn); void sendPing(NetConnection *conn, uint32 id); void sendAck(NetConnection *conn, uint32 id); void sendEndTurn(NetConnection *conn); void sendReady(NetConnection *conn); int sendEndTurnDirect(NetConnection *conn); void sendHandshake0(NetConnection *conn); void sendHandshake1(NetConnection *conn); void sendHandshakeCancel(NetConnection *conn); void sendHandshakeCancelAck(NetConnection *conn); void sendTeamString(NetConnection *conn, NetplaySide side, const char *name, size_t len); void sendFleet(NetConnection *conn, NetplaySide side, const BYTE *ships, size_t numShips); void sendFleetShip(NetConnection *conn, NetplaySide player, size_t shipIndex, BYTE ship); void sendSeedRandom(NetConnection *conn, uint32 seed); void sendInputDelay(NetConnection *conn, uint32 delay); void sendSelectShip(NetConnection *conn, COUNT ship); void sendBattleInput(NetConnection *conn, BATTLE_INPUT_STATE input); void sendFrameCount(NetConnection *conn, uint32 frameCount); void sendChecksum(NetConnection *conn, uint32 frameNr, uint32 checksum); void sendAbort(NetConnection *conn, NetplayAbortReason reason); void sendReset(NetConnection *conn, NetplayResetReason reason); #endif /* _PACKETSENDERS_H */ uqm-0.6.2/sc2/src/sc2code/netplay/netinput.h0000600000175000017500000000322310543202057017300 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETINPUT_H #define _NETINPUT_H #include "../controls.h" // for BATTLE_INPUT_STATE #include "../init.h" // for NUM_PLAYERS typedef struct BattleInputBuffer { BATTLE_INPUT_STATE *buf; // Cyclic buffer. if 'size' > 0, then 'first' is an index to // the first used entry, 'size' is the number of used // entries in the buffer, and (first + size) % maxSize is the // index to just past the end of the buffer. size_t maxSize; size_t first; size_t size; } BattleInputBuffer; void setBattleInputDelay(size_t delay); size_t getBattleInputDelay(void); void initBattleInputBuffers(void); void uninitBattleInputBuffers(void); bool BattleInputBuffer_push(BattleInputBuffer *bib, BATTLE_INPUT_STATE input); bool BattleInputBuffer_pop(BattleInputBuffer *bib, BATTLE_INPUT_STATE *input); BattleInputBuffer *getBattleInputBuffer(size_t player); #endif /* _NETINPUT_H */ uqm-0.6.2/sc2/src/sc2code/netplay/crc.c0000600000175000017500000001317710543202056016204 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "crc.h" #ifdef DUMP_CRC_OPS # include "libs/log.h" #endif // CRC table for Polynomial 0x04c11db7 (0xedb88320 reversed) uint32 crcTable[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; void crc_init(crc_State *state) { state->crc = 0xffffffff; } void crc_processBytes(crc_State *state, uint8 *buf, size_t bufLen) { uint8 *end = buf + bufLen; uint32 newCrc = state->crc; while (buf < end) newCrc = (newCrc >> 8) ^ crcTable[(newCrc ^ *buf) & 0xff]; #ifdef DUMP_CRC_OPS log_add(log_Debug, "crc_processBytes(%08x, [%zu bytes]) --> %08x.", state->crc, bufLen, newCrc); #endif state->crc = newCrc; } void crc_processUint8(crc_State *state, uint8 val) { uint32 newCrc = state->crc; newCrc = (newCrc >> 8) ^ crcTable[(newCrc ^ val) & 0xff]; #ifdef DUMP_CRC_OPS log_add(log_Debug, "crc_processUint8(%08x, %02x) --> %08x.", state->crc, (int) val, newCrc); #endif state->crc = newCrc; } void crc_processUint16(crc_State *state, uint16 val) { uint32 newCrc = state->crc; newCrc = (newCrc >> 8) ^ crcTable[(newCrc ^ (val & 0xff)) & 0xff]; newCrc = (newCrc >> 8) ^ crcTable[(newCrc ^ (val >> 8) ) & 0xff]; #ifdef DUMP_CRC_OPS log_add(log_Debug, "crc_processUint16(%08x, %04x) --> %08x.", state->crc, (int) val, newCrc); #endif state->crc = newCrc; } void crc_processUint32(crc_State *state, uint32 val) { uint32 newCrc = state->crc; newCrc = (newCrc >> 8) ^ crcTable[(newCrc ^ (val & 0xff)) & 0xff]; newCrc = (newCrc >> 8) ^ crcTable[(newCrc ^ ((val >> 8) & 0xff)) & 0xff]; newCrc = (newCrc >> 8) ^ crcTable[(newCrc ^ ((val >> 16) & 0xff)) & 0xff]; newCrc = (newCrc >> 8) ^ crcTable[(newCrc ^ ((val >> 24) )) & 0xff]; #ifdef DUMP_CRC_OPS log_add(log_Debug, "crc_processUint32(%08x, %08x) --> %08x.", state->crc, (int) val, newCrc); #endif state->crc = newCrc; } uint32 crc_finish(const crc_State *state) { return ~state->crc; } uqm-0.6.2/sc2/src/sc2code/netplay/notify.c0000600000175000017500000000633510543202057016744 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // This files contains functions that notify the other side of local // changes. #define NETCONNECTION_INTERNAL #include "netplay.h" #include "notify.h" #include "packetsenders.h" // Convert a local player number to a side indication relative to this // party. static inline NetplaySide netSide(NetConnection *conn, int side) { if (side == conn->player) return NetplaySide_remote; return NetplaySide_local; } void Netplay_selectShip(NetConnection *conn, uint16 index) { assert(NetConnection_getState(conn) == NetState_selectShip); sendSelectShip(conn, index); } void Netplay_battleInput(NetConnection *conn, BATTLE_INPUT_STATE input) { assert(NetConnection_getState(conn) == NetState_inBattle || NetConnection_getState(conn) == NetState_endingBattle || NetConnection_getState(conn) == NetState_endingBattle2); sendBattleInput(conn, input); } void Netplay_teamStringChanged(NetConnection *conn, int player, const char *name, size_t len) { assert(NetConnection_getState(conn) == NetState_inSetup); assert(!conn->stateFlags.handshake.localOk); sendTeamString(conn, netSide(conn, player), name, len); } // On initialisation, or load. void Netplay_entireFleetChanged(NetConnection *conn, int player, const BYTE *fleet, size_t fleetSize) { assert(NetConnection_getState(conn) == NetState_inSetup); assert(!conn->stateFlags.handshake.localOk); sendFleet(conn, netSide(conn, player), fleet, fleetSize); } void Netplay_fleetShipChanged(NetConnection *conn, int player, size_t index, BYTE ship) { assert(NetConnection_getState(conn) == NetState_inSetup); assert(!conn->stateFlags.handshake.localOk); sendFleetShip(conn, netSide(conn, player), index, ship); } void Netplay_seedRandom(NetConnection *conn, uint32 seed) { assert(NetConnection_getState(conn) == NetState_preBattle); sendSeedRandom(conn, seed); conn->stateFlags.agreement.randomSeed = true; } void Netplay_sendInputDelay(NetConnection *conn, uint32 delay) { assert(NetConnection_getState(conn) == NetState_preBattle); sendInputDelay(conn, delay); } void Netplay_sendFrameCount(NetConnection *conn, BattleFrameCounter frameCount) { assert(NetConnection_getState(conn) == NetState_endingBattle); sendFrameCount(conn, frameCount); } #ifdef NETPLAY_CHECKSUM void Netplay_sendChecksum(NetConnection *conn, BattleFrameCounter frameNr, Checksum checksum) { assert(NetState_battleActive(NetConnection_getState(conn))); sendChecksum(conn, frameNr, checksum); } #endif /* NETPLAY_CHECKSUM */ uqm-0.6.2/sc2/src/sc2code/netplay/netplay.h0000644000175000017500000000426310545477401017134 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if !defined(_NETPLAY_H) && defined(NETPLAY) #define _NETPLAY_H // NETPLAY can either be unset (in which case we will never get here) // NETPLAY_FULL, or NETPLAY_IPV4 (disables IPv6) #define NETPLAY_IPV4 1 #define NETPLAY_FULL 2 #define NETPLAY_PROTOCOL_VERSION_MAJOR 0 #define NETPLAY_PROTOCOL_VERSION_MINOR 3 #define NETPLAY_MIN_UQM_VERSION_MAJOR 0 #define NETPLAY_MIN_UQM_VERSION_MINOR 5 #define NETPLAY_MIN_UQM_VERSION_PATCH 4 #define NETPLAY_DEBUG /* Extra debugging for netplay */ #define NETPLAY_STATISTICS /* Keep some statistics */ #define NETPLAY_CHECKSUM /* Send/process checksums to verify that both sides of a network * connection are still in sync. * If not enabled, incoming checksum packets will be ignored. * TODO: make compilation of crc.c and checksum.c conditional. */ #define NETPLAY_CHECKSUM_INTERVAL 1 /* If NETPLAY_CHECKSUM is defined, this define determines * every how many frames a checksum packet is sent. */ #define NETPLAY_READBUFSIZE 2048 #define NETPLAY_CONNECTTIMEOUT 2000 /* Time to wait for a connect() to succeed. In ms. */ //#define NETPLAY_LISTENTIMEOUT 30000 // /* Time to wait for a listen() to succeed. In ms. */ #define NETPLAY_RETRYDELAY 2000 /* Time to wait after all addresses of a host have been tried * before starting retrying them all. In ms. */ #define NETPLAY_LISTEN_BACKLOG 2 /* Second argument to listen(). */ #endif /* _NETPLAY_H */ uqm-0.6.2/sc2/src/sc2code/netplay/packetsenders.c0000600000175000017500000001157410543202056020267 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "netplay.h" #include "packetsenders.h" #include "packet.h" #include "packetq.h" #include "netsend.h" void sendInit(NetConnection *conn) { Packet_Init *packet; packet = Packet_Init_create(); queuePacket(conn, (Packet *) packet, false); } void sendPing(NetConnection *conn, uint32 id) { Packet_Ping *packet; packet = Packet_Ping_create(id); queuePacket(conn, (Packet *) packet, true); } void sendAck(NetConnection *conn, uint32 id) { Packet_Ack *packet; packet = Packet_Ack_create(id); queuePacket(conn, (Packet *) packet, true); } void sendEndTurn(NetConnection *conn) { Packet_EndTurn *packet; packet = Packet_EndTurn_create(); queuePacket(conn, (Packet *) packet, true); } void sendReady(NetConnection *conn) { Packet_Ready *packet; packet = Packet_Ready_create(); queuePacket(conn, (Packet *) packet, false); } // Bypass the packet queue. // Should only be called from the packet queue functions themselves. int sendEndTurnDirect(NetConnection *conn) { Packet_EndTurn *packet; packet = Packet_EndTurn_create(); return sendPacket(conn, (Packet *) packet); } void sendHandshake0(NetConnection *conn) { Packet_Handshake0 *packet; packet = Packet_Handshake0_create(); queuePacket(conn, (Packet *) packet, false); } void sendHandshake1(NetConnection *conn) { Packet_Handshake1 *packet; packet = Packet_Handshake1_create(); queuePacket(conn, (Packet *) packet, false); } void sendHandshakeCancel(NetConnection *conn) { Packet_HandshakeCancel *packet; packet = Packet_HandshakeCancel_create(); queuePacket(conn, (Packet *) packet, false); } void sendHandshakeCancelAck(NetConnection *conn) { Packet_HandshakeCancelAck *packet; packet = Packet_HandshakeCancelAck_create(); queuePacket(conn, (Packet *) packet, false); } void sendTeamString(NetConnection *conn, NetplaySide side, const char *name, size_t len) { Packet_TeamName *packet; packet = Packet_TeamName_create(side, name, len); queuePacket(conn, (Packet *) packet, false); } void sendFleet(NetConnection *conn, NetplaySide side, const BYTE *ships, size_t numShips) { size_t i; Packet_Fleet *packet; packet = Packet_Fleet_create(side, numShips); for (i = 0; i < numShips; i++) { packet->ships[i].index = (uint32) i; packet->ships[i].ship = ships[i]; } queuePacket(conn, (Packet *) packet, false); } void sendFleetShip(NetConnection *conn, NetplaySide side, size_t shipIndex, BYTE ship) { Packet_Fleet *packet; packet = Packet_Fleet_create(side, 1); packet->ships[0].index = shipIndex; packet->ships[0].ship = ship; queuePacket(conn, (Packet *) packet, false); } void sendSeedRandom(NetConnection *conn, uint32 seed) { Packet_SeedRandom *packet; packet = Packet_SeedRandom_create(seed); queuePacket(conn, (Packet *) packet, false); } void sendInputDelay(NetConnection *conn, uint32 delay) { Packet_InputDelay *packet; packet = Packet_InputDelay_create(delay); queuePacket(conn, (Packet *) packet, false); } void sendSelectShip(NetConnection *conn, COUNT ship) { Packet_SelectShip *packet; packet = Packet_SelectShip_create(ship); queuePacket(conn, (Packet *) packet, false); } void sendBattleInput(NetConnection *conn, BATTLE_INPUT_STATE input) { Packet_BattleInput *packet; packet = Packet_BattleInput_create((uint8) input); queuePacket(conn, (Packet *) packet, false); } void sendFrameCount(NetConnection *conn, BattleFrameCounter frameCount) { Packet_FrameCount *packet; packet = Packet_FrameCount_create((uint32) frameCount); queuePacket(conn, (Packet *) packet, false); } #ifdef NETPLAY_CHECKSUM void sendChecksum(NetConnection *conn, BattleFrameCounter frameNr, Checksum checksum) { Packet_Checksum *packet; packet = Packet_Checksum_create((uint32) frameNr, (uint32) checksum); queuePacket(conn, (Packet *) packet, false); } #endif void sendAbort(NetConnection *conn, NetplayAbortReason reason) { Packet_Abort *packet; packet = Packet_Abort_create((uint16) reason); queuePacket(conn, (Packet *) packet, false); } void sendReset(NetConnection *conn, NetplayResetReason reason) { Packet_Reset *packet; packet = Packet_Reset_create((uint16) reason); queuePacket(conn, (Packet *) packet, false); } uqm-0.6.2/sc2/src/sc2code/netplay/packetq.h0000600000175000017500000000440210543202057017062 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _PACKETQ_H #define _PACKETQ_H typedef struct PacketQueue PacketQueue; #include "packet.h" #include "types.h" #include typedef struct PacketQueueLink PacketQueueLink; struct PacketQueueLink { PacketQueueLink *next; Packet *packet; }; struct PacketQueue { size_t size; PacketQueueLink *first; PacketQueueLink **end; PacketQueueLink *firstUrgent; PacketQueueLink **endUrgent; // first points to the first entry in the queue // end points to the location where the next non-urgent message should // be inserted. // 'firstUrgent' and 'endUrgent' are analogous to 'first' and 'end'. // Urgent packets should only be used for packets that may not // be delayed while we wait for some remote confirmation. // As such, these messages themselves should not require a state change // which needs to be remotely confirmed. // For example, the endTurn message can be sent when we want to change // which party is allowed to transmit specific packets. That message // should not be delayed by messages which require that *we* are that // party, as without the endTurn message, it will never become our turn. // Also, ping and ack packets should give some indication of the round // trip time, which they can only do if they aren't delayed by other // packets. }; void PacketQueue_init(PacketQueue *queue); void PacketQueue_uninit(PacketQueue *queue); void queuePacket(NetConnection *conn, Packet *packet, bool urgent); int flushPacketQueue(NetConnection *conn); #endif uqm-0.6.2/sc2/src/sc2code/netplay/netrcv.c0000600000175000017500000001147710543202056016737 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PORT_WANT_ERRNO #define NETCONNECTION_INTERNAL #include "netplay.h" #include "port.h" #include "netconnection.h" #include "netrcv.h" #include "packet.h" #include "types.h" #include "libs/log.h" #include #include // Try to get a single packet from a stream of data. // Returns 0 if the packet was successfully processed, or // -1 on an error, in which case the state is unchanged. static ssize_t dataReceivedSingle(NetConnection *conn, const uint8 *data, size_t dataLen) { uint32 packetLen; PacketType type; int result; if (dataLen < sizeof (PacketHeader)) { // Incomplete packet. We'll have to wait for the rest. return 0; } packetLen = packetLength((const Packet *) data); type = packetType((const Packet *) data); if (!validPacketType(type)) { log_add(log_Warning, "Packet with invalid type %d received.\n", type); errno = EBADMSG; return -1; } if (packetLen < packetTypeData[type].len) { // Bad len field of packet. log_add(log_Warning, "Packet with bad length field received (type=" "%s, lenfield=%d.\n", packetTypeData[type].name, packetLen); errno = EBADMSG; return -1; } if (dataLen < packetLen) { // Incomplete packet. We'll have to wait for the rest. return 0; } #ifdef NETPLAY_STATISTICS NetConnection_getStatistics(conn)->packetsReceived++; NetConnection_getStatistics(conn)->packetTypeReceived[type]++; #endif #ifdef NETPLAY_DEBUG if (type != PACKET_BATTLEINPUT && type != PACKET_CHECKSUM) { // Reporting BattleInput and Checksum would get so spammy that it // would slow down the battle. log_add(log_Debug, "NETPLAY: [%d] <== Received packet of type %s.\n", NetConnection_getPlayerNr(conn), packetTypeData[type].name); } #endif result = packetTypeData[type].handler(conn, data); if (result == -1) { // An error occured. errno is set by the handler. return -1; } return packetLen; } // Try to get all the packets from a stream of data. // Returns the number of bytes processed. static ssize_t dataReceivedMulti(NetConnection *conn, const uint8 *data, size_t len) { size_t processed; processed = 0; while (len > 0) { ssize_t packetLen = dataReceivedSingle(conn, data, len); if (packetLen == -1) { // Bad packet. Errno is set. return -1; } if (packetLen == 0) { // No packet was processed. This means that no complete // packet arrived. break; } processed += packetLen; data += packetLen; len -= packetLen; } return processed; } void dataReadyCallback(NetDescriptor *nd) { NetConnection *conn = (NetConnection *) NetDescriptor_getExtra(nd); Socket *socket = NetDescriptor_getSocket(nd); for (;;) { ssize_t numRead; ssize_t numProcessed; numRead = Socket_recv(socket, conn->readEnd, NETPLAY_READBUFSIZE - (conn->readEnd - conn->readBuf), 0); if (numRead == 0) { // Other side closed the connection. NetDescriptor_close(nd); return; } if (numRead == -1) { switch (errno) { case EAGAIN: // No more data for now. return; case EINTR: // System call was interrupted. Retry. continue; default: { int savedErrno = errno; log_add(log_Error, "recv() failed: %s.\n", strerror(errno)); NetConnection_doErrorCallback(conn, savedErrno); NetDescriptor_close(nd); return; } } } conn->readEnd += numRead; numProcessed = dataReceivedMulti(conn, conn->readBuf, conn->readEnd - conn->readBuf); if (numProcessed == -1) { // An error occured during processing. // errno is set. NetConnection_doErrorCallback(conn, errno); NetDescriptor_close(nd); return; } if (numProcessed == 0) { // No packets could be processed. This means we need to receive // more data first. return; } // Some packets have been processed. // We more any rest to the front of the buffer, to make room // for more data. // A cyclic buffer would obviate the need for this move, // but it would complicate things a lot. memmove(conn->readBuf, conn->readBuf + numProcessed, (conn->readEnd - conn->readBuf) - numProcessed); conn->readEnd -= numProcessed; } } uqm-0.6.2/sc2/src/sc2code/netplay/netmelee.c0000600000175000017500000004624310543202056017233 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "netmelee.h" #include "libs/alarm.h" #include "libs/callback.h" #include "libs/log.h" #include "libs/net.h" #include "netplay/netinput.h" #include "netplay/netmisc.h" #include "netplay/netsend.h" #include "netplay/notify.h" #include "netplay/packetq.h" #include "netplay/proto/npconfirm.h" #include "netplay/proto/ready.h" #include "netplay/proto/reset.h" #include "build.h" // for StarShipPlayer() #include "controls.h" // for BATTLE_INPUT_STATE #include "init.h" // for NUM_PLAYERS #include "globdata.h" // for GLOBAL #include #include //////////////////////////////////////////////////////////////////////////// NetConnection *netConnections[NUM_PLAYERS]; size_t numNetConnections; void addNetConnection(NetConnection *conn, int playerNr) { netConnections[playerNr] = conn; numNetConnections++; } void removeNetConnection(int playerNr) { netConnections[playerNr] = NULL; numNetConnections--; } void closeAllConnections(void) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn != NULL) closePlayerNetworkConnection(player); } } void closeDisconnectedConnections(void) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn != NULL && !NetConnection_isConnected(conn)) closePlayerNetworkConnection(player); } } size_t getNumNetConnections(void) { return numNetConnections; } //////////////////////////////////////////////////////////////////////////// struct melee_state * NetMelee_getMeleeState(NetConnection *conn) { if (NetConnection_getState(conn) > NetState_connecting) { BattleStateData *battleStateData = (BattleStateData *) NetConnection_getStateData(conn); return battleStateData->meleeState; } else { return (struct melee_state *) NetConnection_getExtra(conn); } } struct battlestate_struct * NetMelee_getBattleState(NetConnection *conn) { if (NetConnection_getState(conn) > NetState_connecting) { BattleStateData *battleStateData = (BattleStateData *) NetConnection_getStateData(conn); return battleStateData->battleState; } else { return NULL; } } //////////////////////////////////////////////////////////////////////////// static inline void netInputAux(uint32 timeoutMs) { NetManager_process(&timeoutMs); // This may cause more packets to be queued, hence the // flushPacketQueues(). Alarm_process(); Callback_process(); flushPacketQueues(); // During the flush, a disconnect may be noticed, which triggers // another callback. It must be handled immediately, before // another flushPacketQueue() can occur, which would not know // that the socket is no longer valid. // TODO: modify the close handling so this order isn't // necessary. Callback_process(); } // Check the network connections for input. void netInput(void) { netInputAux(0); } void netInputBlocking(uint32 timeoutMs) { uint32 nextAlarmMs; nextAlarmMs = Alarm_timeBeforeNextMs(); if (nextAlarmMs < timeoutMs) timeoutMs = nextAlarmMs; netInputAux(timeoutMs); } //////////////////////////////////////////////////////////////////////////// // Send along all pending network packets. void flushPacketQueues(void) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn; int flushStatus; conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) continue; flushStatus = flushPacketQueue(conn); if (flushStatus == -1 && errno != EAGAIN) closePlayerNetworkConnection(player); } } void confirmConnections(void) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) continue; Netplay_confirm(conn); } } void cancelConfirmations(void) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) continue; Netplay_cancelConfirmation(conn); } } void connectionsLocalReady(NetConnection_ReadyCallback callback, void *arg) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) continue; Netplay_localReady(conn, callback, arg, true); } } bool allConnected(void) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) return false; } return true; } void sendBattleInputConnections(BATTLE_INPUT_STATE input) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) continue; Netplay_battleInput(conn, input); } } #ifdef NETPLAY_CHECKSUM void sendChecksumConnections(uint32 frameNr, uint32 checksum) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) continue; Netplay_sendChecksum(conn, frameNr, checksum); } } #endif /* NETPLAY_CHECKSUM */ void initBattleStateDataConnections(void) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { BattleStateData *battleStateData; NetConnection *conn = netConnections[player]; if (conn == NULL) continue; battleStateData = (BattleStateData *) NetConnection_getStateData(conn); battleStateData->endFrameCount = 0; } } void setBattleStateConnections(struct battlestate_struct *bs) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { BattleStateData *battleStateData; NetConnection *conn = netConnections[player]; if (conn == NULL) continue; battleStateData = (BattleStateData *) NetConnection_getStateData(conn); battleStateData->battleState = bs; } } BATTLE_INPUT_STATE networkBattleInput(COUNT player, STARSHIPPTR StarShipPtr) { BattleInputBuffer *bib = getBattleInputBuffer(player); BATTLE_INPUT_STATE result; for (;;) { bool ok; #if 0 // This is a useful debugging trick. By enabling this #if // block, this side will always lag the maximum number of frames // behind the other side. When the remote side stops on some event // (a breakpoint or so), this side will stop too, waiting for input // in the loop below, but it won't have processed the frame that // triggered the event yet. If you then jump over this 'if' // statement here, you can walk through the decisive frames // manually. Works best with no input delay. if (bib->size <= getBattleInputDelay() + 1) { ok = false; } else #endif ok = BattleInputBuffer_pop(bib, &result); // Get the input from the front of the // buffer. if (ok) break; { NetConnection *conn = netConnections[player]; // First try whether there is incoming data, without blocking. // If there isn't any, only then give a warning, and then // block after all. netInput(); if (!NetConnection_isConnected(conn)) { // Connection aborted. GLOBAL(CurrentActivity) |= CHECK_ABORT; return (BATTLE_INPUT_STATE) 0; } if (GLOBAL(CurrentActivity) & CHECK_ABORT) return (BATTLE_INPUT_STATE) 0; #if 0 log_add(log_Warning, "NETPLAY: [%d] stalling for " "network input. Increase the input delay if this " "happens a lot.\n", player); #endif #define MAX_BLOCK_TIME 500 netInputBlocking(MAX_BLOCK_TIME); if (!NetConnection_isConnected(conn)) { // Connection aborted. GLOBAL(CurrentActivity) |= CHECK_ABORT; return (BATTLE_INPUT_STATE) 0; } } } (void) StarShipPtr; return result; } static void deleteConnectionCallback(NetConnection *conn) { removeNetConnection(NetConnection_getPlayerNr(conn)); } NetConnection * openPlayerNetworkConnection(COUNT player, void *extra) { NetConnection *conn; assert(netConnections[player] == NULL); conn = NetConnection_open(player, &netplayOptions.peer[player], NetMelee_connectCallback, NetMelee_closeCallback, NetMelee_errorCallback, deleteConnectionCallback, extra); addNetConnection(conn, player); return conn; } void shutdownPlayerNetworkConnection(COUNT player) { NetConnection_close(netConnections[player]); } void closePlayerNetworkConnection(COUNT player) { assert(netConnections[player] != NULL); NetConnection_close(netConnections[player]); } // If the callback function returns 'false', the function will immediately // return with 'false'. Otherwise it will return 'true' after calling // the callback function for each connected player. bool forAllConnectedPlayers(ForAllCallback callback, void *arg) { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) continue; if (!(*callback)(conn, arg)) return false; } return true; } bool setupInputDelay(size_t localInputDelay) { COUNT player; bool haveNetworkPlayer = false; // We have at least one network controlled player. size_t inputDelay = 0; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) continue; haveNetworkPlayer = true; if (NetConnection_getInputDelay(conn) > inputDelay) inputDelay = NetConnection_getInputDelay(conn); } if (haveNetworkPlayer && inputDelay < localInputDelay) inputDelay = localInputDelay; setBattleInputDelay(inputDelay); return true; } static bool sendInputDelayConnection(NetConnection *conn, const size_t *delay) { Netplay_sendInputDelay(conn, *delay); return true; } bool sendInputDelayConnections(size_t delay) { return forAllConnectedPlayers( (ForAllCallback) sendInputDelayConnection, &delay); } static bool setStateConnection(NetConnection *conn, const NetState *state) { NetConnection_setState(conn, *state); return true; } bool setStateConnections(NetState state) { return forAllConnectedPlayers( (bool(*)(NetConnection *, void *)) setStateConnection, &state); } static bool sendAbortConnection(NetConnection *conn, const NetplayAbortReason *reason) { sendAbort(conn, *reason); return true; } bool sendAbortConnections(NetplayAbortReason reason) { return forAllConnectedPlayers( (bool(*)(NetConnection *, void *)) sendAbortConnection, &reason); } static bool resetConnection(NetConnection *conn, const NetplayResetReason *reason) { Netplay_localReset(conn, *reason); return true; } bool resetConnections(NetplayResetReason reason) { return forAllConnectedPlayers( (bool(*)(NetConnection *, void *)) resetConnection, &reason); } ///////////////////////////////////////////////////////////////////////////// typedef struct { NetConnection_ReadyCallback readyCallback; void *readyCallbackArg; bool notifyRemote; } LocalReadyConnectionArg; static bool localReadyConnection(NetConnection *conn, LocalReadyConnectionArg *arg) { Netplay_localReady(conn, arg->readyCallback, arg->readyCallbackArg, arg->notifyRemote); return true; } bool localReadyConnections(NetConnection_ReadyCallback readyCallback, void *readyArg, bool notifyRemote) { LocalReadyConnectionArg arg; arg.readyCallback = readyCallback; arg.readyCallbackArg = readyArg; arg.notifyRemote = notifyRemote; return forAllConnectedPlayers( (bool(*)(NetConnection *, void *)) localReadyConnection, &arg); } ///////////////////////////////////////////////////////////////////////////// #define NETWORK_POLL_DELAY (ONE_SECOND / 24) typedef struct NegotiateReadyState NegotiateReadyState; struct NegotiateReadyState { // Common fields of INPUT_STATE_DESC, from which this structure // "inherits". BOOLEAN(*InputFunc)(PVOID pInputState); COUNT MenuRepeatDelay; NetConnection *conn; NetState nextState; bool done; }; static BOOLEAN negotiateReadyInputFunc(NegotiateReadyState *state) { netInputBlocking(NETWORK_POLL_DELAY); // The timing out is necessary so that immediate key presses get // handled while we wait. If we could do without the timeout, // we wouldn't even need negotiateReadyInputFunc() and the // DoInput() call. // No need to call flushPacketQueues(); nothing needs to be sent // right now. if (!NetConnection_isConnected(state->conn)) return FALSE; return !state->done; } // Called when both sides are ready static void negotiateReadyBothReadyCallback(NetConnection *conn, void *arg) { NegotiateReadyState *state =(NegotiateReadyState *) arg; NetConnection_setState(conn, state->nextState); // This has to be done immediately, as more packets in the // receive queue may be handled by the netInput() call that // triggered this callback. // This is the reason for the nextState argument to // negotiateReady(); setting the state after the call to // negotiateReady() would be too late. state->done = true; } bool negotiateReady(NetConnection *conn, bool notifyRemote, NetState nextState) { NegotiateReadyState state; state.InputFunc = (BOOLEAN(*)(void *)) negotiateReadyInputFunc; state.MenuRepeatDelay = 0; state.conn = conn; state.nextState = nextState; state.done = false; Netplay_localReady(conn, negotiateReadyBothReadyCallback, (void *) &state, notifyRemote); flushPacketQueue(conn); if (!state.done) DoInput(&state, FALSE); return NetConnection_isConnected(conn); } // Wait for all connections to get ready. // XXX: Right now all connections are handled one by one. Handling them all // at once would be faster but would require more work, which is // not worth it as the time is minimal and this function is not // time critical. bool negotiateReadyConnections(bool notifyRemote, NetState nextState) { COUNT player; size_t numDisconnected = 0; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) { numDisconnected++; continue; } negotiateReady(conn, notifyRemote, nextState); } return numDisconnected == 0; } typedef struct WaitReadyState WaitReadyState; struct WaitReadyState { // Common fields of INPUT_STATE_DESC, from which this structure // "inherits". BOOLEAN(*InputFunc)(PVOID pInputState); COUNT MenuRepeatDelay; NetConnection *conn; NetConnection_ReadyCallback readyCallback; void *readyCallbackArg; bool done; }; static void waitReadyCallback(NetConnection *conn, void *arg) { WaitReadyState *state =(WaitReadyState *) arg; state->done = true; // Call the original callback. state->readyCallback(conn, state->readyCallbackArg); } static BOOLEAN waitReadyInputFunc(WaitReadyState *state) { netInputBlocking(NETWORK_POLL_DELAY); // The timing out is necessary so that immediate key presses get // handled while we wait. If we could do without the timeout, // we wouldn't even need negotiateReadyInputFunc() and the // DoInput() call. // No need to call flushPacketQueues(); nothing needs to be sent // right now. if (!NetConnection_isConnected(state->conn)) return FALSE; return !state->done; } bool waitReady(NetConnection *conn) { WaitReadyState state; state.InputFunc =(BOOLEAN(*)(void *)) waitReadyInputFunc; state.MenuRepeatDelay = 0; state.conn = conn; state.readyCallback = NetConnection_getReadyCallback(conn); state.readyCallbackArg = NetConnection_getReadyCallbackArg(conn); state.done = false; NetConnection_setReadyCallback(conn, waitReadyCallback, (void *) &state); DoInput(&state, FALSE); return NetConnection_isConnected(conn); } //////////////////////////////////////////////////////////////////////////// typedef struct WaitResetState WaitResetState; struct WaitResetState { // Common fields of INPUT_STATE_DESC, from which this structure // "inherits". BOOLEAN(*InputFunc)(PVOID pInputState); COUNT MenuRepeatDelay; NetConnection *conn; NetState nextState; bool done; }; static BOOLEAN waitResetInputFunc(WaitResetState *state) { netInputBlocking(NETWORK_POLL_DELAY); // The timing out is necessary so that immediate key presses get // handled while we wait. If we could do without the timeout, // we wouldn't even need waitResetInputFunc() and the // DoInput() call. // No need to call flushPacketQueues(); nothing needs to be sent // right now. if (!NetConnection_isConnected(state->conn)) return FALSE; return !state->done; } // Called when both sides are reset. static void waitResetBothResetCallback(NetConnection *conn, void *arg) { WaitResetState *state = (WaitResetState *) arg; if (state->nextState != (NetState) -1) { NetConnection_setState(conn, state->nextState); // This has to be done immediately, as more packets in the // receive queue may be handled by the netInput() call that // triggered this callback. // This is the reason for the nextState argument to // waitReset(); setting the state after the call to // waitReset() would be too late. } state->done = true; } bool waitReset(NetConnection *conn, NetState nextState) { WaitResetState state; state.InputFunc = (BOOLEAN(*)(void *)) waitResetInputFunc; state.MenuRepeatDelay = 0; state.conn = conn; state.nextState = nextState; state.done = false; Netplay_setResetCallback(conn, waitResetBothResetCallback, (void *) &state); if (state.done) goto out; if (!Netplay_isLocalReset(conn)) { Netplay_localReset(conn, ResetReason_manualReset); flushPacketQueue(conn); } if (!state.done) DoInput(&state, FALSE); out: return NetConnection_isConnected(conn); } // Wait until we have received a reset packet to all connections. If we // ourselves have not sent a reset packet, one is sent, with reason // 'manualReset'. // XXX: Right now all connections are handled one by one. Handling them all // at once would be faster but would require more work, which is // not worth it as the time is minimal and this function is not // time critical. // Use '(NetState) -1' for nextState to keep the current state. bool waitResetConnections(NetState nextState) { COUNT player; size_t numDisconnected = 0; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn = netConnections[player]; if (conn == NULL) continue; if (!NetConnection_isConnected(conn)) { numDisconnected++; continue; } waitReset(conn, nextState); } return numDisconnected == 0; } //////////////////////////////////////////////////////////////////////////// uqm-0.6.2/sc2/src/sc2code/netplay/netsend.c0000600000175000017500000000441110543202056017064 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PORT_WANT_ERRNO #define NETCONNECTION_INTERNAL #include "netplay.h" #include "port.h" #include "netconnection.h" #include "packet.h" #include "libs/log.h" #include "libs/net.h" #include #include #include int sendPacket(NetConnection *conn, Packet *packet) { ssize_t sendResult; size_t len; Socket *socket; assert(NetConnection_isConnected(conn)); #ifdef NETPLAY_DEBUG //if (packetType(packet) != PACKET_BATTLEINPUT && // packetType(packet) != PACKET_CHECKSUM) { // // Reporting BattleInput or Checksum would get so spammy that it // // would slow down the battle. // log_add(log_Debug, "NETPLAY: [%d] ==> Sending packet of type %s.\n", // conn->player, packetTypeData[packetType(packet)].name); //} #endif socket = NetDescriptor_getSocket(conn->nd); len = packetLength(packet); while (len > 0) { sendResult = Socket_send(socket, (void *) packet, len, 0); if (sendResult >= 0) { len -= sendResult; continue; } switch (errno) { case EINTR: // System call interrupted, retry; continue; case ECONNRESET: { // Connection reset by peer. // keep errno return -1; } default: { // Should not happen. int savedErrno = errno; log_add(log_Error, "send() failed: %s.\n", strerror(errno)); errno = savedErrno; return -1; } } } #ifdef NETPLAY_STATISTICS NetConnection_getStatistics(conn)->packetsSent++; NetConnection_getStatistics(conn)->packetTypeSent[packetType(packet)]++; #endif return 0; } uqm-0.6.2/sc2/src/sc2code/netplay/netmisc.h0000600000175000017500000000400010543202057017066 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETMISC_H #define _NETMISC_H typedef struct BattleStateData BattleStateData; #include "netconnection.h" #include "netstate.h" #include "types.h" #include "battle.h" // for BattleFrameCounter struct BattleStateData { NETCONNECTION_STATE_DATA_COMMON struct melee_state *meleeState; struct battlestate_struct *battleState; struct getmelee_struct *getMeleeState; BattleFrameCounter endFrameCount; }; void NetMelee_connectCallback(NetConnection *conn); void NetMelee_closeCallback(NetConnection *conn); void NetMelee_errorCallback(NetConnection *conn, const NetConnectionError *error); void NetMelee_reenterState_inSetup(NetConnection *conn); // Returns true iff the connection is in a state where the confirmation // handshake is meaningful. Right now this is only when we're in the // pre-game setup menu. static inline bool handshakeMeaningful(NetState state) { return state == NetState_inSetup; } static inline bool readyFlagsMeaningful(NetState state) { return state == NetState_init || state == NetState_preBattle || state == NetState_interBattle || state == NetState_inBattle || state == NetState_endingBattle || state == NetState_endingBattle2 || state == NetState_endMelee; } #endif /* _NETMISC_H */ uqm-0.6.2/sc2/src/sc2code/netplay/proto/0000755000175000017500000000000010552600274016437 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/netplay/proto/npconfirm.c0000600000175000017500000000446610543202056020574 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define NETCONNECTION_INTERNAL #include "../netplay.h" #include "npconfirm.h" #include "types.h" #include "../netmisc.h" #include "../packetsenders.h" #include #include int Netplay_confirm(NetConnection *conn) { assert(handshakeMeaningful(NetConnection_getState(conn))); if (conn->stateFlags.handshake.localOk) { // Already confirmed errno = EINVAL; return -1; } conn->stateFlags.handshake.localOk = true; if (conn->stateFlags.handshake.canceling) { // If a previous confirmation was cancelled, but the cancel // is not acknowledged yet, we don't have to send anything yet. // The handshake0 packet will be sent when the acknowledgement // arrives. } else if (conn->stateFlags.handshake.remoteOk) { // A Handshake0 is implied by the following Handshake1. sendHandshake1(conn); } else { sendHandshake0(conn); } return 0; } int Netplay_cancelConfirmation(NetConnection *conn) { assert(handshakeMeaningful(NetConnection_getState(conn))); if (!conn->stateFlags.handshake.localOk) { // Not confirmed, or already canceling. errno = EINVAL; return -1; } conn->stateFlags.handshake.localOk = false; if (conn->stateFlags.handshake.canceling) { // If previous cancellation is still waiting to be acknowledged, // the confirmation we are cancelling here, has not actually been // sent yet. By setting the localOk flag to false, it is // cancelled, without the need for any packets to be sent. } else { conn->stateFlags.handshake.canceling = true; sendHandshakeCancel(conn); } return 0; } uqm-0.6.2/sc2/src/sc2code/netplay/proto/ready.h0000600000175000017500000000220110543202056017673 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _READY_H #define _READY_H #include "../netconnection.h" bool Netplay_localReady(NetConnection *conn, NetConnection_ReadyCallback callback, void *arg, bool notifyRemote); bool Netplay_remoteReady(NetConnection *conn); bool Netplay_isLocalReady(const NetConnection *conn); bool Netplay_isRemoteReady(const NetConnection *conn); #endif /* _READY_H */ uqm-0.6.2/sc2/src/sc2code/netplay/proto/ready.c0000600000175000017500000000560510543202056017701 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define NETCONNECTION_INTERNAL #include "../netplay.h" #include "ready.h" #include "types.h" #include "../netmisc.h" #include "../packetsenders.h" #include static void Netplay_bothReady(NetConnection *conn) { NetConnection_ReadyCallback callback; void *readyArg; assert(conn->readyCallback != NULL); callback = conn->readyCallback; readyArg = conn->readyCallbackArg; NetConnection_setReadyCallback(conn, NULL, NULL); // Clear the readyCallback field before performing the callback, // so that it can be set again from inside the callback // function. callback(conn, readyArg); } // If notifyRemote is set, a 'Ready' message will be sent to the other side. // returns true iff both sides are ready. // Inside the callback function, ready flags may be set for a possible // next Ready communication. bool Netplay_localReady(NetConnection *conn, NetConnection_ReadyCallback callback, void *readyArg, bool notifyRemote) { assert(readyFlagsMeaningful(NetConnection_getState(conn))); assert(!conn->stateFlags.ready.localReady); assert(callback != NULL); NetConnection_setReadyCallback(conn, callback, readyArg); if (notifyRemote) sendReady(conn); if (!conn->stateFlags.ready.remoteReady) { conn->stateFlags.ready.localReady = true; return false; } // Reset ready flags: conn->stateFlags.ready.remoteReady = false; // Trigger the callback. Netplay_bothReady(conn); return true; } // returns true iff both sides are ready. bool Netplay_remoteReady(NetConnection *conn) { assert(readyFlagsMeaningful(NetConnection_getState(conn))); // This is supposed to be already verified by the calling // function. assert(!conn->stateFlags.ready.remoteReady); if (!conn->stateFlags.ready.localReady) { conn->stateFlags.ready.remoteReady = true; return false; } // Reset ready flags: conn->stateFlags.ready.localReady = false; // Trigger the callback. Netplay_bothReady(conn); return true; } bool Netplay_isLocalReady(const NetConnection *conn) { return conn->stateFlags.ready.localReady; } bool Netplay_isRemoteReady(const NetConnection *conn) { return conn->stateFlags.ready.remoteReady; } uqm-0.6.2/sc2/src/sc2code/netplay/proto/reset.h0000600000175000017500000000236510543202056017724 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RESET_H #define _RESET_H #include "../netconnection.h" #include "../packet.h" void Netplay_setResetCallback(NetConnection *conn, NetConnection_ResetCallback callback, void *resetArg); void Netplay_localReset(NetConnection *conn, NetplayResetReason reason); void Netplay_remoteReset(NetConnection *conn, NetplayResetReason reason); bool Netplay_isLocalReset(const NetConnection *conn); bool Netplay_isRemoteReset(const NetConnection *conn); #endif /* _RESET_H */ uqm-0.6.2/sc2/src/sc2code/netplay/proto/Makeinfo0000600000175000017500000000005210543202056020074 0ustar joeyjoeyuqm_CFILES="npconfirm.c ready.c reset.c" uqm-0.6.2/sc2/src/sc2code/netplay/proto/npconfirm.h0000600000175000017500000000176510543202056020600 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NPCONFIRM_H #define _NPCONFIRM_H #include "../netplay.h" #include "../netconnection.h" int Netplay_confirm(NetConnection *conn); int Netplay_cancelConfirmation(NetConnection *conn); #endif /* _NPCONFIRM_H */ uqm-0.6.2/sc2/src/sc2code/netplay/proto/reset.c0000600000175000017500000001246710543202056017723 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // See doc/devel/netplay/protocol #define NETCONNECTION_INTERNAL #include "../netplay.h" #include "reset.h" #include "types.h" #include "../packetsenders.h" #include "../../melee.h" // For resetFeedback. #include // Reset packets are sent to indicate that a game is to be reset. // i.e. the game is to return to the SuperMelee fleet setup menu. // The reset will occur when a reset packet has both been sent and // received. When a reset packet is received and the local side had not // sent a reset packet itself, the local side will confirm the reset. // When both sides initiate a reset simultaneously, the reset packets // of each side will act as a confirmation for the other side. // // When a reset packet has been sent, no further gameplay packets should be // sent until the game has been reset. Non-gameplay packets such as 'ping' // are allowed. // When a reset packet has been received, all further incoming gameplay // packets are ignored until the game has been reset. // // conn->stateFlags.reset.localReset is set when a reset packet is sent. // conn->stateFlags.reset.remoteReset is set when a reset packet is // received. // // When either localReset or remoteReset gets set and the other flag isn't // set, Netplay_connectionReset() gets called. // // As soon as the following three conditions are met, the reset callback is // called and the localReset and remoteReset flags are cleared. // - conn->stateFlags.reset.localReset is set // - conn->stateFlags.reset.remoteReset is set // - the reset callback is non-NULL. // // Elsewhere in the UQM source: // When the local side causes a reset, it calls Netplay_localReset(). // When a remote reset packet is received, Netplay_remoteReset() is called // (which will sent a reset packet back as confirmation, as required). // At the end of melee, the reset callback is set (for each connection), // and the game will wait until the reset callback for each connection has // been called (when the forementioned conditions have become true) // (or until the connection is terminated). // This function is called when one side initiates a reset. static void Netplay_connectionReset(NetConnection *conn, NetplayResetReason reason, bool byRemote) { switch (NetConnection_getState(conn)) { case NetState_unconnected: case NetState_connecting: case NetState_init: case NetState_inSetup: break; case NetState_preBattle: case NetState_interBattle: case NetState_selectShip: case NetState_inBattle: case NetState_endingBattle: case NetState_endingBattle2: case NetState_endMelee: resetFeedback(conn, reason, byRemote); break; } } static void Netplay_doConnectionResetCallback(NetConnection *conn) { NetConnection_ResetCallback callback; void *resetArg; callback = conn->resetCallback; resetArg = conn->resetCallbackArg; NetConnection_setResetCallback(conn, NULL, NULL); // Clear the resetCallback field before performing the callback, // so that it can be set again from inside the callback // function. callback(conn, resetArg); } static void Netplay_resetConditionTriggered(NetConnection *conn) { if (conn->resetCallback == NULL) return; if (!conn->stateFlags.reset.localReset || !conn->stateFlags.reset.remoteReset) return; conn->stateFlags.reset.localReset = false; conn->stateFlags.reset.remoteReset = false; Netplay_doConnectionResetCallback(conn); } void Netplay_setResetCallback(NetConnection *conn, NetConnection_ResetCallback callback, void *resetArg) { NetConnection_setResetCallback(conn, callback, resetArg); Netplay_resetConditionTriggered(conn); } void Netplay_localReset(NetConnection *conn, NetplayResetReason reason) { assert(!conn->stateFlags.reset.localReset); conn->stateFlags.reset.localReset = true; if (conn->stateFlags.reset.remoteReset) { // Both sides have initiated/confirmed the reset. Netplay_resetConditionTriggered(conn); } else { sendReset(conn, reason); Netplay_connectionReset(conn, reason, false); } } void Netplay_remoteReset(NetConnection *conn, NetplayResetReason reason) { assert(!conn->stateFlags.reset.remoteReset); // Should already be checked when the packet arrives. conn->stateFlags.reset.remoteReset = true; if (!conn->stateFlags.reset.localReset) { sendReset(conn, reason); conn->stateFlags.reset.localReset = true; Netplay_connectionReset(conn, reason, true); } Netplay_resetConditionTriggered(conn); } bool Netplay_isLocalReset(const NetConnection *conn) { return conn->stateFlags.reset.localReset; } bool Netplay_isRemoteReset(const NetConnection *conn) { return conn->stateFlags.reset.remoteReset; } uqm-0.6.2/sc2/src/sc2code/netplay/packetq.c0000600000175000017500000001216310543202057017060 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define NETCONNECTION_INTERNAL #include "netplay.h" #include "netconnection.h" #include "packetq.h" #include "netsend.h" #include "packetsenders.h" #ifdef NETPLAY_DEBUG # include "libs/log.h" #endif #include #include #include static inline PacketQueueLink * PacketQueueLink_alloc(void) { // XXX: perhaps keep a pool of links? return malloc(sizeof (PacketQueueLink)); } static inline void PacketQueueLink_delete(PacketQueueLink *link) { free(link); } // 'maxSize' should at least be 1 void PacketQueue_init(PacketQueue *queue) { queue->size = 0; queue->first = NULL; queue->end = &queue->first; queue->firstUrgent = NULL; queue->endUrgent = &queue->first; } static void PacketQueue_deleteLinks(PacketQueueLink *link) { while (link != NULL) { PacketQueueLink *next = link->next; Packet_delete(link->packet); PacketQueueLink_delete(link); link = next; } } void PacketQueue_uninit(PacketQueue *queue) { PacketQueue_deleteLinks(queue->firstUrgent); PacketQueue_deleteLinks(queue->first); } void queuePacket(NetConnection *conn, Packet *packet, bool urgent) { PacketQueue *queue; PacketQueueLink *link; assert(NetConnection_isConnected(conn)); assert(!urgent || !packetTypeData[packetType(packet)].inTurn); // Urgent packets should never stall the connection. queue = &conn->queue; link = PacketQueueLink_alloc(); link->packet = packet; link->next = NULL; if (urgent) { *queue->endUrgent = link; queue->endUrgent = &link->next; } else { *queue->end = link; queue->end = &link->next; } queue->size++; // XXX: perhaps check that this queue isn't getting too large? #ifdef NETPLAY_DEBUG if (packetType(packet) != PACKET_BATTLEINPUT && packetType(packet) != PACKET_CHECKSUM) { // Reporting BattleInput or Checksum would get so spammy that it // would slow down the battle. log_add(log_Debug, "NETPLAY: [%d] ==> Queueing packet of type %s.\n", NetConnection_getPlayerNr(conn), packetTypeData[packetType(packet)].name); } #endif } // If an error occurs during sending, we leave the unsent packets in // the queue, and let the caller decide what to do with them. // This function may return -1 with errno EAGAIN if we're waiting for // the other party to act first. static int flushPacketQueueLinks(NetConnection *conn, PacketQueueLink **first) { PacketQueueLink *link; PacketQueueLink *next; PacketQueue *queue = &conn->queue; for (link = *first; link != NULL; link = next) { if (packetTypeData[packetType(link->packet)].inTurn && (!conn->stateFlags.myTurn || conn->stateFlags.endingTurn)) { // This packet requires it to be 'our turn', and it isn't, // or we've already told the other party we wanted to end our // turn. // This should never happen in the urgent queue. assert(first != &queue->firstUrgent); if (!conn->stateFlags.myTurn && !conn->stateFlags.endingTurn) { conn->stateFlags.endingTurn = true; if (sendEndTurnDirect(conn) == -1) { // errno is set *first = link; return -1; } } *first = link; errno = EAGAIN; // We need to wait for the reply to the turn change. return -1; } if (sendPacket(conn, link->packet) == -1) { // Errno is set. *first = link; return -1; } next = link->next; Packet_delete(link->packet); PacketQueueLink_delete(link); queue->size--; } *first = link; return 0; } int flushPacketQueue(NetConnection *conn) { int flushResult; PacketQueue *queue = &conn->queue; assert(NetConnection_isConnected(conn)); flushResult = flushPacketQueueLinks(conn, &queue->firstUrgent); if (queue->firstUrgent == NULL) queue->endUrgent = &queue->firstUrgent; if (flushResult == -1) { // errno is set return -1; } flushResult = flushPacketQueueLinks(conn, &queue->first); if (queue->first == NULL) queue->end = &queue->first; if (flushResult == -1) { // errno is set return -1; } // If a turn change had been requested by the other side while it was // our turn, we first sent everything we still had to send in our turn. // Now that is done, it is the time to actually give up the turn. if (conn->stateFlags.pendingTurnChange) { assert(conn->stateFlags.myTurn); conn->stateFlags.myTurn = false; conn->stateFlags.pendingTurnChange = false; // Send the confirmation to the other side: if (sendEndTurnDirect(conn) == -1) { // errno is set return -1; } } return 0; } uqm-0.6.2/sc2/src/sc2code/netplay/netoptions.h0000600000175000017500000000265210543202056017640 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETOPTIONS_H #define _NETOPTIONS_H #include "types.h" #include #define NETPLAY_NUM_PLAYERS 2 // Not using NUM_PLAYERS because that would mean we'd have // to include init.h, and all that comes with it. // XXX: Don't use a hardcoded limit. typedef struct { bool isServer; const char *host; const char *port; // May be given as a service name. } NetplayPeerOptions; typedef struct { const char *metaServer; const char *metaPort; // May be given as a service name. NetplayPeerOptions peer[NETPLAY_NUM_PLAYERS]; size_t inputDelay; } NetplayOptions; extern NetplayOptions netplayOptions; #endif /* _NETOPTIONS_H */ uqm-0.6.2/sc2/src/sc2code/netplay/netmelee.h0000600000175000017500000000551210543202057017233 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if !defined(_NETMELEE_H) && defined(NETPLAY) #define _NETMELEE_H #include "netplay.h" #include "netinput.h" #include "netconnection.h" #include "packetsenders.h" #include "../controls.h" // for BATTLE_INPUT_STATE extern struct NetConnection *netConnections[]; void addNetConnection(NetConnection *conn, int playerNr); void removeNetConnection(int playerNr); void closeAllConnections(void); void closeDisconnectedConnections(void); size_t getNumNetConnections(void); struct melee_state *NetMelee_getMeleeState(NetConnection *conn); struct battlestate_struct *NetMelee_getBattleState(NetConnection *conn); void netInput(void); void netInputBlocking(uint32 timeoutMs); void flushPacketQueues(void); void confirmConnections(void); void cancelConfirmations(void); void connectionsLocalReady(NetConnection_ReadyCallback callback, void *arg); bool allConnected(void); void sendBattleInputConnections(BATTLE_INPUT_STATE input); void sendChecksumConnections(uint32 frameNr, uint32 checksum); void initBattleStateDataConnections(void); void setBattleStateConnections(struct battlestate_struct *bs); BATTLE_INPUT_STATE networkBattleInput(COUNT player, STARSHIPPTR StarShipPtr); NetConnection *openPlayerNetworkConnection(COUNT player, void *extra); void closePlayerNetworkConnection(COUNT player); typedef bool(*ForAllCallback)(NetConnection *conn, void *arg); bool forAllConnectedPlayers(ForAllCallback callback, void *arg); bool setupInputDelay(size_t localInputDelay); bool sendInputDelayConnections(size_t delay); bool setStateConnections(NetState state); bool sendAbortConnections(NetplayAbortReason reason); bool resetConnections(NetplayResetReason reason); bool localReadyConnections(NetConnection_ReadyCallback readyCallback, void *arg, bool notifyRemote); bool negotiateReady(NetConnection *conn, bool notifyRemote, NetState nextState); bool negotiateReadyConnections(bool notifyRemote, NetState nextState); bool waitReady(NetConnection *conn); bool waitReset(NetConnection *conn, NetState nextState); bool waitResetConnections(NetState nextState); #endif /* _NETMELEE_H */ uqm-0.6.2/sc2/src/sc2code/netplay/netstate.h0000600000175000017500000000435110543202057017264 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETSTATE_H #define _NETSTATE_H #include "port.h" typedef struct NetConnectionStateData NetConnectionStateData; // State of a NetConnection. typedef enum { NetState_unconnected, /* No connection initiated */ NetState_connecting, /* Connection being setup */ NetState_init, /* Initialising the connection */ NetState_inSetup, /* In the network game setup */ NetState_preBattle, /* Pre-battle initialisations */ NetState_interBattle, /* Negotiations between battles. */ NetState_selectShip, /* Selecting a ship in battle */ NetState_inBattle, /* Battle has started */ NetState_endingBattle, /* Both sides are prepared to end */ NetState_endingBattle2, /* Waiting for the final synchronisation */ NetState_endMelee, /* Melee ended; remote is not yet in setup */ } NetState; #include "types.h" typedef struct { const char *name; } NetStateData; extern NetStateData netStateData[]; typedef void (*NetConnectionStateData_ReleaseFunction)( NetConnectionStateData *stateData); #define NETCONNECTION_STATE_DATA_COMMON \ NetConnectionStateData_ReleaseFunction releaseFunction; struct NetConnectionStateData { NETCONNECTION_STATE_DATA_COMMON }; void NetConnectionStateData_release(NetConnectionStateData *stateData); static inline bool NetState_battleActive(NetState state) { return state == NetState_inBattle || state == NetState_endingBattle || state == NetState_endingBattle2; } #endif /* _NETSTATE_H */ uqm-0.6.2/sc2/src/sc2code/netplay/netrcv.h0000600000175000017500000000162710543202056016740 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETRCV_H #define _NETRCV_H #include "libs/net.h" void dataReadyCallback(NetDescriptor *nd); #endif /* _NETRCV_H */ uqm-0.6.2/sc2/src/sc2code/netplay/checkbuf.c0000600000175000017500000001004610543202056017177 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PORT_WANT_ERRNO #include "port.h" #include "netplay.h" #include "checkbuf.h" #include "libs/log.h" #include "libs/misc.h" #include "../battle.h" // for battleFrameCount #include #include static inline BattleFrameCounter ChecksumBuffer_getCurrentFrameNr(void) { return battleFrameCount; } void ChecksumBuffer_init(ChecksumBuffer *cb, size_t delay, size_t interval) { // The input buffer lags BattleInput_inputDelay frames behind, // but only every interval frames will there be a checksum to be // checked. // Checksums will be checked when 'frameNr % interval == 0'. // (and frameNr is zero-based). // The checksum of frame n will be processed in frame 'n + delay'. // In the worst case, side 1 processes frames 'n' through 'n + delay - 1', // then blocks in frame 'n + delay' (after sending a checksum, if that's // pertinent for that frame). // Then side 2 receives all this input and these checksums, and // progresses to 'delay' frames after the last frame the received input // originated from, and blocks in the frame after it (after sending a // checksum, if that's pertinent for the frame). // So it sent input and checksums for frames 'n' through // 'n + delay + delay + 1'. // The input and checksums for these '2*delay + 2' frames are still // unhandled by side 1, so it needs buffer space for this. // With checksums only sent every interval frames, the buffer space // needed will be 'roundUp(2*delay + 2)' spaces. size_t bufSize = ((2 * delay + 2) + (interval - 1)) / interval; { #ifdef NETPLAY_DEBUG size_t i; #endif cb->checksums = malloc(bufSize * sizeof (ChecksumEntry)); cb->maxSize = bufSize; cb->interval = interval; #ifdef NETPLAY_DEBUG for (i = 0; i < bufSize; i++) { cb->checksums[i].checksum = 0; cb->checksums[i].frameNr = (BattleFrameCounter) -1; } #endif } } void ChecksumBuffer_uninit(ChecksumBuffer *cb) { if (cb->checksums != NULL) { free(cb->checksums); cb->checksums = NULL; } } // Returns the entry that would be used for the checksum for the specified // frame. Whether the entry is actually valid is not checked. static ChecksumEntry * ChecksumBuffer_getChecksumEntry(ChecksumBuffer *cb, BattleFrameCounter frameNr) { size_t index; ChecksumEntry *entry; assert(frameNr % cb->interval == 0); // We only record checksums exactly every 'interval' frames. index = (frameNr / cb->interval) % cb->maxSize; entry = &cb->checksums[index]; return entry; } bool ChecksumBuffer_addChecksum(ChecksumBuffer *cb, BattleFrameCounter frameNr, Checksum checksum) { ChecksumEntry *entry; assert(frameNr % cb->interval == 0); entry = ChecksumBuffer_getChecksumEntry(cb, frameNr); #ifdef NETPLAY_DEBUG entry->frameNr = frameNr; #endif entry->checksum = checksum; return true; } // Pre: frameNr is within the range of the checksums stored in cb. bool ChecksumBuffer_getChecksum(ChecksumBuffer *cb, BattleFrameCounter frameNr, Checksum *result) { ChecksumEntry *entry; entry = ChecksumBuffer_getChecksumEntry(cb, frameNr); #ifdef NETPLAY_DEBUG if (frameNr != entry->frameNr) { log_add(log_Error, "Checksum buffer entry for requested frame %u " "(still?) contains a checksum for frame %u.\n", frameNr, entry->frameNr); return false; } #endif *result = entry->checksum; return true; } uqm-0.6.2/sc2/src/sc2code/netplay/checkbuf.h0000600000175000017500000000406610543202056017211 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CHECKBUF_H #define _CHECKBUF_H typedef struct ChecksumEntry ChecksumEntry; typedef struct ChecksumBuffer ChecksumBuffer; #include "../battle.h" // for BattleFrameCounter #include "checksum.h" struct ChecksumEntry { #ifdef NETPLAY_DEBUG BattleFrameCounter frameNr; // The number of the frame this checksum originated from. // If the checksumming code is working correctly, the checksum // can only come from one frame, so this value is not needed // for normal operation. // Its only use is to detect some cases where checksumming code // is *not* working correctly. #endif Checksum checksum; }; struct ChecksumBuffer { ChecksumEntry *checksums; // Cyclic buffer. if 'size' > 0, then 'first' is an index to // the first used entry, 'size' is the number of used // entries in the buffer, and (first + size) % maxSize is the // index to just past the end of the buffer. size_t maxSize; size_t interval; }; void ChecksumBuffer_init(ChecksumBuffer *cb, size_t delay, size_t interval); void ChecksumBuffer_uninit(ChecksumBuffer *cb); bool ChecksumBuffer_addChecksum(ChecksumBuffer *cb, BattleFrameCounter frameNr, Checksum checksum); bool ChecksumBuffer_getChecksum(ChecksumBuffer *cb, BattleFrameCounter frameNr, Checksum *result); #endif /* _CHECKBUF_H */ uqm-0.6.2/sc2/src/sc2code/netplay/netsend.h0000600000175000017500000000164310543202056017075 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETSEND_H #define _NETSEND_H #include "packet.h" int sendPacket(NetConnection *conn, Packet *packet); #endif /* _NETSEND_H */ uqm-0.6.2/sc2/src/sc2code/netplay/Makeinfo0000600000175000017500000000032610543202056016735 0ustar joeyjoeyuqm_SUBDIRS="proto" uqm_CFILES="checkbuf.c checksum.c crc.c netconnection.c netinput.c netmelee.c netmisc.c netoptions.c netrcv.c netsend.c netstate.c notify.c packet.c packethandlers.c packetsenders.c packetq.c" uqm-0.6.2/sc2/src/sc2code/netplay/crc.h0000600000175000017500000000247310543202056016206 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CRC_H #define _CRC_H #include "types.h" #include // If set, every CRC operation is logged. Very spammy. #undef DUMP_CRC_OPS typedef struct crc_State crc_State; struct crc_State { uint32 crc; }; void crc_init(crc_State *state); void crc_processBytes(crc_State *state, uint8 *buf, size_t bufLen); void crc_processUint8(crc_State *state, uint8 val); void crc_processUint16(crc_State *state, uint16 val); void crc_processUint32(crc_State *state, uint32 val); uint32 crc_finish(const crc_State *state); #endif /* _CRC_H */ uqm-0.6.2/sc2/src/sc2code/netplay/FILES0000600000175000017500000000470510543202057016054 0ustar joeyjoeyIn netplay/: crc.{c,h} Generic CRC routines. checkbuf.{c,h} Buffer of checksums. checksum.{c,h} Routines for checksumming the game state. netconnection.{c,h} Definition of NetConnection, being the state of a network connection, and operations on it. nc_connect.ci Part of netconnection.c that handles establishing connections. netinput.{c,h} Definitions and operations for melee input commands over a network connection. netmelee.{c,h} Keeps track of network connections used in the game, with methods to control them all at once. Functions that directly access the game data are kept in the relevant files (melee.c, pickmele.c, battle.c). netmisc.{c,h} Miscelaneous functions that didn't fit in elsewhere. netoptions.{c,h} Description of a network connection to be established. netplay.h Some global netplay definitions. netrcv.{c,h} Processes incoming packets. Does know about the protocol and will do consistency checking. Does not directly manipulate the game state. netsend.{c,h} Enqueues all sorts of packets for sending. Does not know about the protocol and hence will do no checks for protocol sanity. netstate.{c,h} Definitions of the states of a network connection. notify.{c,h} Routines for notifying a remote side of local changes. Knows about the protocal and has assert()s to check for local consistency. packet.{c,h} Definition and creation of packets. Create functions should only be called from netsend.c. packethandlers.{c,h} Routines for processing each type of incoming packet. packetq.{c,h} Manages the packet queue. packetsenders.{c,h} Creates and sends/queues packets. In netplay/proto/: npconfirm.{c,h} Functions for handing the 'confirmation' protocol. ready.{c,h} Functions for handling the 'ready' protocol. reset.{c,h} Functions for handling the 'reset' protocol. TODO: Division: - files that interface with sockets and knows nothing of the game (these are in libs/network) - files that know of sockets and the game but don't directly interface with either - files that interface with the game and know nothing of sockets uqm-0.6.2/sc2/src/sc2code/netplay/netoptions.c0000600000175000017500000000236210543202056017631 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "netoptions.h" NetplayOptions netplayOptions = { /* .metaServer = */ "uqm.stack.nl", /* .metaPort = */ "21836", /* .peer = */ { /* [0] Player 1 (bottom) */ { /* .isServer = */ true, /* .host = */ "localhost", /* .port = */ "21837" /* 0x554d - "UM" */, }, /* [1] Player 2 (top) */ { /* .isServer = */ true, /* .host = */ "localhost", /* .port = */ "21837" /* 0x554d - "UM" */, }, }, /* .inputDelay = */ 2, }; uqm-0.6.2/sc2/src/sc2code/netplay/packethandlers.c0000600000175000017500000004303610543202056020422 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PORT_WANT_ERRNO #include "port.h" #define NETCONNECTION_INTERNAL #include "netplay.h" #include "packethandlers.h" #include "netinput.h" #include "netmisc.h" #include "packetsenders.h" #include "proto/npconfirm.h" #include "proto/ready.h" #include "proto/reset.h" #include "libs/log.h" #include "controls.h" // for BATTLE_INPUT_STATE #include "init.h" // for NUM_PLAYERS #include "globdata.h" // for GLOBAL #include "melee.h" // for various update functions. #include "pickmele.h" // for various update functions. #include "libs/mathlib.h" // for TFB_SeedRandom #include static bool testNetState(bool condition, PacketType type) { if (!condition) { log_add(log_Error, "Packet of type '%s' received from wrong " "state.\n", packetTypeData[type].name); errno = EBADMSG; } return condition; } static int versionCompare(int major1, int minor1, int patch1, int major2, int minor2, int patch2) { if (major1 < major2) return -1; if (major1 > major2) return 1; if (minor1 < minor2) return -1; if (minor1 > minor2) return 1; if (patch1 < patch2) return -1; if (patch1 > patch2) return 1; return 0; } int PacketHandler_Init(NetConnection *conn, const Packet_Init *packet) { if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(conn->state == NetState_init && !conn->stateFlags.ready.remoteReady, PACKET_INIT)) return -1; // errno is set if (packet->protoVersion.major != NETPLAY_PROTOCOL_VERSION_MAJOR || packet->protoVersion.minor != NETPLAY_PROTOCOL_VERSION_MINOR) { sendAbort (conn, AbortReason_versionMismatch); abortFeedback(conn, AbortReason_versionMismatch); log_add(log_Error, "Protocol version %d.%d not supported.\n", packet->protoVersion.major, packet->protoVersion.minor); errno = ENOSYS; return -1; } if (versionCompare(packet->uqmVersion.major, packet->uqmVersion.minor, packet->uqmVersion.patch, NETPLAY_MIN_UQM_VERSION_MAJOR, NETPLAY_MIN_UQM_VERSION_MINOR, NETPLAY_MIN_UQM_VERSION_PATCH) < 0) { sendAbort (conn, AbortReason_versionMismatch); abortFeedback(conn, AbortReason_versionMismatch); log_add(log_Error, "Remote side is running a version of UQM that " "is too old (%d.%d.%d; %d.%d.%d is required).\n", packet->uqmVersion.major, packet->uqmVersion.minor, packet->uqmVersion.patch, NETPLAY_MIN_UQM_VERSION_MAJOR, NETPLAY_MIN_UQM_VERSION_MINOR, NETPLAY_MIN_UQM_VERSION_PATCH); errno = ENOSYS; return -1; } Netplay_remoteReady(conn); return 0; } int PacketHandler_Ping(NetConnection *conn, const Packet_Ping *packet) { if (!testNetState(conn->state > NetState_init, PACKET_PING)) return -1; // errno is set sendAck(conn, packet->id); return 0; } int PacketHandler_Ack(NetConnection *conn, const Packet_Ack *packet) { if (!testNetState(conn->state > NetState_init, PACKET_ACK)) return -1; // errno is set (void) conn; (void) packet; return 0; } int PacketHandler_EndTurn(NetConnection *conn, const Packet_EndTurn *packet) { if (!testNetState(conn->state > NetState_init && !conn->stateFlags.pendingTurnChange, PACKET_ENDTURN)) return -1; // errno is set if (conn->stateFlags.endingTurn) { // This was the confirmation we were waiting for. // NB. A remote request while we had sent a request serves as // a confirmation. conn->stateFlags.myTurn = !conn->stateFlags.myTurn; conn->stateFlags.endingTurn = false; } else { // The other party wants to change whose turn it is. // If it would become the other party's turn, we wait until // the queue is flushed to actually carry out the turn change, // and send the confirmation. I we wouldn't do that, and we still // had some data to send in our own turn, we would end up asking // for our turn back, and the turn would keep changing without // any progress being made. if (conn->stateFlags.myTurn) { // Schedule the turn change until after the next queue flush. conn->stateFlags.pendingTurnChange = true; } else { conn->stateFlags.myTurn = true; sendEndTurn(conn); } } (void) packet; // Its contents is not interesting. return 0; } // Convert the side indication relative to a remote party to // a local player number. static inline int localSide(NetConnection *conn, NetplaySide side) { if (side == NetplaySide_local) { // "local" relative to the remote party. return conn->player; } return 1 - conn->player; } static bool checkYourTurn(NetConnection *conn, PacketType type) { if (conn->stateFlags.myTurn) { log_add(log_Warning, "Packet of type '%s' received in an " "inappropriate turn.\n", packetTypeData[type].name); errno = EBADMSG; return false; } return true; } int PacketHandler_Ready(NetConnection *conn, const Packet_Ready *packet) { if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(readyFlagsMeaningful(conn->state) && !conn->stateFlags.ready.remoteReady, PACKET_READY)) return -1; // errno is set Netplay_remoteReady(conn); (void) packet; // Its contents is not interesting. return 0; } int PacketHandler_Fleet(NetConnection *conn, const Packet_Fleet *packet) { uint16 numShips = ntoh16(packet->numShips); size_t i; size_t len; int player; BattleStateData *battleStateData; if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(conn->state == NetState_inSetup, PACKET_FLEET)) return -1; // errno is set if (!checkYourTurn(conn, PACKET_FLEET)) { // errno is set return -1; } player = localSide(conn, (NetplaySide) packet->side); len = packetLength((const Packet *) packet); if (sizeof packet + numShips * sizeof(packet->ships[0]) > len) { // There is not enough room in the packet to contain all // the ships it says it contains. log_add(log_Warning, "Invalid fleet size. Specified size is %d, " "actual size = %d\n", numShips, (len - sizeof packet) / sizeof(packet->ships[0])); errno = EBADMSG; return -1; } battleStateData = (BattleStateData *) NetConnection_getStateData(conn); if (conn->stateFlags.handshake.localOk) { Netplay_cancelConfirmation(conn); confirmationCancelled(battleStateData->meleeState, conn->player); } for (i = 0; i < numShips; i++) { int ship = packet->ships[i].ship; int index = packet->ships[i].index; bool updateResult = updateFleetShip( battleStateData->meleeState, player, index, ship); if (!updateResult) { errno = EBADMSG; return -1; } } // Padding data may follow; it is ignored. return 0; } int PacketHandler_TeamName(NetConnection *conn, const Packet_TeamName *packet) { size_t nameLen; int side; BattleStateData *battleStateData; if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(conn->state == NetState_inSetup, PACKET_TEAMNAME)) return -1; // errno is set if (!checkYourTurn(conn, PACKET_TEAMNAME)) { // errno is set return -1; } battleStateData = (BattleStateData *) NetConnection_getStateData(conn); if (conn->stateFlags.handshake.localOk) { Netplay_cancelConfirmation(conn); confirmationCancelled(battleStateData->meleeState, conn->player); } side = localSide(conn, (NetplaySide) packet->side); nameLen = packetLength((const Packet *) packet) - sizeof (Packet_TeamName) - 1; // The -1 is for not counting the terminating '\0'. updateTeamName(battleStateData->meleeState, side, packet->name, nameLen); // Padding data may follow; it is ignored. return 0; } static void handshakeComplete(NetConnection *conn) { assert(!conn->stateFlags.handshake.localOk); assert(!conn->stateFlags.handshake.remoteOk); assert(!conn->stateFlags.handshake.canceling); assert(conn->state == NetState_inSetup); NetConnection_setState(conn, NetState_preBattle); } int PacketHandler_Handshake0(NetConnection *conn, const Packet_Handshake0 *packet) { if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(handshakeMeaningful(conn->state) && !conn->stateFlags.handshake.remoteOk, PACKET_HANDSHAKE0)) return -1; // errno is set conn->stateFlags.handshake.remoteOk = true; if (conn->stateFlags.handshake.localOk && !conn->stateFlags.handshake.canceling) sendHandshake1(conn); (void) packet; // Its contents is not interesting. return 0; } int PacketHandler_Handshake1(NetConnection *conn, const Packet_Handshake1 *packet) { if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(handshakeMeaningful(conn->state) && (conn->stateFlags.handshake.localOk || conn->stateFlags.handshake.canceling), PACKET_HANDSHAKE1)) return -1; // errno is set if (conn->stateFlags.handshake.canceling) { conn->stateFlags.handshake.remoteOk = true; } else { bool remoteWasOk = conn->stateFlags.handshake.remoteOk; conn->stateFlags.handshake.localOk = false; conn->stateFlags.handshake.remoteOk = false; if (!remoteWasOk) { // Received Handshake1 without prior Handshake0. // A Handshake0 is implied, but we still need to confirm // it with a Handshake1. sendHandshake1(conn); } handshakeComplete(conn); } (void) packet; // Its contents is not interesting. return 0; } int PacketHandler_HandshakeCancel(NetConnection *conn, const Packet_HandshakeCancel *packet) { if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(handshakeMeaningful(conn->state) && conn->stateFlags.handshake.remoteOk, PACKET_HANDSHAKECANCEL)) return -1; // errno is set conn->stateFlags.handshake.remoteOk = false; sendHandshakeCancelAck(conn); (void) packet; // Its contents is not interesting. return 0; } int PacketHandler_HandshakeCancelAck(NetConnection *conn, const Packet_HandshakeCancelAck *packet) { if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(handshakeMeaningful(conn->state) && conn->stateFlags.handshake.canceling, PACKET_HANDSHAKECANCELACK)) return -1; // errno is set conn->stateFlags.handshake.canceling = false; if (conn->stateFlags.handshake.localOk) { if (conn->stateFlags.handshake.remoteOk) { sendHandshake1(conn); } else sendHandshake0(conn); } (void) packet; // Its contents is not interesting. return 0; } int PacketHandler_SeedRandom(NetConnection *conn, const Packet_SeedRandom *packet) { BattleStateData *battleStateData; if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(conn->state == NetState_preBattle && !conn->stateFlags.discriminant, PACKET_SEEDRANDOM)) return -1; // errno is set battleStateData = (BattleStateData *) NetConnection_getStateData(conn); updateRandomSeed (battleStateData->meleeState, conn->player, ntoh32(packet->seed)); conn->stateFlags.agreement.randomSeed = true; return 0; } int PacketHandler_InputDelay(NetConnection *conn, const Packet_InputDelay *packet) { BattleStateData *battleStateData; uint32 delay; if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(conn->state == NetState_preBattle, PACKET_INPUTDELAY)) return -1; // errno is set battleStateData = (BattleStateData *) NetConnection_getStateData(conn); delay = ntoh32(packet->delay); if (delay > 60 * BATTLE_FRAME_RATE) { log_add(log_Error, "NETPLAY: [%d] Received absurdly large " "input delay value (%d).\n", conn->player, delay); return -1; } conn->stateFlags.inputDelay = ntoh32(packet->delay); return 0; } int PacketHandler_SelectShip(NetConnection *conn, const Packet_SelectShip *packet) { bool updateResult; BattleStateData *battleStateData; if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(conn->state == NetState_selectShip, PACKET_SELECTSHIP)) return -1; // errno is set battleStateData = (BattleStateData *) NetConnection_getStateData(conn); updateResult = updateMeleeSelection(battleStateData->getMeleeState, conn->player, ntoh16(packet->ship)); if (!updateResult) { errno = EBADMSG; return -1; } return 0; } int PacketHandler_BattleInput(NetConnection *conn, const Packet_BattleInput *packet) { BATTLE_INPUT_STATE input; BattleInputBuffer *bib; if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(conn->state == NetState_inBattle || conn->state == NetState_endingBattle || conn->state == NetState_endingBattle2, PACKET_BATTLEINPUT)) return -1; // errno is set input = (BATTLE_INPUT_STATE) packet->state; bib = getBattleInputBuffer(conn->player); if (!BattleInputBuffer_push(bib, input)) { // errno is set return -1; } return 0; } int PacketHandler_FrameCount(NetConnection *conn, const Packet_FrameCount *packet) { BattleStateData *battleStateData; BattleFrameCounter frameCount; if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(conn->state == NetState_endingBattle, PACKET_FRAMECOUNT)) return -1; // errno is set frameCount = (BattleFrameCounter) ntoh32(packet->frameCount); #ifdef NETPLAY_DEBUG log_add(log_Debug, "NETPLAY: [%d] <== Received battleFrameCount %u.\n", conn->player, (unsigned int) frameCount); #endif battleStateData = (BattleStateData *) NetConnection_getStateData(conn); if (frameCount > battleStateData->endFrameCount) battleStateData->endFrameCount = frameCount; Netplay_remoteReady(conn); return 0; } int PacketHandler_Checksum(NetConnection *conn, const Packet_Checksum *packet) { #ifdef NETPLAY_CHECKSUM uint32 frameNr; uint32 checksum; size_t delay; size_t interval; #endif if (conn->stateFlags.reset.localReset) return 0; if (conn->stateFlags.reset.remoteReset) { errno = EBADMSG; return -1; } if (!testNetState(NetState_battleActive(conn->state), PACKET_CHECKSUM)) return -1; // errno is set #ifdef NETPLAY_CHECKSUM frameNr = ntoh32(packet->frameNr); checksum = ntoh32(packet->checksum); interval = NetConnection_getChecksumInterval(conn); delay = getBattleInputDelay(); if (frameNr % interval != 0) { log_add(log_Warning, "NETPLAY: [%d] <== Received checksum " "for frame %u, while we only expect checksums on frames " "divisable by %u -- discarding.\n", conn->player, (unsigned int) frameNr, interval); return 0; // No need to close the connection; checksums are not // essential. } // The checksum is sent at the beginning of a frame. // If we're in frame n and have sent our input already, // the remote side has got enough input to progress delay + 1 frames from // frame n. The next frame is then n + delay + 1, for which we can // receive a checksum. if (frameNr > battleFrameCount + delay + 1) { log_add(log_Warning, "NETPLAY: [%d] <== Received checksum " "for a frame too far in the future (frame %u, current " "is %u, input delay is %u) -- discarding.\n", conn->player, (unsigned int) frameNr, battleFrameCount, delay); return 0; // No need to close the connection; checksums are not // essential. } // We can progress delay more frames after the last frame for which we // received input. If we call that frame n, we can complete frames // n through n + delay - 1. While we are waiting for the next input, // in frame n + delay, we will first receive the checksum that the // remote side sent at the start of frame n + 1. // In this situation frameNr is n + 1, and battleFrameCount is // n + delay. if (frameNr + delay < battleFrameCount) { log_add(log_Warning, "NETPLAY: [%d] <== Received checksum " "for a frame too far in the past (frame %u, current " "is %u, input delay is %u) -- discarding.\n", conn->player, (unsigned int) frameNr, battleFrameCount, delay); return 0; // No need to close the connection; checksums are not // essential. } addRemoteChecksum(conn, frameNr, checksum); #endif #ifndef NETPLAY_CHECKSUM (void) packet; #endif return 0; } int PacketHandler_Abort(NetConnection *conn, const Packet_Abort *packet) { abortFeedback(conn, packet->reason); return -1; // Close connection. } int PacketHandler_Reset(NetConnection *conn, const Packet_Reset *packet) { NetplayResetReason reason; if (!testNetState(!conn->stateFlags.reset.remoteReset, PACKET_RESET)) return -1; // errno is set reason = ntoh16(packet->reason); Netplay_remoteReset(conn, reason); return 0; } uqm-0.6.2/sc2/src/sc2code/netplay/packethandlers.h0000600000175000017500000000316610543202056020427 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _PACKETHANDLERS_H #define _PACKETHANDLERS_H #include "packet.h" #define DECLARE_PACKETHANDLER(type) \ int PacketHandler_##type(NetConnection *conn, \ const Packet_##type *packet); DECLARE_PACKETHANDLER(Init); DECLARE_PACKETHANDLER(Ping); DECLARE_PACKETHANDLER(Ack); DECLARE_PACKETHANDLER(EndTurn); DECLARE_PACKETHANDLER(Ready); DECLARE_PACKETHANDLER(Fleet); DECLARE_PACKETHANDLER(TeamName); DECLARE_PACKETHANDLER(Handshake0); DECLARE_PACKETHANDLER(Handshake1); DECLARE_PACKETHANDLER(HandshakeCancel); DECLARE_PACKETHANDLER(HandshakeCancelAck); DECLARE_PACKETHANDLER(SeedRandom); DECLARE_PACKETHANDLER(InputDelay); DECLARE_PACKETHANDLER(SelectShip); DECLARE_PACKETHANDLER(BattleInput); DECLARE_PACKETHANDLER(FrameCount); DECLARE_PACKETHANDLER(Checksum); DECLARE_PACKETHANDLER(Abort); DECLARE_PACKETHANDLER(Reset); #endif /* _PACKETHANDLERS_H */ uqm-0.6.2/sc2/src/sc2code/netplay/checksum.h0000600000175000017500000000524610543202057017243 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CHECKSUM_H #define _CHECKSUM_H #include "types.h" typedef uint32 Checksum; #include "crc.h" #include "element.h" #include "libs/gfxlib.h" #include "netconnection.h" static inline void crc_processELEMENT_FLAGS(crc_State *state, ELEMENT_FLAGS val) { crc_processUint16(state, (uint16) (val & ~(GOOD_GUY | BAD_GUY))); // Excluding the element side, as this does not have to // be the same for both players over a network. } static inline void crc_processCOUNT(crc_State *state, COUNT val) { crc_processUint16(state, (uint16) val); } static inline void crc_processBYTE(crc_State *state, BYTE val) { crc_processUint8(state, (uint8) val); } static inline void crc_processDWORD(crc_State *state, DWORD val) { crc_processUint32(state, (uint32) val); } static inline void crc_processCOORD(crc_State *state, COORD val) { crc_processUint16(state, (uint16) val); } #if 0 static inline void crc_processTIME_VALUE(crc_State *state, const TIME_VALUE val) { crc_processUint16(state, (uint16) val); } #endif void crc_processEXTENT(crc_State *state, const EXTENT *val); void crc_processVELOCITY_DESC(crc_State *state, const VELOCITY_DESC *val); void crc_processPOINT(crc_State *state, const POINT *val); #if 0 void crc_processSTAMP(crc_State *state, const STAMP *val); void crc_processINTERSECT_CONTROL(crc_State *state, const INTERSECT_CONTROL *val); #endif void crc_processSTATE(crc_State *state, const STATE *val); void crc_processELEMENT(crc_State *state, const ELEMENT *val); void crc_processDispQueue(crc_State *state); void crc_processRNG(crc_State *state); void crc_processState(crc_State *state); void initChecksumBuffers(void); void uninitChecksumBuffers(void); void addLocalChecksum(BattleFrameCounter frameNr, Checksum checksum); void addRemoteChecksum(NetConnection *conn, BattleFrameCounter frameNr, Checksum checksum); bool verifyChecksums(BattleFrameCounter frameNr); #endif /* _CHECKSUM_H */ uqm-0.6.2/sc2/src/sc2code/netplay/packet.c0000600000175000017500000001620710543202056016701 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "netplay.h" #include "packet.h" #include "uqmversion.h" #include "netrcv.h" #include "packethandlers.h" #include #include #include #define DEFINE_PACKETDATA(name, inTurn) \ { \ /* .len = */ sizeof (Packet_##name), \ /* .handler = */ (PacketHandler) PacketHandler_##name, \ /* .name = */ #name, \ /* .inTurn = */ (inTurn) \ } PacketTypeData packetTypeData[PACKET_NUM] = { DEFINE_PACKETDATA(Init, false), DEFINE_PACKETDATA(Ping, false), DEFINE_PACKETDATA(Ack, false), DEFINE_PACKETDATA(EndTurn, false), DEFINE_PACKETDATA(Ready, false), DEFINE_PACKETDATA(Fleet, true), DEFINE_PACKETDATA(TeamName, true), DEFINE_PACKETDATA(Handshake0, false), DEFINE_PACKETDATA(Handshake1, false), DEFINE_PACKETDATA(HandshakeCancel, false), DEFINE_PACKETDATA(HandshakeCancelAck, false), DEFINE_PACKETDATA(SeedRandom, false), DEFINE_PACKETDATA(InputDelay, false), DEFINE_PACKETDATA(SelectShip, false), DEFINE_PACKETDATA(BattleInput, false), DEFINE_PACKETDATA(FrameCount, false), DEFINE_PACKETDATA(Checksum, false), DEFINE_PACKETDATA(Abort, false), DEFINE_PACKETDATA(Reset, false), }; static inline void * Packet_alloc(size_t size) { return malloc(size); } static Packet * Packet_create(PacketType type, size_t extraSize) { Packet *result; size_t len; // Alignment requirement. assert(extraSize % 4 == 0); len = packetTypeData[type].len + extraSize; result = Packet_alloc(len); result->header.len = hton16((uint16) len); result->header.type = hton16((uint16) type); return result; } void Packet_delete(Packet *packet) { free(packet); } Packet_Init * Packet_Init_create(void) { Packet_Init *packet = (Packet_Init *) Packet_create(PACKET_INIT, 0); packet->protoVersion.major = NETPLAY_PROTOCOL_VERSION_MAJOR; packet->protoVersion.minor = NETPLAY_PROTOCOL_VERSION_MINOR; packet->padding0 = 0; packet->uqmVersion.major = UQM_MAJOR_VERSION; packet->uqmVersion.minor = UQM_MINOR_VERSION; packet->uqmVersion.patch = UQM_PATCH_VERSION; packet->padding1 = 0; return packet; } Packet_Ping * Packet_Ping_create(uint32 id) { Packet_Ping *packet = (Packet_Ping *) Packet_create(PACKET_PING, 0); packet->id = hton32(id); return packet; } Packet_Ack * Packet_Ack_create(uint32 id) { Packet_Ack *packet = (Packet_Ack *) Packet_create(PACKET_ACK, 0); packet->id = hton32(id); return packet; } Packet_EndTurn * Packet_EndTurn_create(void) { Packet_EndTurn *packet = (Packet_EndTurn *) Packet_create(PACKET_ENDTURN, 0); return packet; } Packet_Ready * Packet_Ready_create(void) { Packet_Ready *packet = (Packet_Ready *) Packet_create(PACKET_READY, 0); return packet; } // The fleet itself still needs to be filled by the caller. // This function takes care of the necessary padding; it is allocated, // and filled with zero chars. Packet_Fleet * Packet_Fleet_create(NetplaySide side, size_t numShips) { Packet_Fleet *packet; size_t fleetSize; size_t extraSize; fleetSize = numShips * sizeof (FleetEntry); extraSize = (fleetSize + 3) & ~0x03; packet = (Packet_Fleet *) Packet_create(PACKET_FLEET, extraSize); packet->side = (uint8) side; packet->padding = 0; packet->numShips = hton16((uint16) numShips); memset((char *) packet + sizeof (Packet_Fleet) + fleetSize, '\0', extraSize - fleetSize); return packet; } // 'size' is the number of bytes (not characters) in 'name', excluding // a possible terminating '\0'. A '\0' will be included in the packet though. // This function takes care of the required padding. Packet_TeamName * Packet_TeamName_create(NetplaySide side, const char *name, size_t size) { Packet_TeamName *packet; size_t extraSize; extraSize = ((size + 1) + 3) & ~0x03; // The +1 is for the '\0'. packet = (Packet_TeamName *) Packet_create(PACKET_TEAMNAME, extraSize); packet->side = (uint8) side; packet->padding = 0; memcpy(packet->name, name, size); memset((char *) packet + sizeof (Packet_TeamName) + size, '\0', extraSize - size); // This takes care of the terminating '\0', as well as the // padding. return packet; } Packet_Handshake0 * Packet_Handshake0_create(void) { Packet_Handshake0 *packet = (Packet_Handshake0 *) Packet_create(PACKET_HANDSHAKE0, 0); return packet; } Packet_Handshake1 * Packet_Handshake1_create(void) { Packet_Handshake1 *packet = (Packet_Handshake1 *) Packet_create(PACKET_HANDSHAKE1, 0); return packet; } Packet_HandshakeCancel * Packet_HandshakeCancel_create(void) { Packet_HandshakeCancel *packet = (Packet_HandshakeCancel *) Packet_create( PACKET_HANDSHAKECANCEL, 0); return packet; } Packet_HandshakeCancelAck * Packet_HandshakeCancelAck_create(void) { Packet_HandshakeCancelAck *packet = (Packet_HandshakeCancelAck *) Packet_create( PACKET_HANDSHAKECANCELACK, 0); return packet; } Packet_SeedRandom * Packet_SeedRandom_create(uint32 seed) { Packet_SeedRandom *packet = (Packet_SeedRandom *) Packet_create(PACKET_SEEDRANDOM, 0); packet->seed = hton32(seed); return packet; } Packet_InputDelay * Packet_InputDelay_create(uint32 delay) { Packet_InputDelay *packet = (Packet_InputDelay *) Packet_create(PACKET_INPUTDELAY, 0); packet->delay = hton32(delay); return packet; } Packet_SelectShip * Packet_SelectShip_create(uint16 ship) { Packet_SelectShip *packet = (Packet_SelectShip *) Packet_create(PACKET_SELECTSHIP, 0); packet->ship = hton16(ship); packet->padding = 0; return packet; } Packet_BattleInput * Packet_BattleInput_create(uint8 state) { Packet_BattleInput *packet = (Packet_BattleInput *) Packet_create(PACKET_BATTLEINPUT, 0); packet->state = (uint8) state; packet->padding0 = 0; packet->padding1 = 0; return packet; } Packet_FrameCount * Packet_FrameCount_create(uint32 frameCount) { Packet_FrameCount *packet = (Packet_FrameCount *) Packet_create(PACKET_FRAMECOUNT, 0); packet->frameCount = hton32(frameCount); return packet; } Packet_Checksum * Packet_Checksum_create(uint32 frameNr, uint32 checksum) { Packet_Checksum *packet = (Packet_Checksum *) Packet_create(PACKET_CHECKSUM, 0); packet->frameNr = hton32(frameNr); packet->checksum = hton32(checksum); return packet; } Packet_Abort * Packet_Abort_create(uint16 reason) { Packet_Abort *packet = (Packet_Abort *) Packet_create(PACKET_ABORT, 0); packet->reason = hton16(reason); return packet; } Packet_Reset * Packet_Reset_create(uint16 reason) { Packet_Reset *packet = (Packet_Reset *) Packet_create(PACKET_RESET, 0); packet->reason = hton16(reason); return packet; } uqm-0.6.2/sc2/src/sc2code/netplay/netconnection.h0000600000175000017500000001700310543202056020300 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETCONNECTION_H #define _NETCONNECTION_H #include "netplay.h" // for NETPLAY_STATISTICS typedef struct NetConnection NetConnection; typedef struct NetConnectionError NetConnectionError; typedef struct ConnectStateData ConnectStateData; #ifdef NETPLAY_STATISTICS typedef struct NetStatistics NetStatistics; #endif typedef void (*NetConnection_ConnectCallback)(NetConnection *nd); typedef void (*NetConnection_CloseCallback)(NetConnection *nd); typedef void (*NetConnection_ErrorCallback)(NetConnection *nd, const NetConnectionError *error); typedef void (*NetConnection_DeleteCallback)(NetConnection *nd); typedef void (*NetConnection_ReadyCallback)(NetConnection *conn, void *arg); typedef void (*NetConnection_ResetCallback)(NetConnection *conn, void *arg); #include "netstate.h" #include "netoptions.h" #ifdef NETPLAY_CHECKSUM # include "checkbuf.h" #endif struct NetConnectionError { NetState state; int err; union { const struct ListenError *listenError; const struct ConnectError *connectError; } extra; }; #ifdef NETPLAY_STATISTICS #include "packet.h" struct NetStatistics { size_t packetsReceived; size_t packetTypeReceived[PACKET_NUM]; size_t packetsSent; size_t packetTypeSent[PACKET_NUM]; }; #endif #ifdef NETCONNECTION_INTERNAL #include "libs/net.h" #include "packetq.h" typedef struct { // For actions that require agreement by both parties. bool localOk : 1; /* Action confirmed by us */ bool remoteOk : 1; /* Action confirmed by the remote party */ bool canceling : 1; /* Awaiting cancel confirmation */ } HandShakeFlags; typedef struct { // For actions that do not require agreement, but for which it // only is relevant that both sides are ready. bool localReady : 1; bool remoteReady : 1; } ReadyFlags; typedef struct { bool localReset : 1; bool remoteReset : 1; } ResetFlags; // Which parameters have we both sides of a connection reached agreement on? typedef struct { bool randomSeed : 1; } Agreement; typedef struct { bool connected; /* This NetConnection is connected. */ bool disconnected; /* This NetConnection has been disconnected. This implies * !connected. It is only set if the NetConnection was once * connected, but is no longer. */ bool myTurn; /* This party is the only one who may send specific packets * at the moment. */ bool endingTurn; /* Request to change the turn from/to the other party. */ bool pendingTurnChange; /* It is our turn and the other party wants our turn, * but we're not ready to give it up just yet; we will first * send our pending packets. */ bool discriminant; /* If it is true here, it is false on the remote side * of the same connection. It may be used to break ties. * Unlike myTurn, this one is guaranteed not to change * during a connection. Undefined while not connected. */ HandShakeFlags handshake; ReadyFlags ready; ResetFlags reset; Agreement agreement; size_t inputDelay; /* Used during negotiation of the actual inputDelay. This * field does NOT necessarilly contain the actual input delay, * which is a property of the game, not of any specific * connection. Use getBattleInputDelay() to get at it. */ #ifdef NETPLAY_CHECKSUM size_t checksumInterval; #endif } NetStateFlags; struct NetConnection { NetDescriptor *nd; int player; // Number of the player for this connection, as it is // known locally. For the other player, it may be // differently. NetState state; NetStateFlags stateFlags; NetConnection_ReadyCallback readyCallback; // Called when both sides have indicated that they are ready. // Set by Netplay_localReady(). void *readyCallbackArg; // Extra argument for readyCallback(). // XXX: when is this cleaned up if a connection is broken? NetConnection_ResetCallback resetCallback; // Called when a reset has been signalled and confirmed. // Set by Netplay_localReset(). void *resetCallbackArg; // Extra argument for resetCallback(). // XXX: when is this cleaned up if a connection is broken? const NetplayPeerOptions *options; PacketQueue queue; #ifdef NETPLAY_STATISTICS NetStatistics statistics; #endif #ifdef NETPLAY_CHECKSUM ChecksumBuffer checksumBuffer; #endif NetConnection_ConnectCallback connectCallback; NetConnection_CloseCallback closeCallback; // Called when the NetConnection becomes disconnected. NetConnection_ErrorCallback errorCallback; NetConnection_DeleteCallback deleteCallback; // Called when the NetConnection is destroyed. uint8 *readBuf; uint8 *readEnd; NetConnectionStateData *stateData; // State dependant information. void *extra; }; struct ConnectStateData { NETCONNECTION_STATE_DATA_COMMON bool isServer; union { struct ConnectState *connectState; struct ListenState *listenState; } state; }; #endif /* NETCONNECTION_INTERNAL */ NetConnection *NetConnection_open(int player, const NetplayPeerOptions *options, NetConnection_ConnectCallback connectCallback, NetConnection_CloseCallback closeCallback, NetConnection_ErrorCallback errorCallback, NetConnection_DeleteCallback deleteCallback, void *extra); void NetConnection_close(NetConnection *conn); bool NetConnection_isConnected(const NetConnection *conn); void NetConnection_doErrorCallback(NetConnection *nd, int err); bool NetConnection_isMyTurn(const NetConnection *conn); void NetConnection_setStateData(NetConnection *conn, NetConnectionStateData *stateData); NetConnectionStateData *NetConnection_getStateData(const NetConnection *conn); void NetConnection_setExtra(NetConnection *conn, void *extra); void *NetConnection_getExtra(const NetConnection *conn); void NetConnection_setState(NetConnection *conn, NetState state); NetState NetConnection_getState(const NetConnection *conn); bool NetConnection_getDiscriminant(const NetConnection *conn); const NetplayPeerOptions *NetConnection_getPeerOptions( const NetConnection *conn); int NetConnection_getPlayerNr(const NetConnection *conn); size_t NetConnection_getInputDelay(const NetConnection *conn); #ifdef NETPLAY_CHECKSUM ChecksumBuffer *NetConnection_getChecksumBuffer(NetConnection *conn); size_t NetConnection_getChecksumInterval(const NetConnection *conn); #endif #ifdef NETPLAY_STATISTICS NetStatistics *NetConnection_getStatistics(NetConnection *conn); #endif void NetConnection_setReadyCallback(NetConnection *conn, NetConnection_ReadyCallback callback, void *arg); NetConnection_ReadyCallback NetConnection_getReadyCallback( const NetConnection *conn); void *NetConnection_getReadyCallbackArg(const NetConnection *conn); void NetConnection_setResetCallback(NetConnection *conn, NetConnection_ResetCallback callback, void *arg); NetConnection_ResetCallback NetConnection_getResetCallback( const NetConnection *conn); void *NetConnection_getResetCallbackArg(const NetConnection *conn); #endif /* _NETCONNECTION_H */ uqm-0.6.2/sc2/src/sc2code/netplay/notify.h0000600000175000017500000000340410543202057016743 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NOTIFY_H #define _NOTIFY_H #include "netplay.h" // for NETPLAY_CHECKSUM #include "netconnection.h" #include "controls.h" // for BATTLE_INPUT_STATE #ifdef NETPLAY_CHECKSUM # include "checksum.h" #endif void Netplay_selectShip(NetConnection *conn, uint16 index); void Netplay_battleInput(NetConnection *conn, BATTLE_INPUT_STATE input); void Netplay_teamStringChanged(NetConnection *conn, int player, const char *name, size_t len); void Netplay_entireFleetChanged(NetConnection *conn, int player, const BYTE *fleet, size_t fleetSize); void Netplay_fleetShipChanged(NetConnection *conn, int player, size_t index, BYTE ship); void Netplay_seedRandom(NetConnection *conn, uint32 seed); void Netplay_sendInputDelay(NetConnection *conn, uint32 delay); void Netplay_sendFrameCount(NetConnection *conn, BattleFrameCounter frameCount); #ifdef NETPLAY_CHECKSUM void Netplay_sendChecksum(NetConnection *conn, BattleFrameCounter frameCount, Checksum checksum); #endif #endif /* _NOTIFY_H */ uqm-0.6.2/sc2/src/sc2code/igfxres.h0000600000175000017500000003017710543202102015424 0ustar joeyjoey#define TITLE_ANIM 0x00400002L #define STATUS_MASK_PMAP_ANIM 0x03800102L #define ACTIVITY_ANIM 0x03800202L #define PLAYMENU_ANIM 0x03a00302L #define FLAGSTAT_MASK_PMAP_ANIM 0x03e00402L #define MISCDATA_MASK_PMAP_ANIM 0x03e00502L #define STAR_MASK_PMAP_ANIM 0x04400602L #define ASTEROID_BIG_MASK_PMAP_ANIM 0x04400702L #define ASTEROID_MED_MASK_PMAP_ANIM 0x04400802L #define ASTEROID_SML_MASK_PMAP_ANIM 0x04400902L #define BLAST_BIG_MASK_PMAP_ANIM 0x04400a02L #define BLAST_MED_MASK_PMAP_ANIM 0x04400b02L #define BLAST_SML_MASK_PMAP_ANIM 0x04400c02L #define BOOM_BIG_MASK_PMAP_ANIM 0x04400d02L #define BOOM_MED_MASK_PMAP_ANIM 0x04400e02L #define BOOM_SML_MASK_PMAP_ANIM 0x04400f02L #define AMBIENT_MASK_PMAP_ANIM 0x04601002L #define HYPERSTARS_MASK_PMAP_ANIM 0x04801102L #define ARISPACE_MASK_PMAP_ANIM 0x04a01202L #define IPBKGND_MASK_PMAP_ANIM 0x05001302L #define SISIP_MASK_PMAP_ANIM 0x05201402L #define ORBPLAN_MASK_PMAP_ANIM 0x05201502L #define SUN_MASK_PMAP_ANIM 0x05201602L #define LANDER_MASK_PMAP_ANIM 0x05401702L #define QUAKE_MASK_PMAP_ANIM 0x05401802L #define LIGHTNING_MASK_ANIM 0x05401902L #define LAVA_MASK_PMAP_ANIM 0x05401a02L #define LANDER_SHIELD_MASK_ANIM 0x05401b02L #define LANDER_LAUNCH_MASK_PMAP_ANIM 0x05401c02L #define LANDER_RETURN_MASK_PMAP_ANIM 0x05401d02L #define ORBIT_VIEW_ANIM 0x05601e02L #define EARTH_MASK_ANIM 0x05801f02L #define CANNISTER_MASK_PMAP_ANIM 0x05a02002L #define LIFE00_MASK_PMAP_ANIM 0x05c02102L #define LIFE01_MASK_PMAP_ANIM 0x05e02202L #define LIFE02_MASK_PMAP_ANIM 0x06002302L #define LIFE03_MASK_PMAP_ANIM 0x06202402L #define LIFE04_MASK_PMAP_ANIM 0x06402502L #define LIFE05_MASK_PMAP_ANIM 0x06602602L #define LIFE06_MASK_PMAP_ANIM 0x06802702L #define LIFE07_MASK_PMAP_ANIM 0x06a02802L #define LIFE08_MASK_PMAP_ANIM 0x06c02902L #define LIFE09_MASK_PMAP_ANIM 0x06e02a02L #define LIFE10_MASK_PMAP_ANIM 0x07002b02L #define LIFE11_MASK_PMAP_ANIM 0x07202c02L #define LIFE12_MASK_PMAP_ANIM 0x07402d02L #define LIFE13_MASK_PMAP_ANIM 0x07602e02L #define LIFE14_MASK_PMAP_ANIM 0x07802f02L #define LIFE15_MASK_PMAP_ANIM 0x07a03002L #define LIFE16_MASK_PMAP_ANIM 0x07c03102L #define LIFE17_MASK_PMAP_ANIM 0x07e03202L #define LIFE18_MASK_PMAP_ANIM 0x08003302L #define LIFE19_MASK_PMAP_ANIM 0x08203402L #define LIFE20_MASK_PMAP_ANIM 0x08403502L #define LIFE21_MASK_PMAP_ANIM 0x08603602L #define LIFE22_MASK_PMAP_ANIM 0x08803702L #define LIFE23_MASK_PMAP_ANIM 0x08a03802L #define LIFE24_MASK_PMAP_ANIM 0x08c03902L #define LIFE25_MASK_PMAP_ANIM 0x08e03a02L #define MOONBASE_MASK_PMAP_ANIM 0x11603b02L #define MAIDENS_MASK_PMAP_ANIM 0x11803c02L #define AQUA_MASK_PMAP_ANIM 0x11c03d02L #define BURV_BCS_MASK_PMAP_ANIM 0x11e03e02L #define TAALO_DEVICE_MASK_PMAP_ANIM 0x12003f02L #define SUN_DEVICE_MASK_PMAP_ANIM 0x12204002L #define VAULT_MASK_PMAP_ANIM 0x12404102L #define WRECK_MASK_PMAP_ANIM 0x12604202L #define BOMB_MASK_PMAP_ANIM 0x12804302L #define EGG_CASE_MASK_PMAP_ANIM 0x12c04402L #define SPAPLUTO_MASK_PMAP_ANIM 0x12e04502L #define RUINS_MASK_PMAP_ANIM 0x13804602L #define UMGAH_BCS_MASK_PMAP_ANIM 0x13c04702L #define MELEE_SCREEN_PMAP_ANIM 0x14204802L #define MELEE_PICK_MASK_PMAP_ANIM 0x14404902L #define SEGUE_PMAP_ANIM 0x14604a02L #define SC2_PICK_PMAP_ANIM 0x14804b02L #define RESTART_PMAP_ANIM 0x18204c02L #define MODULES_PMAP_ANIM 0x18404d02L #define SISMODS_MASK_PMAP_ANIM 0x18604e02L #define OUTFIT_PMAP_ANIM 0x18604f02L #define SISBLU_MASK_ANIM 0x18a05002L #define SHIPYARD_PMAP_ANIM 0x18a05102L #define STARBASE_ANIM 0x18e05202L #define SAMATRA_BIG_MASK_PMAP_ANIM 0x19005302L #define SHIELDED_BIG_MASK_PMAP_ANIM 0x19205402L #define SHIELDED_MED_MASK_PMAP_ANIM 0x19205502L #define SHIELDED_SML_MASK_PMAP_ANIM 0x19205602L #define PLANET00_BIG_MASK_PMAP_ANIM 0x19405702L #define PLANET00_MED_MASK_PMAP_ANIM 0x19405802L #define PLANET00_SML_MASK_PMAP_ANIM 0x19405902L #define PLANET01_BIG_MASK_PMAP_ANIM 0x19605a02L #define PLANET01_MED_MASK_PMAP_ANIM 0x19605b02L #define PLANET01_SML_MASK_PMAP_ANIM 0x19605c02L #define PLANET02_BIG_MASK_PMAP_ANIM 0x19805d02L #define PLANET02_MED_MASK_PMAP_ANIM 0x19805e02L #define PLANET02_SML_MASK_PMAP_ANIM 0x19805f02L #define PLANET03_BIG_MASK_PMAP_ANIM 0x19a06002L #define PLANET03_MED_MASK_PMAP_ANIM 0x19a06102L #define PLANET03_SML_MASK_PMAP_ANIM 0x19a06202L #define PLANET04_BIG_MASK_PMAP_ANIM 0x19c06302L #define PLANET04_MED_MASK_PMAP_ANIM 0x19c06402L #define PLANET04_SML_MASK_PMAP_ANIM 0x19c06502L #define PLANET05_BIG_MASK_PMAP_ANIM 0x19e06602L #define PLANET05_MED_MASK_PMAP_ANIM 0x19e06702L #define PLANET05_SML_MASK_PMAP_ANIM 0x19e06802L #define PLANET06_BIG_MASK_PMAP_ANIM 0x1a006902L #define PLANET06_MED_MASK_PMAP_ANIM 0x1a006a02L #define PLANET06_SML_MASK_PMAP_ANIM 0x1a006b02L #define PLANET07_BIG_MASK_PMAP_ANIM 0x1a206c02L #define PLANET07_MED_MASK_PMAP_ANIM 0x1a206d02L #define PLANET07_SML_MASK_PMAP_ANIM 0x1a206e02L #define PLANET08_BIG_MASK_PMAP_ANIM 0x1a406f02L #define PLANET08_MED_MASK_PMAP_ANIM 0x1a407002L #define PLANET08_SML_MASK_PMAP_ANIM 0x1a407102L #define PLANET09_BIG_MASK_PMAP_ANIM 0x1a607202L #define PLANET09_MED_MASK_PMAP_ANIM 0x1a607302L #define PLANET09_SML_MASK_PMAP_ANIM 0x1a607402L #define PLANET10_BIG_MASK_PMAP_ANIM 0x1a807502L #define PLANET10_MED_MASK_PMAP_ANIM 0x1a807602L #define PLANET10_SML_MASK_PMAP_ANIM 0x1a807702L #define PLANET11_BIG_MASK_PMAP_ANIM 0x1aa07802L #define PLANET11_MED_MASK_PMAP_ANIM 0x1aa07902L #define PLANET11_SML_MASK_PMAP_ANIM 0x1aa07a02L #define PLANET12_BIG_MASK_PMAP_ANIM 0x1ac07b02L #define PLANET12_MED_MASK_PMAP_ANIM 0x1ac07c02L #define PLANET12_SML_MASK_PMAP_ANIM 0x1ac07d02L #define PLANET13_BIG_MASK_PMAP_ANIM 0x1ae07e02L #define PLANET13_MED_MASK_PMAP_ANIM 0x1ae07f02L #define PLANET13_SML_MASK_PMAP_ANIM 0x1ae08002L #define PLANET14_BIG_MASK_PMAP_ANIM 0x1b008102L #define PLANET14_MED_MASK_PMAP_ANIM 0x1b008202L #define PLANET14_SML_MASK_PMAP_ANIM 0x1b008302L #define PLANET15_BIG_MASK_PMAP_ANIM 0x1b208402L #define PLANET15_MED_MASK_PMAP_ANIM 0x1b208502L #define PLANET15_SML_MASK_PMAP_ANIM 0x1b208602L #define PLANET16_BIG_MASK_PMAP_ANIM 0x1b408702L #define PLANET16_MED_MASK_PMAP_ANIM 0x1b408802L #define PLANET16_SML_MASK_PMAP_ANIM 0x1b408902L #define PLANET17_BIG_MASK_PMAP_ANIM 0x1b608a02L #define PLANET17_MED_MASK_PMAP_ANIM 0x1b608b02L #define PLANET17_SML_MASK_PMAP_ANIM 0x1b608c02L #define PLANET18_BIG_MASK_PMAP_ANIM 0x1b808d02L #define PLANET18_MED_MASK_PMAP_ANIM 0x1b808e02L #define PLANET18_SML_MASK_PMAP_ANIM 0x1b808f02L #define PLANET19_BIG_MASK_PMAP_ANIM 0x1ba09002L #define PLANET19_MED_MASK_PMAP_ANIM 0x1ba09102L #define PLANET19_SML_MASK_PMAP_ANIM 0x1ba09202L #define PLANET20_BIG_MASK_PMAP_ANIM 0x1bc09302L #define PLANET20_MED_MASK_PMAP_ANIM 0x1bc09402L #define PLANET20_SML_MASK_PMAP_ANIM 0x1bc09502L #define PLANET21_BIG_MASK_PMAP_ANIM 0x1be09602L #define PLANET21_MED_MASK_PMAP_ANIM 0x1be09702L #define PLANET21_SML_MASK_PMAP_ANIM 0x1be09802L #define PLANET22_BIG_MASK_PMAP_ANIM 0x1c009902L #define PLANET22_MED_MASK_PMAP_ANIM 0x1c009a02L #define PLANET22_SML_MASK_PMAP_ANIM 0x1c009b02L #define PLANET23_BIG_MASK_PMAP_ANIM 0x1c209c02L #define PLANET23_MED_MASK_PMAP_ANIM 0x1c209d02L #define PLANET23_SML_MASK_PMAP_ANIM 0x1c209e02L #define PLANET24_BIG_MASK_PMAP_ANIM 0x1c409f02L #define PLANET24_MED_MASK_PMAP_ANIM 0x1c40a002L #define PLANET24_SML_MASK_PMAP_ANIM 0x1c40a102L #define PLANET25_BIG_MASK_PMAP_ANIM 0x1c60a202L #define PLANET25_MED_MASK_PMAP_ANIM 0x1c60a302L #define PLANET25_SML_MASK_PMAP_ANIM 0x1c60a402L #define PLANET26_BIG_MASK_PMAP_ANIM 0x1c80a502L #define PLANET26_MED_MASK_PMAP_ANIM 0x1c80a602L #define PLANET26_SML_MASK_PMAP_ANIM 0x1c80a702L #define PLANET27_BIG_MASK_PMAP_ANIM 0x1ca0a802L #define PLANET27_MED_MASK_PMAP_ANIM 0x1ca0a902L #define PLANET27_SML_MASK_PMAP_ANIM 0x1ca0aa02L #define PLANET28_BIG_MASK_PMAP_ANIM 0x1cc0ab02L #define PLANET28_MED_MASK_PMAP_ANIM 0x1cc0ac02L #define PLANET28_SML_MASK_PMAP_ANIM 0x1cc0ad02L #define PLANET29_BIG_MASK_PMAP_ANIM 0x1ce0ae02L #define PLANET29_MED_MASK_PMAP_ANIM 0x1ce0af02L #define PLANET29_SML_MASK_PMAP_ANIM 0x1ce0b002L #define PLANET30_BIG_MASK_PMAP_ANIM 0x1d00b102L #define PLANET30_MED_MASK_PMAP_ANIM 0x1d00b202L #define PLANET30_SML_MASK_PMAP_ANIM 0x1d00b302L #define PLANET31_BIG_MASK_PMAP_ANIM 0x1d20b402L #define PLANET31_MED_MASK_PMAP_ANIM 0x1d20b502L #define PLANET31_SML_MASK_PMAP_ANIM 0x1d20b602L #define PLANET32_BIG_MASK_PMAP_ANIM 0x1d40b702L #define PLANET32_MED_MASK_PMAP_ANIM 0x1d40b802L #define PLANET32_SML_MASK_PMAP_ANIM 0x1d40b902L #define PLANET33_BIG_MASK_PMAP_ANIM 0x1d60ba02L #define PLANET33_MED_MASK_PMAP_ANIM 0x1d60bb02L #define PLANET33_SML_MASK_PMAP_ANIM 0x1d60bc02L #define PLANET34_BIG_MASK_PMAP_ANIM 0x1d80bd02L #define PLANET34_MED_MASK_PMAP_ANIM 0x1d80be02L #define PLANET34_SML_MASK_PMAP_ANIM 0x1d80bf02L #define PLANET35_BIG_MASK_PMAP_ANIM 0x1da0c002L #define PLANET35_MED_MASK_PMAP_ANIM 0x1da0c102L #define PLANET35_SML_MASK_PMAP_ANIM 0x1da0c202L #define PLANET36_BIG_MASK_PMAP_ANIM 0x1dc0c302L #define PLANET36_MED_MASK_PMAP_ANIM 0x1dc0c402L #define PLANET36_SML_MASK_PMAP_ANIM 0x1dc0c502L #define PLANET37_BIG_MASK_PMAP_ANIM 0x1de0c602L #define PLANET37_MED_MASK_PMAP_ANIM 0x1de0c702L #define PLANET37_SML_MASK_PMAP_ANIM 0x1de0c802L #define PLANET38_BIG_MASK_PMAP_ANIM 0x1e00c902L #define PLANET38_MED_MASK_PMAP_ANIM 0x1e00ca02L #define PLANET38_SML_MASK_PMAP_ANIM 0x1e00cb02L #define PLANET39_BIG_MASK_PMAP_ANIM 0x1e20cc02L #define PLANET39_MED_MASK_PMAP_ANIM 0x1e20cd02L #define PLANET39_SML_MASK_PMAP_ANIM 0x1e20ce02L #define PLANET40_BIG_MASK_PMAP_ANIM 0x1e40cf02L #define PLANET40_MED_MASK_PMAP_ANIM 0x1e40d002L #define PLANET40_SML_MASK_PMAP_ANIM 0x1e40d102L #define PLANET41_BIG_MASK_PMAP_ANIM 0x1e60d202L #define PLANET41_MED_MASK_PMAP_ANIM 0x1e60d302L #define PLANET41_SML_MASK_PMAP_ANIM 0x1e60d402L #define PLANET42_BIG_MASK_PMAP_ANIM 0x1e80d502L #define PLANET42_MED_MASK_PMAP_ANIM 0x1e80d602L #define PLANET42_SML_MASK_PMAP_ANIM 0x1e80d702L #define PLANET43_BIG_MASK_PMAP_ANIM 0x1ea0d802L #define PLANET43_MED_MASK_PMAP_ANIM 0x1ea0d902L #define PLANET43_SML_MASK_PMAP_ANIM 0x1ea0da02L #define PLANET44_BIG_MASK_PMAP_ANIM 0x1ec0db02L #define PLANET44_MED_MASK_PMAP_ANIM 0x1ec0dc02L #define PLANET44_SML_MASK_PMAP_ANIM 0x1ec0dd02L #define PLANET45_BIG_MASK_PMAP_ANIM 0x1ee0de02L #define PLANET45_MED_MASK_PMAP_ANIM 0x1ee0df02L #define PLANET45_SML_MASK_PMAP_ANIM 0x1ee0e002L #define PLANET46_BIG_MASK_PMAP_ANIM 0x1f00e102L #define PLANET46_MED_MASK_PMAP_ANIM 0x1f00e202L #define PLANET46_SML_MASK_PMAP_ANIM 0x1f00e302L #define PLANET47_BIG_MASK_PMAP_ANIM 0x1f20e402L #define PLANET47_MED_MASK_PMAP_ANIM 0x1f20e502L #define PLANET47_SML_MASK_PMAP_ANIM 0x1f20e602L #define PLANET48_BIG_MASK_PMAP_ANIM 0x1f40e702L #define PLANET48_MED_MASK_PMAP_ANIM 0x1f40e802L #define PLANET48_SML_MASK_PMAP_ANIM 0x1f40e902L #define PLANET49_BIG_MASK_PMAP_ANIM 0x1f60ea02L #define PLANET49_MED_MASK_PMAP_ANIM 0x1f60eb02L #define PLANET49_SML_MASK_PMAP_ANIM 0x1f60ec02L #define PLANET50_BIG_MASK_PMAP_ANIM 0x1f80ed02L #define PLANET50_MED_MASK_PMAP_ANIM 0x1f80ee02L #define PLANET50_SML_MASK_PMAP_ANIM 0x1f80ef02L #define PLANET51_BIG_MASK_PMAP_ANIM 0x1fa0f002L #define PLANET51_MED_MASK_PMAP_ANIM 0x1fa0f102L #define PLANET51_SML_MASK_PMAP_ANIM 0x1fa0f202L #define PLANET52_BIG_MASK_PMAP_ANIM 0x1fc0f302L #define PLANET52_MED_MASK_PMAP_ANIM 0x1fc0f402L #define PLANET52_SML_MASK_PMAP_ANIM 0x1fc0f502L #define PLANET53_BIG_MASK_PMAP_ANIM 0x1fe0f602L #define PLANET53_MED_MASK_PMAP_ANIM 0x1fe0f702L #define PLANET53_SML_MASK_PMAP_ANIM 0x1fe0f802L #define PLANET54_BIG_MASK_PMAP_ANIM 0x2000f902L #define PLANET54_MED_MASK_PMAP_ANIM 0x2000fa02L #define PLANET54_SML_MASK_PMAP_ANIM 0x2000fb02L #define PLANET55_BIG_MASK_PMAP_ANIM 0x2020fc02L #define PLANET55_MED_MASK_PMAP_ANIM 0x2020fd02L #define PLANET55_SML_MASK_PMAP_ANIM 0x2020fe02L #define PLANET56_BIG_MASK_PMAP_ANIM 0x2040ff02L #define PLANET56_MED_MASK_PMAP_ANIM 0x20410002L #define PLANET56_SML_MASK_PMAP_ANIM 0x20410102L #define PLANET57_BIG_MASK_PMAP_ANIM 0x20610202L #define PLANET57_MED_MASK_PMAP_ANIM 0x20610302L #define PLANET57_SML_MASK_PMAP_ANIM 0x20610402L #define PLANET58_BIG_MASK_PMAP_ANIM 0x20810502L #define PLANET58_MED_MASK_PMAP_ANIM 0x20810602L #define PLANET58_SML_MASK_PMAP_ANIM 0x20810702L #define CREDITS_BACK_ANIM 0x20c10802L #define SISSKEL_MASK_PMAP_ANIM 0x23611c02L #define ORBENTER_PMAP_ANIM 0x23811d02L #define MENUBKG_PMAP_ANIM 0x23a11e02L #define FONTGRAD_PMAP_ANIM 0x03e11f02L #define LANDER_FONTEFF_PMAP_ANIM 0x11412002L uqm-0.6.2/sc2/src/sc2code/gamestr.h0000600000175000017500000000657410543202102015423 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * This file contains definitions relating to using strings specific to * the game. libs/strlib.h is for the string library. */ #ifndef _GAMESTR_H #define _GAMESTR_H #include "libs/strlib.h" #define STAR_STRING_COUNT 133 #define DEVICE_STRING_COUNT 29 #define CARGO_STRING_COUNT 10 #define ELEMENTS_STRING_COUNT 133 #define SCAN_STRING_COUNT 56 #define STAR_NUMBER_COUNT 14 #define PLANET_NUMBER_COUNT 32 #define MONTHS_STRING_COUNT 12 #define FEEDBACK_STRING_COUNT 2 #define STARBASE_STRING_COUNT 5 #define ENCOUNTER_STRING_COUNT 8 #define NAVIGATION_STRING_COUNT 6 #define NAMING_STRING_COUNT 4 #define MELEE_STRING_COUNT 9 #define SAVEGAME_STRING_COUNT 5 #define OPTION_STRING_COUNT 5 #define QUITMENU_STRING_COUNT 5 #define STATUS_STRING_COUNT 6 #define FLAGSHIP_STRING_COUNT 13 #define ORBITSCAN_STRING_COUNT 19 #define MAINMENU_STRING_COUNT 57 #define NETMELEE_STRING_COUNT 18 enum { STAR_STRING_BASE = 0, DEVICE_STRING_BASE = STAR_STRING_BASE + STAR_STRING_COUNT, CARGO_STRING_BASE = DEVICE_STRING_BASE + DEVICE_STRING_COUNT, ELEMENTS_STRING_BASE = CARGO_STRING_BASE + CARGO_STRING_COUNT, SCAN_STRING_BASE = ELEMENTS_STRING_BASE + ELEMENTS_STRING_COUNT, STAR_NUMBER_BASE = SCAN_STRING_BASE + SCAN_STRING_COUNT, PLANET_NUMBER_BASE = STAR_NUMBER_BASE + STAR_NUMBER_COUNT, MONTHS_STRING_BASE = PLANET_NUMBER_BASE + PLANET_NUMBER_COUNT, FEEDBACK_STRING_BASE = MONTHS_STRING_BASE + MONTHS_STRING_COUNT, STARBASE_STRING_BASE = FEEDBACK_STRING_BASE + FEEDBACK_STRING_COUNT, ENCOUNTER_STRING_BASE = STARBASE_STRING_BASE + STARBASE_STRING_COUNT, NAVIGATION_STRING_BASE = ENCOUNTER_STRING_BASE + ENCOUNTER_STRING_COUNT, NAMING_STRING_BASE = NAVIGATION_STRING_BASE + NAVIGATION_STRING_COUNT, MELEE_STRING_BASE = NAMING_STRING_BASE + NAMING_STRING_COUNT, SAVEGAME_STRING_BASE = MELEE_STRING_BASE + MELEE_STRING_COUNT, OPTION_STRING_BASE = SAVEGAME_STRING_BASE + SAVEGAME_STRING_COUNT, QUITMENU_STRING_BASE = OPTION_STRING_BASE + OPTION_STRING_COUNT, STATUS_STRING_BASE = QUITMENU_STRING_BASE + QUITMENU_STRING_COUNT, FLAGSHIP_STRING_BASE = STATUS_STRING_BASE + STATUS_STRING_COUNT, ORBITSCAN_STRING_BASE = FLAGSHIP_STRING_BASE + FLAGSHIP_STRING_COUNT, MAINMENU_STRING_BASE = ORBITSCAN_STRING_BASE + ORBITSCAN_STRING_COUNT, NETMELEE_STRING_BASE = MAINMENU_STRING_BASE + MAINMENU_STRING_COUNT, GAMESTR_COUNT = NETMELEE_STRING_BASE + NETMELEE_STRING_COUNT }; #define GAME_STRING(i) ((UNICODE *)GetStringAddress (SetAbsStringTableIndex (GameStrings, (i)))) extern STRING GameStrings; #endif /* _GAMESTR_H */ uqm-0.6.2/sc2/src/sc2code/cyborg.c0000600000175000017500000010744510543202101015237 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "battle.h" #include "colors.h" #include "collide.h" #include "element.h" #include "globdata.h" #include "intel.h" #include "setup.h" #include "units.h" #include "libs/inplib.h" #include "libs/mathlib.h" #include "libs/log.h" //#define DEBUG_CYBORG COUNT PlotIntercept (ELEMENTPTR ElementPtr0, ELEMENTPTR ElementPtr1, COUNT max_turns, COUNT margin_of_error) { SIZE dy; SIZE time_y_0, time_y_1; POINT dst[2]; RECT r0, r1; SIZE dx_0, dy_0, dx_1, dy_1; if ((ElementPtr0->state_flags | ElementPtr1->state_flags) & FINITE_LIFE) { if (!(ElementPtr0->state_flags & FINITE_LIFE)) { if (ElementPtr1->life_span < max_turns) max_turns = ElementPtr1->life_span; } else if (!(ElementPtr1->state_flags & FINITE_LIFE)) { if (ElementPtr0->life_span < max_turns) max_turns = ElementPtr0->life_span; } else { if (ElementPtr0->life_span < max_turns) max_turns = ElementPtr0->life_span; if (ElementPtr1->life_span < max_turns) max_turns = ElementPtr1->life_span; } } dst[0] = ElementPtr0->current.location; GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx_0, &dy_0); dx_0 = (SIZE)VELOCITY_TO_WORLD ((long)dx_0 * (long)max_turns); dy_0 = (SIZE)VELOCITY_TO_WORLD ((long)dy_0 * (long)max_turns); dst[1] = ElementPtr1->current.location; GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx_1, &dy_1); dx_1 = (SIZE)VELOCITY_TO_WORLD ((long)dx_1 * (long)max_turns); dy_1 = (SIZE)VELOCITY_TO_WORLD ((long)dy_1 * (long)max_turns); if (margin_of_error) { dst[1].y -= margin_of_error; time_y_0 = 1; time_y_1 = margin_of_error << 1; } else { GetFrameRect ( ElementPtr0->IntersectControl.IntersectStamp.frame, &r0); GetFrameRect ( ElementPtr1->IntersectControl.IntersectStamp.frame, &r1); dst[0].y += DISPLAY_TO_WORLD (r0.corner.y); dst[1].y += DISPLAY_TO_WORLD (r1.corner.y); time_y_0 = DISPLAY_TO_WORLD (r0.extent.height); time_y_1 = DISPLAY_TO_WORLD (r1.extent.height); } dy = dst[1].y - dst[0].y; time_y_0 = dy - time_y_0 + 1; time_y_1 = dy + time_y_1 - 1; dy = dy_0 - dy_1; if ((time_y_0 <= 0 && time_y_1 >= 0) || (time_y_0 > 0 && dy >= time_y_0) || (time_y_1 < 0 && dy <= time_y_1)) { SIZE dx; SIZE time_x_0, time_x_1; if (margin_of_error) { dst[1].x -= margin_of_error; time_x_0 = 1; time_x_1 = margin_of_error << 1; } else { dst[0].x += DISPLAY_TO_WORLD (r0.corner.x); dst[1].x += DISPLAY_TO_WORLD (r1.corner.x); time_x_0 = DISPLAY_TO_WORLD (r0.extent.width); time_x_1 = DISPLAY_TO_WORLD (r1.extent.width); } dx = dst[1].x - dst[0].x; time_x_0 = dx - time_x_0 + 1; time_x_1 = dx + time_x_1 - 1; dx = dx_0 - dx_1; if ((time_x_0 <= 0 && time_x_1 >= 0) || (time_x_0 > 0 && dx >= time_x_0) || (time_x_1 < 0 && dx <= time_x_1)) { if (dx == 0 && dy == 0) time_y_0 = time_y_1 = 0; else { SIZE t; long time_beg, time_end, fract; if (time_y_1 < 0) { t = time_y_0; time_y_0 = -time_y_1; time_y_1 = -t; } else if (time_y_0 <= 0) { if (dy < 0) time_y_1 = -time_y_0; time_y_0 = 0; } if (dy < 0) dy = -dy; if (dy < time_y_1) time_y_1 = dy; if (time_x_1 < 0) { t = time_x_0; time_x_0 = -time_x_1; time_x_1 = -t; } else if (time_x_0 <= 0) { if (dx < 0) time_x_1 = -time_x_0; time_x_0 = 0; } if (dx < 0) dx = -dx; if (dx < time_x_1) time_x_1 = dx; if (dx == 0) { time_beg = time_y_0; time_end = time_y_1; fract = dy; } else if (dy == 0) { time_beg = time_x_0; time_end = time_x_1; fract = dx; } else { long time_x, time_y; time_x = (long)time_x_0 * (long)dy; time_y = (long)time_y_0 * (long)dx; time_beg = time_x < time_y ? time_y : time_x; time_x = (long)time_x_1 * (long)dy; time_y = (long)time_y_1 * (long)dx; time_end = time_x > time_y ? time_y : time_x; fract = (long)dx * (long)dy; } if ((time_beg *= max_turns) < fract) time_y_0 = 0; else time_y_0 = (SIZE)(time_beg / fract); if (time_end >= fract) /* just in case of overflow */ time_y_1 = max_turns - 1; else time_y_1 = (SIZE)((time_end * max_turns) / fract); } if (time_y_0 <= time_y_1) { if (margin_of_error != 0) return ((COUNT)time_y_0 + 1); else { POINT Pt0, Pt1; VELOCITY_DESC Velocity0, Velocity1; INTERSECT_CONTROL Control0, Control1; Pt0 = ElementPtr0->current.location; Velocity0 = ElementPtr0->velocity; Control0 = ElementPtr0->IntersectControl; Pt1 = ElementPtr1->current.location; Velocity1 = ElementPtr1->velocity; Control1 = ElementPtr1->IntersectControl; if (time_y_0) { GetNextVelocityComponents (&Velocity0, &dx_0, &dy_0, time_y_0); Pt0.x += dx_0; Pt0.y += dy_0; Control0.EndPoint.x = WORLD_TO_DISPLAY (Pt0.x); Control0.EndPoint.y = WORLD_TO_DISPLAY (Pt0.y); GetNextVelocityComponents (&Velocity1, &dx_1, &dy_1, time_y_0); Pt1.x += dx_1; Pt1.y += dy_1; Control1.EndPoint.x = WORLD_TO_DISPLAY (Pt1.x); Control1.EndPoint.y = WORLD_TO_DISPLAY (Pt1.y); } do { TIME_VALUE when; ++time_y_0; GetNextVelocityComponents (&Velocity0, &dx_0, &dy_0, 1); Pt0.x += dx_0; Pt0.y += dy_0; GetNextVelocityComponents (&Velocity1, &dx_1, &dy_1, 1); Pt1.x += dx_1; Pt1.y += dy_1; Control0.IntersectStamp.origin = Control0.EndPoint; Control0.EndPoint.x = WORLD_TO_DISPLAY (Pt0.x); Control0.EndPoint.y = WORLD_TO_DISPLAY (Pt0.y); Control1.IntersectStamp.origin = Control1.EndPoint; Control1.EndPoint.x = WORLD_TO_DISPLAY (Pt1.x); Control1.EndPoint.y = WORLD_TO_DISPLAY (Pt1.y); when = DrawablesIntersect (&Control0, &Control1, MAX_TIME_VALUE); if (when) { if (when == 1 && time_y_0 == 1 && ((ElementPtr0->state_flags | ElementPtr1->state_flags) & APPEARING)) { when = 0; Control0.EndPoint.x = WORLD_TO_DISPLAY (Pt0.x); Control0.EndPoint.y = WORLD_TO_DISPLAY (Pt0.y); Control1.EndPoint.x = WORLD_TO_DISPLAY (Pt1.x); Control1.EndPoint.y = WORLD_TO_DISPLAY (Pt1.y); } if (when) return ((COUNT)time_y_0); } } while (time_y_0 < time_y_1); } } } } return (0); } STARSHIPPTR CyborgDescPtr; static void InitCyborg (STARSHIPPTR StarShipPtr) { COUNT Index, Divisor; Index = StarShipPtr->RaceDescPtr->characteristics.max_thrust * StarShipPtr->RaceDescPtr->characteristics.thrust_increment; if ((Divisor = StarShipPtr->RaceDescPtr->characteristics.turn_wait + StarShipPtr->RaceDescPtr->characteristics.thrust_wait) > 0) Index /= Divisor; else Index >>= 1; #ifdef PRINT_MI { char buf[40]; GetStringContents (StarShipPtr->RaceDescPtr->ship_data.race_strings, buf, FALSE); log_add (log_Debug, "MI(%s) -- <%u:%u> = %u", buf, StarShipPtr->RaceDescPtr->characteristics.max_thrust * StarShipPtr->RaceDescPtr->characteristics.thrust_increment, Divisor, Index); } #endif /* PRINT_MI */ StarShipPtr->RaceDescPtr->cyborg_control.ManeuverabilityIndex = Index; } static void ship_movement (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr) { if (EvalDescPtr->which_turn == 0) EvalDescPtr->which_turn = 1; switch (EvalDescPtr->MoveState) { case PURSUE: Pursue (ShipPtr, EvalDescPtr); break; case AVOID: #ifdef NOTYET Avoid (ShipPtr, EvalDescPtr); break; #endif /* NOTYET */ case ENTICE: Entice (ShipPtr, EvalDescPtr); break; case NO_MOVEMENT: break; } } BOOLEAN ship_weapons (ELEMENTPTR ShipPtr, ELEMENTPTR OtherPtr, COUNT margin_of_error) { SIZE delta_x, delta_y; COUNT n, num_weapons; ELEMENT Ship; HELEMENT Weapon[6]; STARSHIPPTR StarShipPtr; if (OBJECT_CLOAKED (OtherPtr)) margin_of_error += DISPLAY_TO_WORLD (40); Ship = *ShipPtr; GetNextVelocityComponents (&Ship.velocity, &delta_x, &delta_y, 1); Ship.next.location.x = Ship.current.location.x + delta_x; Ship.next.location.y = Ship.current.location.y + delta_y; Ship.current.location = Ship.next.location; GetElementStarShip (&Ship, &StarShipPtr); num_weapons = (*StarShipPtr->RaceDescPtr->init_weapon_func) (&Ship, Weapon); if ((n = num_weapons)) { HELEMENT *WeaponPtr, w; //STARSHIPPTR StarShipPtr; ELEMENTPTR EPtr; WeaponPtr = &Weapon[0]; do { w = *WeaponPtr; if (w) { LockElement (w, &EPtr); if (EPtr->state_flags & APPEARING) { EPtr->next = EPtr->current; InitIntersectStartPoint (EPtr); InitIntersectEndPoint (EPtr); InitIntersectFrame (EPtr); } if (PlotIntercept (EPtr, OtherPtr, EPtr->life_span, margin_of_error)) { UnlockElement (w); break; } UnlockElement (w); FreeElement (w); } ++WeaponPtr; } while (--n); if ((num_weapons = n)) { do { w = *WeaponPtr++; if (w) FreeElement (w); } while (--n); } } return (num_weapons > 0); } void ship_intelligence (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR ObjectsOfConcern, COUNT ConcernCounter) { BOOLEAN ShipMoved, ShipFired; COUNT margin_of_error; STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); ShipMoved = TRUE; if (ShipPtr->turn_wait == 0) ShipMoved = FALSE; if (ShipPtr->thrust_wait == 0) ShipMoved = FALSE; ShipFired = TRUE; if (StarShipPtr->weapon_counter == 0) { StarShipPtr->ship_input_state &= ~WEAPON; if (!(StarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_WEAPON)) ShipFired = FALSE; } if (PlayerControl[cur_player] & AWESOME_RATING) margin_of_error = 0; else if (PlayerControl[cur_player] & GOOD_RATING) margin_of_error = DISPLAY_TO_WORLD (20); else /* if (PlayerControl[cur_player] & STANDARD_RATING) */ margin_of_error = DISPLAY_TO_WORLD (40); ObjectsOfConcern += ConcernCounter; while (ConcernCounter--) { --ObjectsOfConcern; if (ObjectsOfConcern->ObjectPtr) { if (!ShipMoved && (ConcernCounter != ENEMY_WEAPON_INDEX || ObjectsOfConcern->MoveState == PURSUE || (ObjectsOfConcern->ObjectPtr->state_flags & CREW_OBJECT) || MANEUVERABILITY ( &StarShipPtr->RaceDescPtr->cyborg_control ) >= MEDIUM_SHIP)) { ship_movement (ShipPtr, ObjectsOfConcern); ShipMoved = TRUE; } if (!ShipFired && (ConcernCounter == ENEMY_SHIP_INDEX || (ConcernCounter == ENEMY_WEAPON_INDEX && ObjectsOfConcern->MoveState != AVOID #ifdef NEVER && !(PlayerControl[cur_player] & STANDARD_RATING) #endif /* NEVER */ ))) { ShipFired = ship_weapons (ShipPtr, ObjectsOfConcern->ObjectPtr, margin_of_error); if (ShipFired) StarShipPtr->ship_input_state |= WEAPON; } } } } BOOLEAN TurnShip (ELEMENTPTR ShipPtr, COUNT angle) { COUNT f, ship_delta_facing; STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); f = StarShipPtr->ShipFacing; ship_delta_facing = NORMALIZE_FACING (ANGLE_TO_FACING (angle) - f); if (ship_delta_facing) { if (ship_delta_facing == ANGLE_TO_FACING (HALF_CIRCLE)) ship_delta_facing = NORMALIZE_FACING (ship_delta_facing + (TFB_Random () & 1 ? ANGLE_TO_FACING (OCTANT >> 1) : -ANGLE_TO_FACING (OCTANT >> 1))); if (ship_delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) { StarShipPtr->ship_input_state |= RIGHT; ++f; ShipPtr->next.image.frame = IncFrameIndex (ShipPtr->current.image.frame); } else { StarShipPtr->ship_input_state |= LEFT; --f; ShipPtr->next.image.frame = DecFrameIndex (ShipPtr->current.image.frame); } #ifdef NOTYET if (((StarShipPtr->ship_input_state & (LEFT | RIGHT)) ^ (StarShipPtr->cur_status_flags & (LEFT | RIGHT))) == (LEFT | RIGHT)) StarShipPtr->ship_input_state &= ~(LEFT | RIGHT); else #endif /* NOTYET */ { StarShipPtr->ShipFacing = NORMALIZE_FACING (f); return (TRUE); } } return (FALSE); } BOOLEAN ThrustShip (ELEMENTPTR ShipPtr, COUNT angle) { BOOLEAN ShouldThrust; STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->ship_input_state & THRUST) ShouldThrust = TRUE; else if (NORMALIZE_FACING (ANGLE_TO_FACING (angle) - ANGLE_TO_FACING (GetVelocityTravelAngle (&ShipPtr->velocity))) == 0 && (StarShipPtr->cur_status_flags & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) && !(StarShipPtr->cur_status_flags & SHIP_IN_GRAVITY_WELL)) ShouldThrust = FALSE; else { SIZE ship_delta_facing; ship_delta_facing = NORMALIZE_FACING (ANGLE_TO_FACING (angle) - StarShipPtr->ShipFacing + ANGLE_TO_FACING (QUADRANT)); if (ship_delta_facing == ANGLE_TO_FACING (QUADRANT) || ((StarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED) && ship_delta_facing <= ANGLE_TO_FACING (HALF_CIRCLE))) ShouldThrust = TRUE; else ShouldThrust = FALSE; } if (ShouldThrust) { inertial_thrust (ShipPtr); StarShipPtr->ship_input_state |= THRUST; } return (ShouldThrust); } void Pursue (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr) { INPUT_STATE maneuver_state; COUNT desired_thrust_angle, desired_turn_angle; SIZE delta_x, delta_y; SIZE ship_delta_x, ship_delta_y; SIZE other_delta_x, other_delta_y; ELEMENTPTR OtherObjPtr; VELOCITY_DESC ShipVelocity, OtherVelocity; ShipVelocity = ShipPtr->velocity; GetNextVelocityComponents (&ShipVelocity, &ship_delta_x, &ship_delta_y, EvalDescPtr->which_turn); ShipPtr->next.location.x = ShipPtr->current.location.x + ship_delta_x; ShipPtr->next.location.y = ShipPtr->current.location.y + ship_delta_y; OtherObjPtr = EvalDescPtr->ObjectPtr; OtherVelocity = OtherObjPtr->velocity; GetNextVelocityComponents (&OtherVelocity, &other_delta_x, &other_delta_y, EvalDescPtr->which_turn); delta_x = (OtherObjPtr->current.location.x + other_delta_x) - ShipPtr->next.location.x; delta_y = (OtherObjPtr->current.location.y + other_delta_y) - ShipPtr->next.location.y; delta_x = WRAP_DELTA_X (delta_x); delta_y = WRAP_DELTA_Y (delta_y); desired_thrust_angle = ARCTAN (delta_x, delta_y); maneuver_state = 0; if (ShipPtr->turn_wait == 0) maneuver_state |= LEFT | RIGHT; if (ShipPtr->thrust_wait == 0 && ((OtherObjPtr->state_flags & PLAYER_SHIP) || ((OtherObjPtr->state_flags & (GOOD_GUY | BAD_GUY)) == (ShipPtr->state_flags & (GOOD_GUY | BAD_GUY))) || OtherObjPtr->preprocess_func == crew_preprocess)) maneuver_state |= THRUST; desired_turn_angle = NORMALIZE_ANGLE (desired_thrust_angle + HALF_CIRCLE); /* other player's ship */ if ((OtherObjPtr->state_flags & PLAYER_SHIP) && OtherObjPtr->mass_points <= MAX_SHIP_MASS) { STARSHIPPTR StarShipPtr, EnemyStarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); GetElementStarShip (OtherObjPtr, &EnemyStarShipPtr); if ((MANEUVERABILITY ( &StarShipPtr->RaceDescPtr->cyborg_control ) >= FAST_SHIP && WEAPON_RANGE (&StarShipPtr->RaceDescPtr->cyborg_control) > CLOSE_RANGE_WEAPON) || (EvalDescPtr->which_turn >= 24 && (StarShipPtr->RaceDescPtr->characteristics.max_thrust * 2 / 3 < EnemyStarShipPtr->RaceDescPtr->characteristics.max_thrust || (EnemyStarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED)))) { UWORD ship_flags; ship_flags = EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags; /* you're maneuverable */ if (MANEUVERABILITY ( &StarShipPtr->RaceDescPtr->cyborg_control ) >= MEDIUM_SHIP) { UWORD fire_flags; COUNT facing; for (fire_flags = FIRES_FORE, facing = EvalDescPtr->facing; fire_flags <= FIRES_LEFT; fire_flags <<= 1, facing += QUADRANT) { if ( /* he's dangerous in this direction */ (ship_flags & fire_flags) /* he's facing direction you want to go */ && NORMALIZE_ANGLE ( desired_turn_angle - facing + OCTANT ) <= QUADRANT && ( /* he's moving */ (other_delta_x != 0 || other_delta_y != 0) && /* he's coasting backwards */ NORMALIZE_ANGLE ( (GetVelocityTravelAngle (&OtherVelocity) + HALF_CIRCLE) - facing + (OCTANT + (OCTANT >> 1))) <= ((OCTANT + (OCTANT >> 1)) << 1)) ) { /* catch him on the back side */ desired_thrust_angle = desired_turn_angle; break; } } } if (desired_thrust_angle != desired_turn_angle && (other_delta_x || other_delta_y) && EvalDescPtr->which_turn >= 24 && NORMALIZE_ANGLE (desired_thrust_angle - GetVelocityTravelAngle (&OtherVelocity) + OCTANT) <= QUADRANT && ((NORMALIZE_ANGLE ( GetVelocityTravelAngle (&OtherVelocity) - GetVelocityTravelAngle (&ShipVelocity) + OCTANT) <= QUADRANT && (((StarShipPtr->cur_status_flags & SHIP_AT_MAX_SPEED) && !(StarShipPtr->cur_status_flags & SHIP_BEYOND_MAX_SPEED)) || (ship_flags & DONT_CHASE))) || NORMALIZE_ANGLE ( desired_turn_angle - FACING_TO_ANGLE (StarShipPtr->ShipFacing) + OCTANT) <= QUADRANT)) desired_thrust_angle = desired_turn_angle; } } if (maneuver_state & (LEFT | RIGHT)) TurnShip (ShipPtr, desired_thrust_angle); if (maneuver_state & THRUST) ThrustShip (ShipPtr, desired_thrust_angle); } void Entice (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr) { INPUT_STATE maneuver_state; COUNT desired_thrust_angle, desired_turn_angle; COUNT cone_of_fire, travel_angle; SIZE delta_x, delta_y; SIZE ship_delta_x, ship_delta_y; SIZE other_delta_x, other_delta_y; ELEMENTPTR OtherObjPtr; VELOCITY_DESC ShipVelocity, OtherVelocity; STARSHIPPTR StarShipPtr; RACE_DESCPTR RDPtr; ShipVelocity = ShipPtr->velocity; GetNextVelocityComponents (&ShipVelocity, &ship_delta_x, &ship_delta_y, EvalDescPtr->which_turn); ShipPtr->next.location.x = ShipPtr->current.location.x + ship_delta_x; ShipPtr->next.location.y = ShipPtr->current.location.y + ship_delta_y; OtherObjPtr = (ELEMENTPTR)EvalDescPtr->ObjectPtr; OtherVelocity = OtherObjPtr->velocity; GetNextVelocityComponents (&OtherVelocity, &other_delta_x, &other_delta_y, EvalDescPtr->which_turn); delta_x = (OtherObjPtr->current.location.x + other_delta_x) - ShipPtr->next.location.x; delta_y = (OtherObjPtr->current.location.y + other_delta_y) - ShipPtr->next.location.y; delta_x = WRAP_DELTA_X (delta_x); delta_y = WRAP_DELTA_Y (delta_y); desired_thrust_angle = ARCTAN (delta_x, delta_y); maneuver_state = 0; if (ShipPtr->turn_wait == 0) maneuver_state |= LEFT | RIGHT; if (ShipPtr->thrust_wait == 0) maneuver_state |= THRUST; delta_x = ship_delta_x - other_delta_x; delta_y = ship_delta_y - other_delta_y; travel_angle = ARCTAN (delta_x, delta_y); desired_turn_angle = NORMALIZE_ANGLE (desired_thrust_angle + HALF_CIRCLE); GetElementStarShip (ShipPtr, &StarShipPtr); RDPtr = StarShipPtr->RaceDescPtr; if (EvalDescPtr->MoveState == AVOID) { desired_turn_angle = NORMALIZE_ANGLE (desired_turn_angle - EvalDescPtr->facing); if (NORMALIZE_FACING (ANGLE_TO_FACING (desired_turn_angle))) { if (desired_turn_angle <= HALF_CIRCLE) desired_thrust_angle = RIGHT; else /* if (desired_turn_angle > HALF_CIRCLE) */ desired_thrust_angle = LEFT; } else { desired_turn_angle = NORMALIZE_ANGLE ( FACING_TO_ANGLE (StarShipPtr->ShipFacing) - EvalDescPtr->facing ); if ((desired_turn_angle & (HALF_CIRCLE - 1)) == 0) desired_thrust_angle = TFB_Random () & 1 ? RIGHT : LEFT; else desired_thrust_angle = desired_turn_angle < HALF_CIRCLE ? RIGHT : LEFT; } if (desired_thrust_angle == LEFT) { #define FLANK_LEFT -QUADRANT #define SHIP_LEFT -OCTANT desired_thrust_angle = EvalDescPtr->facing + FLANK_LEFT - (SHIP_LEFT >> 1); } else { #define FLANK_RIGHT QUADRANT #define SHIP_RIGHT OCTANT desired_thrust_angle = EvalDescPtr->facing + FLANK_RIGHT - (SHIP_RIGHT >> 1); } desired_thrust_angle = NORMALIZE_ANGLE (desired_thrust_angle); } else if (GRAVITY_MASS (OtherObjPtr->mass_points)) { COUNT planet_facing; planet_facing = NORMALIZE_FACING (ANGLE_TO_FACING (desired_thrust_angle)); cone_of_fire = NORMALIZE_FACING ( planet_facing - StarShipPtr->ShipFacing + ANGLE_TO_FACING (QUADRANT)); if (RDPtr->characteristics.thrust_increment != RDPtr->characteristics.max_thrust) maneuver_state &= ~THRUST; /* if not pointing towards planet */ if (cone_of_fire > ANGLE_TO_FACING (QUADRANT << 1)) desired_turn_angle = desired_thrust_angle; /* if pointing directly at planet */ else if (cone_of_fire == ANGLE_TO_FACING (QUADRANT) && NORMALIZE_FACING (ANGLE_TO_FACING (travel_angle)) != planet_facing) desired_turn_angle = travel_angle; else if (cone_of_fire == 0 || cone_of_fire == ANGLE_TO_FACING (QUADRANT << 1) || (!(maneuver_state & THRUST) && (cone_of_fire < ANGLE_TO_FACING (OCTANT) || cone_of_fire > ANGLE_TO_FACING ((QUADRANT << 1) - OCTANT)))) { desired_turn_angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); if (NORMALIZE_ANGLE (desired_turn_angle - travel_angle + QUADRANT) > HALF_CIRCLE) desired_turn_angle = travel_angle; if (ShipPtr->thrust_wait == 0) maneuver_state |= THRUST; } desired_thrust_angle = desired_turn_angle; } else { COUNT WRange; WRange = WEAPON_RANGE ( &RDPtr->cyborg_control ); cone_of_fire = NORMALIZE_ANGLE (desired_turn_angle - EvalDescPtr->facing + OCTANT); if (OtherObjPtr->state_flags & PLAYER_SHIP) { UWORD fire_flags, ship_flags; COUNT facing; STARSHIPPTR EnemyStarShipPtr; GetElementStarShip (OtherObjPtr, &EnemyStarShipPtr); ship_flags = EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags; for (fire_flags = FIRES_FORE, facing = EvalDescPtr->facing; fire_flags <= FIRES_LEFT; fire_flags <<= 1, facing += QUADRANT) { if ( /* he's dangerous in this direction */ (ship_flags & fire_flags) /* he's facing direction you want to go */ && (cone_of_fire = NORMALIZE_ANGLE ( desired_turn_angle - facing + OCTANT )) <= QUADRANT /* he's moving */ && ((other_delta_x != 0 || other_delta_y != 0) /* he's coasting backwards */ && NORMALIZE_ANGLE ( (GetVelocityTravelAngle (&OtherVelocity) + HALF_CIRCLE) - facing + OCTANT) <= QUADRANT) ) { /* need to be close for a kill */ if (WRange < LONG_RANGE_WEAPON && EvalDescPtr->which_turn <= 32) { /* catch him on the back side */ desired_thrust_angle = desired_turn_angle; goto DoManeuver; } break; } } if (EvalDescPtr->which_turn <= 8 && RDPtr->characteristics.max_thrust <= EnemyStarShipPtr->RaceDescPtr->characteristics.max_thrust) goto DoManeuver; } if ( #ifdef NOTYET WRange < LONG_RANGE_WEAPON && #endif /* NOTYET */ /* not at full speed */ !(StarShipPtr->cur_status_flags & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) && (PlotIntercept ( ShipPtr, OtherObjPtr, 40, CLOSE_RANGE_WEAPON << 1 ) #ifdef NOTYET || ( /* object's facing direction you want to go */ cone_of_fire <= QUADRANT /* and you're basically going in that direction */ && (travel_angle == FULL_CIRCLE || NORMALIZE_ANGLE (travel_angle - desired_thrust_angle + QUADRANT) <= HALF_CIRCLE) /* and object's in range */ && PlotIntercept (ShipPtr, OtherObjPtr, 1, WRange) ) #endif /* NOTYET */ ) ) { if ( /* pointed straight at him */ NORMALIZE_ANGLE (desired_thrust_angle - FACING_TO_ANGLE (StarShipPtr->ShipFacing) + OCTANT) <= QUADRANT /* or not exposed to business end */ || cone_of_fire > QUADRANT ) { desired_thrust_angle = desired_turn_angle; } else { #ifdef NOTYET if ( travel_angle != FULL_CIRCLE && NORMALIZE_ANGLE (travel_angle - desired_turn_angle + OCTANT) <= QUADRANT ) { desired_turn_angle = NORMALIZE_ANGLE ((EvalDescPtr->facing + HALF_CIRCLE) + (travel_angle - desired_turn_angle)); if (!(maneuver_state & (LEFT | RIGHT))) maneuver_state &= ~THRUST; } if (maneuver_state & (LEFT | RIGHT)) { TurnShip (ShipPtr, desired_turn_angle); maneuver_state &= ~(LEFT | RIGHT); } #endif /* NOTYET */ desired_thrust_angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); desired_turn_angle = desired_thrust_angle; } } else if ((cone_of_fire = PlotIntercept ( ShipPtr, OtherObjPtr, 10, WRange #ifdef OLD - (WRange >> 3) #else /* !OLD */ - (WRange >> 2) #endif /* OLD */ ))) { if (RDPtr->characteristics.thrust_increment != RDPtr->characteristics.max_thrust /* and already at full speed */ && (StarShipPtr->cur_status_flags & (SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED)) /* and facing away from enemy */ && (NORMALIZE_ANGLE (desired_turn_angle - ARCTAN (ship_delta_x, ship_delta_y) + (OCTANT + 2)) <= ((OCTANT + 2) << 1) /* or not on collision course */ || !PlotIntercept ( ShipPtr, OtherObjPtr, 30, CLOSE_RANGE_WEAPON << 1 ))) maneuver_state &= ~THRUST; /* veer off */ else if (cone_of_fire == 1 || RDPtr->characteristics.thrust_increment != RDPtr->characteristics.max_thrust) { if (maneuver_state & (LEFT | RIGHT)) { TurnShip (ShipPtr, desired_turn_angle); maneuver_state &= ~(LEFT | RIGHT); } if (NORMALIZE_ANGLE (desired_thrust_angle - ARCTAN (ship_delta_x, ship_delta_y) + (OCTANT + 2)) <= ((OCTANT + 2) << 1)) desired_thrust_angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); else desired_thrust_angle = desired_turn_angle; } } } DoManeuver: if (maneuver_state & (LEFT | RIGHT)) TurnShip (ShipPtr, desired_thrust_angle); if (maneuver_state & THRUST) ThrustShip (ShipPtr, desired_thrust_angle); } void Avoid (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr) { (void) ShipPtr; /* Satisfying compiler (unused parameter) */ (void) EvalDescPtr; /* Satisfying compiler (unused parameter) */ } BATTLE_INPUT_STATE tactical_intelligence (COUNT player, STARSHIPPTR StarShipPtr) { ELEMENTPTR ShipPtr; ELEMENT Ship; COUNT ShipFacing; HELEMENT hElement, hNextElement; COUNT ConcernCounter; EVALUATE_DESC ObjectsOfConcern[10]; BOOLEAN ShipMoved, UltraManeuverable; STARSHIPPTR EnemyStarShipPtr; RACE_DESCPTR RDPtr, EnemyRDPtr; RDPtr = StarShipPtr->RaceDescPtr; if (RDPtr->cyborg_control.ManeuverabilityIndex == 0) InitCyborg (StarShipPtr); LockElement (StarShipPtr->hShip, &ShipPtr); if (RDPtr->ship_info.crew_level == 0 || GetPrimType (&DisplayArray[ShipPtr->PrimIndex]) == NO_PRIM) { UnlockElement (StarShipPtr->hShip); return (0); } ShipMoved = TRUE; if (PlayerControl[player] & STANDARD_RATING) ++StarShipPtr->special_counter; #ifdef DEBUG_CYBORG if (!(ShipPtr->state_flags & FINITE_LIFE) && ShipPtr->life_span == NORMAL_LIFE) ShipPtr->life_span += 2; /* make ship invulnerable */ #endif /* DEBUG_CYBORG */ Ship = *ShipPtr; UnlockElement (StarShipPtr->hShip); ShipFacing = StarShipPtr->ShipFacing; for (ConcernCounter = 0; ConcernCounter <= FIRST_EMPTY_INDEX; ++ConcernCounter) { ObjectsOfConcern[ConcernCounter].ObjectPtr = 0; ObjectsOfConcern[ConcernCounter].MoveState = NO_MOVEMENT; ObjectsOfConcern[ConcernCounter].which_turn = (COUNT)~0; } --ConcernCounter; UltraManeuverable = (BOOLEAN)( RDPtr->characteristics.thrust_increment == RDPtr->characteristics.max_thrust && MANEUVERABILITY (&RDPtr->cyborg_control) >= MEDIUM_SHIP ); if (Ship.turn_wait == 0) { ShipMoved = FALSE; StarShipPtr->ship_input_state &= ~(LEFT | RIGHT); } if (Ship.thrust_wait == 0) { ShipMoved = FALSE; StarShipPtr->ship_input_state &= ~THRUST; } for (hElement = GetHeadElement (); hElement != 0; hElement = hNextElement) { EVALUATE_DESC ed; LockElement (hElement, &ed.ObjectPtr); hNextElement = GetSuccElement (ed.ObjectPtr); if (CollisionPossible (ed.ObjectPtr, &Ship)) { SIZE dx, dy; dx = ed.ObjectPtr->next.location.x - Ship.next.location.x; dy = ed.ObjectPtr->next.location.y - Ship.next.location.y; dx = WRAP_DELTA_X (dx); dy = WRAP_DELTA_Y (dy); if (GRAVITY_MASS (ed.ObjectPtr->mass_points)) { COUNT maneuver_turn, ship_bounds; RECT ship_footprint; if (UltraManeuverable) maneuver_turn = 16; else if (MANEUVERABILITY (&RDPtr->cyborg_control) <= MEDIUM_SHIP) maneuver_turn = 48; else maneuver_turn = 32; GetFrameRect (SetAbsFrameIndex ( Ship.IntersectControl.IntersectStamp.frame, 0 ), &ship_footprint); ship_bounds = (COUNT)(ship_footprint.extent.width + ship_footprint.extent.height); if (!ShipMoved && (ed.which_turn = PlotIntercept (ed.ObjectPtr, &Ship, maneuver_turn, DISPLAY_TO_WORLD (30 + (ship_bounds * 3 /* << 2 */))))) { if (ed.which_turn > 1 || PlotIntercept (ed.ObjectPtr, &Ship, 1, DISPLAY_TO_WORLD (35 + ship_bounds)) || PlotIntercept (ed.ObjectPtr, &Ship, maneuver_turn << 1, DISPLAY_TO_WORLD (40 + ship_bounds)) > 1) { ed.facing = ARCTAN (-dx, -dy); if (UltraManeuverable) ed.MoveState = AVOID; else ed.MoveState = ENTICE; ObjectsOfConcern[GRAVITY_MASS_INDEX] = ed; } else if (!UltraManeuverable) { ++Ship.thrust_wait; if (Ship.turn_wait) ShipMoved = TRUE; } } } else if (ed.ObjectPtr->state_flags & PLAYER_SHIP) { GetElementStarShip (ed.ObjectPtr, &EnemyStarShipPtr); EnemyRDPtr = EnemyStarShipPtr->RaceDescPtr; if (EnemyRDPtr->cyborg_control.ManeuverabilityIndex == 0) InitCyborg (EnemyStarShipPtr); ed.which_turn = WORLD_TO_TURN ( square_root ((long)dx * dx + (long)dy * dy) ); if (ed.which_turn > ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn) { UnlockElement (hElement); continue; } else if (ed.which_turn == 0) ed.which_turn = 1; ObjectsOfConcern[ENEMY_SHIP_INDEX].ObjectPtr = ed.ObjectPtr; ObjectsOfConcern[ENEMY_SHIP_INDEX].facing = #ifdef MAYBE OBJECT_CLOAKED (ed.ObjectPtr) ? GetVelocityTravelAngle (&ed.ObjectPtr->velocity) : #endif /* MAYBE */ FACING_TO_ANGLE (EnemyStarShipPtr->ShipFacing); ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn = ed.which_turn; if (ShipMoved || ed.ObjectPtr->mass_points > MAX_SHIP_MASS || (WEAPON_RANGE (&RDPtr->cyborg_control) < LONG_RANGE_WEAPON && (WEAPON_RANGE (&RDPtr->cyborg_control) <= CLOSE_RANGE_WEAPON || (WEAPON_RANGE (&EnemyRDPtr->cyborg_control) >= LONG_RANGE_WEAPON && (EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & SEEKING_WEAPON)) || ( #ifdef OLD MANEUVERABILITY (&RDPtr->cyborg_control) < MANEUVERABILITY (&EnemyRDPtr->cyborg_control) #else /* !OLD */ RDPtr->characteristics.max_thrust < EnemyRDPtr->characteristics.max_thrust #endif /* !OLD */ && WEAPON_RANGE (&RDPtr->cyborg_control) < WEAPON_RANGE (&EnemyRDPtr->cyborg_control))))) ObjectsOfConcern[ENEMY_SHIP_INDEX].MoveState = PURSUE; else ObjectsOfConcern[ENEMY_SHIP_INDEX].MoveState = ENTICE; if ((EnemyStarShipPtr->RaceDescPtr->ship_info.ship_flags & IMMEDIATE_WEAPON) && ship_weapons (ed.ObjectPtr, &Ship, 0)) { ed.which_turn = 1; ed.MoveState = AVOID; ed.facing = ObjectsOfConcern[ENEMY_SHIP_INDEX].facing; ObjectsOfConcern[ENEMY_WEAPON_INDEX] = ed; } } else if (ed.ObjectPtr->pParent == 0) { if (!(ed.ObjectPtr->state_flags & FINITE_LIFE)) { ed.which_turn = WORLD_TO_TURN ( square_root ((long)dx * dx + (long)dy * dy) ); if (ed.which_turn < ObjectsOfConcern[FIRST_EMPTY_INDEX].which_turn) { ed.MoveState = PURSUE; ed.facing = GetVelocityTravelAngle ( &ed.ObjectPtr->velocity ); ObjectsOfConcern[FIRST_EMPTY_INDEX] = ed; } } } else if ((ed.ObjectPtr->state_flags & (GOOD_GUY | BAD_GUY)) != (Ship.state_flags & (GOOD_GUY | BAD_GUY)) && ed.ObjectPtr->preprocess_func != crew_preprocess && ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn > 1 && ed.ObjectPtr->life_span > 0) { GetElementStarShip (ed.ObjectPtr, &EnemyStarShipPtr); EnemyRDPtr = EnemyStarShipPtr->RaceDescPtr; if (((EnemyRDPtr->ship_info.ship_flags & SEEKING_WEAPON) && ed.ObjectPtr->next.image.farray != EnemyRDPtr->ship_data.special) || ((EnemyRDPtr->ship_info.ship_flags & SEEKING_SPECIAL) && ed.ObjectPtr->next.image.farray == EnemyRDPtr->ship_data.special)) { if ((!(ed.ObjectPtr->state_flags & (FINITE_LIFE | CREW_OBJECT)) && RDPtr->characteristics.max_thrust > DISPLAY_TO_WORLD (8)) || NORMALIZE_ANGLE (GetVelocityTravelAngle ( &ed.ObjectPtr->velocity ) - ARCTAN (-dx, -dy) + QUADRANT) > HALF_CIRCLE) ed.which_turn = 0; else { ed.which_turn = WORLD_TO_TURN ( square_root ((long)dx * dx + (long)dy * dy) ); ed.MoveState = ENTICE; if (UltraManeuverable) { if (ed.which_turn == 0) ed.which_turn = 1; else if (ed.which_turn > 16) ed.which_turn = 0; } else if (ed.which_turn == 0) ed.which_turn = 1; else if (ed.which_turn > 16 || (MANEUVERABILITY ( &RDPtr->cyborg_control ) > MEDIUM_SHIP && ed.which_turn > 8)) ed.which_turn = 0; } } else if (!(PlayerControl[player] & AWESOME_RATING)) ed.which_turn = 0; else { ed.which_turn = PlotIntercept (ed.ObjectPtr, &Ship, ed.ObjectPtr->life_span, DISPLAY_TO_WORLD (40)); ed.MoveState = AVOID; } if (ed.which_turn > 0 && (ed.which_turn < ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn || (ed.which_turn == ObjectsOfConcern[ENEMY_WEAPON_INDEX].which_turn && ed.MoveState == AVOID))) { ed.facing = GetVelocityTravelAngle ( &ed.ObjectPtr->velocity ); ObjectsOfConcern[ENEMY_WEAPON_INDEX] = ed; } } else if ((ed.ObjectPtr->state_flags & CREW_OBJECT) && ((!(ed.ObjectPtr->state_flags & IGNORE_SIMILAR) && (ed.ObjectPtr->state_flags & (GOOD_GUY | BAD_GUY)) == (Ship.state_flags & (GOOD_GUY | BAD_GUY))) || ed.ObjectPtr->preprocess_func == crew_preprocess) && ObjectsOfConcern[CREW_OBJECT_INDEX].which_turn > 1) { ed.which_turn = WORLD_TO_TURN ( square_root ((long)dx * dx + (long)dy * dy) ); if (ed.which_turn == 0) ed.which_turn = 1; if (ObjectsOfConcern[CREW_OBJECT_INDEX].which_turn > ed.which_turn && (ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn > 32 || (ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn > 8 && StarShipPtr->hShip == ed.ObjectPtr->hTarget))) { ed.MoveState = PURSUE; ed.facing = 0; ObjectsOfConcern[CREW_OBJECT_INDEX] = ed; } } } UnlockElement (hElement); } (*RDPtr->cyborg_control.intelligence_func) (&Ship, ObjectsOfConcern, ConcernCounter); #ifdef DEBUG_CYBORG StarShipPtr->ship_input_state &= ~SPECIAL; #endif /* DEBUG_CYBORG */ StarShipPtr->ShipFacing = ShipFacing; { BATTLE_INPUT_STATE InputState; InputState = 0; if (StarShipPtr->ship_input_state & LEFT) InputState |= BATTLE_LEFT; else if (StarShipPtr->ship_input_state & RIGHT) InputState |= BATTLE_RIGHT; if (StarShipPtr->ship_input_state & THRUST) InputState |= BATTLE_THRUST; if (StarShipPtr->ship_input_state & WEAPON) InputState |= BATTLE_WEAPON; if (StarShipPtr->ship_input_state & SPECIAL) InputState |= BATTLE_SPECIAL; return (InputState); } } uqm-0.6.2/sc2/src/sc2code/misc.c0000600000175000017500000002563410543202101014704 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "element.h" #include "init.h" #include "races.h" #include "setup.h" #include "sounds.h" #include "weapon.h" #include "libs/mathlib.h" void spawn_planet (void) { HELEMENT hPlanetElement; hPlanetElement = AllocElement (); if (hPlanetElement) { ELEMENTPTR PlanetElementPtr; extern FRAME planet[]; LockElement (hPlanetElement, &PlanetElementPtr); PlanetElementPtr->hit_points = 200; PlanetElementPtr->state_flags = APPEARING; PlanetElementPtr->life_span = NORMAL_LIFE + 1; SetPrimType (&DisplayArray[PlanetElementPtr->PrimIndex], STAMP_PRIM); PlanetElementPtr->current.image.farray = planet; PlanetElementPtr->current.image.frame = PlanetElementPtr->current.image.farray[0]; PlanetElementPtr->collision_func = collision; PlanetElementPtr->postprocess_func = (void (*) (struct element *ElementPtr))CalculateGravity; ZeroVelocityComponents (&PlanetElementPtr->velocity); do { PlanetElementPtr->current.location.x = WRAP_X (DISPLAY_ALIGN_X (TFB_Random ())); PlanetElementPtr->current.location.y = WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ())); } while (CalculateGravity (PlanetElementPtr) || TimeSpaceMatterConflict (PlanetElementPtr)); PlanetElementPtr->mass_points = PlanetElementPtr->hit_points; UnlockElement (hPlanetElement); PutElement (hPlanetElement); } } extern FRAME asteroid[]; static void spawn_rubble (PELEMENT AsteroidElementPtr) { HELEMENT hRubbleElement; hRubbleElement = AllocElement (); if (hRubbleElement) { ELEMENTPTR RubbleElementPtr; PutElement (hRubbleElement); LockElement (hRubbleElement, &RubbleElementPtr); RubbleElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; RubbleElementPtr->life_span = 5; RubbleElementPtr->turn_wait = RubbleElementPtr->next_turn = 0; SetPrimType (&DisplayArray[RubbleElementPtr->PrimIndex], STAMP_PRIM); RubbleElementPtr->current.image.farray = asteroid; RubbleElementPtr->current.image.frame = SetAbsFrameIndex (asteroid[0], ANGLE_TO_FACING (FULL_CIRCLE)); RubbleElementPtr->current.location = AsteroidElementPtr->current.location; RubbleElementPtr->preprocess_func = animation_preprocess; RubbleElementPtr->death_func = spawn_asteroid; UnlockElement (hRubbleElement); } } static void asteroid_preprocess (PELEMENT ElementPtr) { if (ElementPtr->turn_wait > 0) --ElementPtr->turn_wait; else { COUNT frame_index; frame_index = GetFrameIndex (ElementPtr->current.image.frame); if (ElementPtr->thrust_wait & (1 << 7)) --frame_index; else ++frame_index; ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, NORMALIZE_FACING (frame_index)); ElementPtr->state_flags |= CHANGING; ElementPtr->turn_wait = (unsigned char)(ElementPtr->thrust_wait & ((1 << 7) - 1)); } } void spawn_asteroid (PELEMENT ElementPtr) { HELEMENT hAsteroidElement; if ((hAsteroidElement = AllocElement ()) == 0) { if (ElementPtr != 0) { ElementPtr->state_flags &= ~DISAPPEARING; SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->life_span = 1; } } else { ELEMENTPTR AsteroidElementPtr; COUNT val; LockElement (hAsteroidElement, &AsteroidElementPtr); AsteroidElementPtr->hit_points = 1; AsteroidElementPtr->mass_points = 3; AsteroidElementPtr->state_flags = APPEARING; AsteroidElementPtr->life_span = NORMAL_LIFE; SetPrimType (&DisplayArray[AsteroidElementPtr->PrimIndex], STAMP_PRIM); if ((val = (COUNT)TFB_Random ()) & (1 << 0)) { if (!(val & (1 << 1))) AsteroidElementPtr->current.location.x = 0; else AsteroidElementPtr->current.location.x = LOG_SPACE_WIDTH; AsteroidElementPtr->current.location.y = WRAP_Y (DISPLAY_ALIGN_Y (TFB_Random ())); } else { AsteroidElementPtr->current.location.x = WRAP_X (DISPLAY_ALIGN_X (TFB_Random ())); if (!(val & (1 << 1))) AsteroidElementPtr->current.location.y = 0; else AsteroidElementPtr->current.location.y = LOG_SPACE_HEIGHT; } { // Using these temporary variables because the execution order // of function arguments may vary per system, which may break // synchronisation on network games. SIZE magnitude = DISPLAY_TO_WORLD (((SIZE)TFB_Random () & 7) + 4); COUNT facing = (COUNT)TFB_Random (); SetVelocityVector (&AsteroidElementPtr->velocity, magnitude, facing); } AsteroidElementPtr->current.image.farray = asteroid; AsteroidElementPtr->current.image.frame = SetAbsFrameIndex (asteroid[0], NORMALIZE_FACING (TFB_Random ())); AsteroidElementPtr->turn_wait = AsteroidElementPtr->thrust_wait = (BYTE)TFB_Random () & (BYTE)((1 << 2) - 1); AsteroidElementPtr->thrust_wait |= (BYTE)TFB_Random () & (BYTE)(1 << 7); AsteroidElementPtr->preprocess_func = asteroid_preprocess; AsteroidElementPtr->death_func = spawn_rubble; AsteroidElementPtr->collision_func = collision; UnlockElement (hAsteroidElement); PutElement (hAsteroidElement); } } void do_damage (ELEMENTPTR ElementPtr, SIZE damage) { if (ElementPtr->state_flags & PLAYER_SHIP) { if (!DeltaCrew (ElementPtr, -damage)) { ElementPtr->life_span = 0; ElementPtr->state_flags |= NONSOLID; } } else if (!GRAVITY_MASS (ElementPtr->mass_points)) { if ((BYTE)damage < ElementPtr->hit_points) ElementPtr->hit_points -= (BYTE)damage; else { ElementPtr->hit_points = 0; ElementPtr->life_span = 0; ElementPtr->state_flags |= NONSOLID; } } } void crew_preprocess (PELEMENT ElementPtr) { HELEMENT hTarget; SetPrimColor (&DisplayArray[ElementPtr->PrimIndex], GetPrimColor (&DisplayArray[ElementPtr->PrimIndex]) ^ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); ElementPtr->state_flags |= CHANGING; if ((hTarget = ElementPtr->hTarget) == 0) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); if (StarShipPtr && StarShipPtr->RaceDescPtr->ship_info.crew_level) ElementPtr->hTarget = StarShipPtr->hShip; else { COUNT facing; facing = 0; TrackShip ((ELEMENTPTR)ElementPtr, &facing); } } if (hTarget) { #define CREW_DELTA SCALED_ONE SIZE delta; ELEMENTPTR ShipPtr; LockElement (hTarget, &ShipPtr); delta = ShipPtr->current.location.x - ElementPtr->current.location.x; delta = WRAP_DELTA_X (delta); if (delta > 0) ElementPtr->next.location.x += CREW_DELTA; else if (delta < 0) ElementPtr->next.location.x -= CREW_DELTA; delta = ShipPtr->current.location.y - ElementPtr->current.location.y; delta = WRAP_DELTA_Y (delta); if (delta > 0) ElementPtr->next.location.y += CREW_DELTA; else if (delta < 0) ElementPtr->next.location.y -= CREW_DELTA; UnlockElement (hTarget); } } void crew_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if ((ElementPtr1->state_flags & PLAYER_SHIP) && ElementPtr1->life_span >= NORMAL_LIFE && ElementPtr0->hit_points > 0) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr1, &StarShipPtr); if (!(StarShipPtr->RaceDescPtr->ship_info.ship_flags & CREW_IMMUNE)) { ProcessSound (SetAbsSoundIndex (GameSounds, GRAB_CREW), ElementPtr1); DeltaCrew ((ELEMENTPTR)ElementPtr1, 1); } } ElementPtr0->hit_points = 0; ElementPtr0->life_span = 0; ElementPtr0->state_flags |= COLLISION | DISAPPEARING | NONSOLID; (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } void AbandonShip (ELEMENTPTR ShipPtr, ELEMENTPTR TargetPtr, COUNT crew_loss) { SIZE dx, dy; COUNT direction; RECT r; STARSHIPPTR StarShipPtr; HELEMENT hCrew; INTERSECT_CONTROL ShipIntersect; GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->RaceDescPtr->ship_info.ship_flags & CREW_IMMUNE) return; ShipIntersect = ShipPtr->IntersectControl; GetFrameRect (ShipIntersect.IntersectStamp.frame, &r); if ((direction = GetVelocityTravelAngle ( &ShipPtr->velocity)) == FULL_CIRCLE) dx = dy = 0; else { #define MORE_THAN_ENOUGH 100 direction += HALF_CIRCLE; dx = COSINE (direction, MORE_THAN_ENOUGH); dy = SINE (direction, MORE_THAN_ENOUGH); } while (crew_loss-- && (hCrew = AllocElement ())) { #define CREW_LIFE 300 ELEMENTPTR CrewPtr; DeltaCrew (ShipPtr, -1); PutElement (hCrew); LockElement (hCrew, &CrewPtr); CrewPtr->hit_points = 1; CrewPtr->state_flags = APPEARING | FINITE_LIFE | CREW_OBJECT; CrewPtr->life_span = CREW_LIFE; SetPrimType (&DisplayArray[CrewPtr->PrimIndex], POINT_PRIM); SetPrimColor (&DisplayArray[CrewPtr->PrimIndex], BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02)); CrewPtr->current.image.frame = DecFrameIndex (stars_in_space); CrewPtr->current.image.farray = &stars_in_space; CrewPtr->preprocess_func = crew_preprocess; CrewPtr->collision_func = crew_collision; SetElementStarShip (CrewPtr, StarShipPtr); GetElementStarShip (TargetPtr, &StarShipPtr); CrewPtr->hTarget = StarShipPtr->hShip; { SIZE w, h; INTERSECT_CONTROL CrewIntersect; ShipIntersect.IntersectStamp.origin = ShipPtr->IntersectControl.EndPoint; w = (SIZE)((COUNT)TFB_Random () % r.extent.width); h = (SIZE)((COUNT)TFB_Random () % r.extent.height); CrewIntersect.EndPoint = ShipIntersect.EndPoint; CrewIntersect.IntersectStamp.frame = DecFrameIndex (stars_in_space); if (dx == 0 && dy == 0) { CrewIntersect.EndPoint.x += w - (r.extent.width >> 1); CrewIntersect.EndPoint.y += h - (r.extent.height >> 1); CrewIntersect.IntersectStamp.origin = TargetPtr->IntersectControl.EndPoint; } else { if (dx == 0) CrewIntersect.EndPoint.x += w - (r.extent.width >> 1); else if (dx > 0) CrewIntersect.EndPoint.x += w; else CrewIntersect.EndPoint.x -= w; if (dy == 0) CrewIntersect.EndPoint.y += h - (r.extent.height >> 1); else if (dy > 0) CrewIntersect.EndPoint.y += h; else CrewIntersect.EndPoint.y -= h; CrewIntersect.IntersectStamp.origin.x = CrewIntersect.EndPoint.x + dx; CrewIntersect.IntersectStamp.origin.y = CrewIntersect.EndPoint.y + dy; } DrawablesIntersect (&CrewIntersect, &ShipIntersect, MAX_TIME_VALUE); CrewPtr->current.location.x = DISPLAY_TO_WORLD (CrewIntersect.EndPoint.x); CrewPtr->current.location.y = DISPLAY_TO_WORLD (CrewIntersect.EndPoint.y); } UnlockElement (hCrew); } } uqm-0.6.2/sc2/src/sc2code/galaxy.c0000600000175000017500000002326310543202103015234 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* background starfield - used to generate agalaxy.asm */ #include "element.h" #include "globdata.h" #include "init.h" #include "units.h" #include "options.h" #include "libs/compiler.h" #include "libs/gfxlib.h" #include "libs/graphics/gfx_common.h" #include "libs/mathlib.h" #include "libs/log.h" extern COUNT zoom_out; extern PRIM_LINKS DisplayLinks; #define BIG_STAR_COUNT 30 #define MED_STAR_COUNT 60 #define SML_STAR_COUNT 90 #define NUM_STARS (BIG_STAR_COUNT \ + MED_STAR_COUNT \ + SML_STAR_COUNT) POINT SpaceOrg; static POINT log_star_array[NUM_STARS]; #define NUM_STAR_PLANES 3 typedef struct { COUNT min_star_index, num_stars; PPOINT star_array; PPOINT pmin_star, plast_star; } STAR_BLOCK; typedef STAR_BLOCK *PSTAR_BLOCK; STAR_BLOCK StarBlock[NUM_STAR_PLANES] = { { 0, BIG_STAR_COUNT, &log_star_array[0], NULL, NULL, }, { 0, MED_STAR_COUNT, &log_star_array[BIG_STAR_COUNT], NULL, NULL, }, { 0, SML_STAR_COUNT, &log_star_array[BIG_STAR_COUNT + MED_STAR_COUNT], NULL, NULL, }, }; static void SortStarBlock (PSTAR_BLOCK pStarBlock) { COUNT i; for (i = 0; i < pStarBlock->num_stars; ++i) { COUNT j; for (j = pStarBlock->num_stars - 1; j > i; --j) { if (pStarBlock->star_array[i].y > pStarBlock->star_array[j].y) { POINT temp; temp = pStarBlock->star_array[i]; pStarBlock->star_array[i] = pStarBlock->star_array[j]; pStarBlock->star_array[j] = temp; } } } pStarBlock->min_star_index = 0; pStarBlock->pmin_star = &pStarBlock->star_array[0]; pStarBlock->plast_star = &pStarBlock->star_array[pStarBlock->num_stars - 1]; } static void WrapStarBlock (SIZE plane, SIZE dx, SIZE dy) { COUNT i; PPOINT ppt; SIZE offs_y; COUNT num_stars; PSTAR_BLOCK pStarBlock; pStarBlock = &StarBlock[plane]; i = pStarBlock->min_star_index; ppt = pStarBlock->pmin_star; num_stars = pStarBlock->num_stars; if (dy < 0) { COUNT first; first = i; dy = -dy; offs_y = (LOG_SPACE_HEIGHT << plane) - dy; while (ppt->y < dy) { ppt->y += offs_y; ppt->x += dx; if (++i < num_stars) ++ppt; else { i = 0; ppt = &pStarBlock->star_array[0]; } if (i == first) return; } pStarBlock->min_star_index = i; pStarBlock->pmin_star = ppt; if (first <= i) { i = num_stars - i; do { ppt->y -= dy; ppt->x += dx; ++ppt; } while (--i); ppt = &pStarBlock->star_array[0]; } if (first > i) { i = first - i; do { ppt->y -= dy; ppt->x += dx; ++ppt; } while (--i); } } else { COUNT last; --ppt; if (i-- == 0) { i = num_stars - 1; ppt = pStarBlock->plast_star; } last = i; if (dy > 0) { offs_y = (LOG_SPACE_HEIGHT << plane) - dy; while (ppt->y >= offs_y) { ppt->y -= offs_y; ppt->x += dx; if (i-- > 0) --ppt; else { i = num_stars - 1; ppt = pStarBlock->plast_star; } if (i == last) return; } pStarBlock->pmin_star = ppt + 1; if ((pStarBlock->min_star_index = i + 1) == num_stars) { pStarBlock->min_star_index = 0; pStarBlock->pmin_star = &pStarBlock->star_array[0]; } } if (last >= i) { ++i; do { ppt->y += dy; ppt->x += dx; --ppt; } while (--i); i = num_stars - 1; ppt = pStarBlock->plast_star; } if (last < i) { i = i - last; do { ppt->y += dy; ppt->x += dx; --ppt; } while (--i); } } } void InitGalaxy (void) { COUNT i, factor; PPOINT ppt; PRIM_LINKS Links; log_add (log_Debug, "InitGalaxy(): transition_width = %d, " "transition_height = %d", TRANSITION_WIDTH, TRANSITION_HEIGHT); Links = MakeLinks (END_OF_LIST, END_OF_LIST); factor = ONE_SHIFT + MAX_REDUCTION + (BACKGROUND_SHIFT - 3); for (i = 0, ppt = log_star_array; i < NUM_STARS; ++i, ++ppt) { COUNT p; p = AllocDisplayPrim (); if (i == BIG_STAR_COUNT || i == BIG_STAR_COUNT + MED_STAR_COUNT) ++factor; ppt->x = (COORD)((UWORD)TFB_Random () % SPACE_WIDTH) << factor; ppt->y = (COORD)((UWORD)TFB_Random () % SPACE_HEIGHT) << factor; if (i < BIG_STAR_COUNT + MED_STAR_COUNT) { SetPrimType (&DisplayArray[p], STAMP_PRIM); SetPrimColor (&DisplayArray[p], BUILD_COLOR (MAKE_RGB15 (0x0B, 0x0B, 0x1F), 0x09)); DisplayArray[p].Object.Stamp.frame = stars_in_space; } else { SetPrimType (&DisplayArray[p], POINT_PRIM); if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) SetPrimColor (&DisplayArray[p], BUILD_COLOR (MAKE_RGB15 (0x15, 0x15, 0x15), 0x07)); else if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) SetPrimColor (&DisplayArray[p], BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x8C)); else SetPrimColor (&DisplayArray[p], BUILD_COLOR (MAKE_RGB15 (0x00, 0x0E, 0x00), 0x8C)); } InsertPrim (&Links, p, GetPredLink (Links)); } SortStarBlock (&StarBlock[0]); SortStarBlock (&StarBlock[1]); SortStarBlock (&StarBlock[2]); } static BOOLEAN CmpMovePoints (const PPOINT pt1, const PPOINT pt2, SIZE dx, SIZE dy, SIZE reduction) { if (optMeleeScale == TFB_SCALE_STEP) { return (int)pt1->x != (int)((pt2->x - dx) >> reduction) || (int)pt1->y != (int)((pt2->y - dy) >> reduction); } else { return (int)pt1->x != (int)(((pt2->x - dx) << ZOOM_SHIFT) / reduction) || (int)pt1->y != (int)(((pt2->y - dy) << ZOOM_SHIFT) / reduction); } } void MoveGalaxy (VIEW_STATE view_state, SIZE dx, SIZE dy) { PPRIMITIVE pprim; static const COUNT star_counts[] = { BIG_STAR_COUNT, MED_STAR_COUNT, SML_STAR_COUNT }; static const COUNT star_frame_ofs[] = { 32 + 26, 26, 0 }; if (view_state != VIEW_STABLE) { COUNT reduction; COUNT i; COUNT iss; PPOINT ppt; int wrap_around; reduction = zoom_out; if (view_state == VIEW_CHANGE) { if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { for (iss = 0, pprim = DisplayArray; iss < 2; ++iss) { for (i = star_counts[iss]; i > 0; --i, ++pprim) { pprim->Object.Stamp.frame = SetAbsFrameIndex ( stars_in_space, (COUNT)(TFB_Random () & 31) + star_frame_ofs[iss]); } } } else { GRAPHICS_PRIM star_object[2]; FRAME star_frame[2]; star_frame[0] = IncFrameIndex (stars_in_space); star_frame[1] = stars_in_space; if (optMeleeScale == TFB_SCALE_STEP) { /* on PC, the closest stars are images when zoomed out */ star_object[0] = STAMP_PRIM; if (reduction > 0) { star_object[1] = POINT_PRIM; star_frame[0] = star_frame[1]; } else { star_object[1] = STAMP_PRIM; } } else { /* on 3DO, the closest stars are pixels when zoomed out */ star_object[1] = POINT_PRIM; if (reduction > (1 << ZOOM_SHIFT)) { star_object[0] = POINT_PRIM; } else { star_object[0] = STAMP_PRIM; } } for (iss = 0, pprim = DisplayArray; iss < 2; ++iss) { for (i = star_counts[iss]; i > 0; --i, ++pprim) { SetPrimType (pprim, star_object[iss]); pprim->Object.Stamp.frame = star_frame[iss]; } } } } if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { for (i = BIG_STAR_COUNT + MED_STAR_COUNT, pprim = DisplayArray; i > 0; --i, ++pprim) { COUNT base_index; base_index = GetFrameIndex (pprim->Object.Stamp.frame) - 26; pprim->Object.Stamp.frame = SetAbsFrameIndex (pprim->Object.Stamp.frame, ((base_index & ~31) + ((base_index + 1) & 31)) + 26); } dx <<= 3; dy <<= 3; } WrapStarBlock (2, dx, dy); WrapStarBlock (1, dx, dy); WrapStarBlock (0, dx, dy); if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) { dx = SpaceOrg.x; dy = SpaceOrg.y; if (optMeleeScale == TFB_SCALE_STEP) reduction += ONE_SHIFT; else reduction <<= ONE_SHIFT; } else { dx = (COORD)(LOG_SPACE_WIDTH >> 1) - (LOG_SPACE_WIDTH >> ((MAX_REDUCTION + 1) - MAX_VIS_REDUCTION)); dy = (COORD)(LOG_SPACE_HEIGHT >> 1) - (LOG_SPACE_HEIGHT >> ((MAX_REDUCTION + 1) - MAX_VIS_REDUCTION)); if (optMeleeScale == TFB_SCALE_STEP) reduction = MAX_VIS_REDUCTION + ONE_SHIFT; else reduction = MAX_ZOOM_OUT << ONE_SHIFT; } ppt = log_star_array; for (iss = 0, pprim = DisplayArray, wrap_around = LOG_SPACE_WIDTH; iss < 3 && (view_state == VIEW_CHANGE || CmpMovePoints ( &pprim->Object.Point, ppt, dx, dy, reduction)); ++iss, wrap_around <<= 1, dx <<= 1, dy <<= 1) { for (i = star_counts[iss]; i > 0; --i, ++pprim, ++ppt) { // ppt->x &= (LOG_SPACE_WIDTH - 1); ppt->x = WRAP_VAL (ppt->x, wrap_around); if (optMeleeScale == TFB_SCALE_STEP) { pprim->Object.Point.x = (ppt->x - dx) >> reduction; pprim->Object.Point.y = (ppt->y - dy) >> reduction; } else { pprim->Object.Point.x = ((ppt->x - dx) << ZOOM_SHIFT) / reduction; pprim->Object.Point.y = ((ppt->y - dy) << ZOOM_SHIFT) / reduction; } } if (optMeleeScale == TFB_SCALE_STEP) ++reduction; else reduction <<= 1; } } DisplayLinks = MakeLinks (NUM_STARS - 1, 0); } uqm-0.6.2/sc2/src/sc2code/tactrans.c0000600000175000017500000006010710543202103015564 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "collide.h" #include "globdata.h" #include "init.h" #ifdef NETPLAY # include "netplay/netmelee.h" # include "netplay/netmisc.h" # include "netplay/notify.h" # include "netplay/proto/ready.h" # include "netplay/packet.h" # include "netplay/packetq.h" #endif #include "races.h" #include "settings.h" #include "sounds.h" #include "libs/mathlib.h" BOOLEAN OpponentAlive (STARSHIPPTR TestStarShipPtr) { HELEMENT hElement, hSuccElement; for (hElement = GetHeadElement (); hElement; hElement = hSuccElement) { ELEMENTPTR ElementPtr; STARSHIPPTR StarShipPtr; LockElement (hElement, &ElementPtr); hSuccElement = GetSuccElement (ElementPtr); GetElementStarShip (ElementPtr, &StarShipPtr); UnlockElement (hElement); if (StarShipPtr && StarShipPtr != TestStarShipPtr && StarShipPtr->RaceDescPtr->ship_info.crew_level == 0) return FALSE; } return TRUE; } #ifdef NETPLAY static void readyToEnd2Callback (NetConnection *conn, void *arg) { NetConnection_setState (conn, NetState_endingBattle2); (void) arg; } static void readyToEndCallback (NetConnection *conn, void *arg) { // This callback function gets called from inside the function that // updates the frame counter, but this is not a problem as the // ending frame count will at least be 1 greater than the current // frame count. BattleStateData *battleStateData; battleStateData = (BattleStateData *) NetConnection_getStateData(conn); #ifdef NETPLAY_DEBUG fprintf (stderr, "Both sides are ready to end the battle; starting " "end-of-battle synchronisation.\n"); #endif NetConnection_setState (conn, NetState_endingBattle); if (battleFrameCount + 1 > battleStateData->endFrameCount) battleStateData->endFrameCount = battleFrameCount + 1; Netplay_sendFrameCount (conn, battleFrameCount + 1); // The +1 is to ensure that after the remote side receives the // frame count it will still receive one more frame data packet, // so it will know in advance when the last frame data packet // will come so it won't block. It also ensures that the // local frame counter won't go past the sent number, which // could happen when the function triggering the call to this // function is the frame update function which might update // the frame counter one more time. flushPacketQueue (conn); #ifdef NETPLAY_DEBUG fprintf (stderr, "NETPLAY: [%d] ==> Sent battleFrameCount %d.\n", NetConnection_getPlayerNr(conn), battleFrameCount + 1); #endif Netplay_localReady(conn, readyToEnd2Callback, NULL, false); (void) arg; } /* * When one player's ship dies, there's a delay before the next ship * can be chosen. This time depends on the time the ditty is playing * and may differ for each side. * To synchronise the time, the following protocol is followed: * 1. (NetState_inBattle) The Ready protocol is used to let either * party know when they're ready to stop the battle. * 2. (NetState_endingBattle) Each party sends the frame number of when * it wants to end the battle, and continues until that point, where * it waits until it has received the frame number of the other party. * 3. After a player has both sent and received a frame count, the * simulation continues for each party, until the maximum of both * frame counts has been achieved. * 4. The Ready protocol is used to let each side signal that the it has * reached the target frame count. * 5. The battle ends. */ static bool readyForBattleEndPlayer (NetConnection *conn, void *arg) { BattleStateData *battleStateData; battleStateData = (BattleStateData *) NetConnection_getStateData(conn); if (NetConnection_getState (conn) == NetState_interBattle || NetConnection_getState (conn) == NetState_endMelee) { // This connection is already ready. The entire synchronisation // protocol has already been done for this connection. return true; } if (NetConnection_getState (conn) == NetState_inBattle) { if (Netplay_isLocalReady(conn)) { // We've already sent notice that we are ready, but we're // still waiting for the other side to say it's ready too. return false; } // We haven't yet told the other side we're ready. We do so now. Netplay_localReady (conn, readyToEndCallback, NULL, true); // This may set the state to endingBattle. if (NetConnection_getState (conn) == NetState_inBattle) return false; } assert (NetConnection_getState (conn) == NetState_endingBattle || NetConnection_getState (conn) == NetState_endingBattle2); // Keep the simulation going as long as the target frame count // hasn't been reached yet. Note that if the connection state is // NetState_endingBattle, that we haven't yet received the // remote frame count, so the target frame count may still rise. if (battleFrameCount < battleStateData->endFrameCount) return false; if (NetConnection_getState (conn) == NetState_endingBattle) { // We have reached the target frame count, but we don't know // the remote target frame count yet. So we wait until it has // come in. waitReady (conn); // TODO: check whether all connections are still connected. assert (NetConnection_getState (conn) == NetState_endingBattle2); // Continue the simulation if the battleFrameCount has gone up. if (battleFrameCount < battleStateData->endFrameCount) return false; } // We are ready and wait for the other party to become ready too. negotiateReady (conn, true, NetState_interBattle); (void) arg; return true; } #endif // Returns true iff this side is ready to end the battle. static inline bool readyForBattleEnd (COUNT side) { #ifndef NETPLAY #if DEMO_MODE // In Demo mode, the saved journal should be replayed with frame // accuracy. PLRPlaying () isn't consistent enough. return true; #else /* !DEMO_MODE */ return !PLRPlaying ((MUSIC_REF)~0); #endif /* !DEMO_MODE */ #else /* defined (NETPLAY) */ if (PLRPlaying ((MUSIC_REF)~0)) return false; // We can only handle one dead ship at a time. So 'deadSide' is set // to the side we're handling now. (COUNT)~0 means we're not handling // any side yet. if (currentDeadSide == (COUNT)~0) { // Not handling any side yet. currentDeadSide = side; } else if (side != currentDeadSide) { // We're handing another side at the moment. return false; } if (!forAllConnectedPlayers (readyForBattleEndPlayer, NULL)) return false; currentDeadSide = (COUNT)~0; // Another side may be handled. return true; #endif /* defined (NETPLAY) */ } void new_ship (PELEMENT DeadShipPtr) { STARSHIPPTR DeadStarShipPtr; ProcessSound ((SOUND)~0, NULL); GetElementStarShip (DeadShipPtr, &DeadStarShipPtr); if (!(DeadShipPtr->state_flags & PLAYER_SHIP)) { if (DeadShipPtr->life_span) /* must be pre-processing */ return; } else { BOOLEAN MusicStarted; HELEMENT hElement, hSuccElement; DeadStarShipPtr->ShipFacing = DeadStarShipPtr->RaceDescPtr->ship_info.var2; DeadStarShipPtr->special_counter = DeadStarShipPtr->RaceDescPtr->ship_info.crew_level; if (DeadStarShipPtr->special_counter) { // We've just warped out. new_ship() will still be called // a few times, to process the trace left behind (I assume). StopMusic (); // Even after much investigation, I could find no purpose for // the next line, but with the crew management changes I need // it not to be here. - SvdB // DeadStarShipPtr->RaceDescPtr->ship_info.crew_level = 0; } MusicStarted = FALSE; DeadShipPtr->turn_wait = (BYTE)( DeadShipPtr->state_flags & (GOOD_GUY | BAD_GUY)); // DeadShipPtr->turn_wait is abused to store which // side this element is for, because this information // will be lost from state_flags when the element is // set up for deletion below. for (hElement = GetHeadElement (); hElement; hElement = hSuccElement) { ELEMENTPTR ElementPtr; STARSHIPPTR StarShipPtr; LockElement (hElement, &ElementPtr); hSuccElement = GetSuccElement (ElementPtr); GetElementStarShip (ElementPtr, &StarShipPtr); // Get the STARSHIP that this ELEMENT belongs to. if (StarShipPtr == DeadStarShipPtr) { // This element belongs to the dead ship; it may be the // ship's own element. SetElementStarShip (ElementPtr, 0); if (!(ElementPtr->state_flags & CREW_OBJECT) || ElementPtr->preprocess_func != crew_preprocess) { // Set the element up for deletion. SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->life_span = 0; ElementPtr->state_flags = NONSOLID | DISAPPEARING | FINITE_LIFE; ElementPtr->preprocess_func = 0; ElementPtr->postprocess_func = 0; ElementPtr->death_func = 0; ElementPtr->collision_func = 0; } } if (StarShipPtr && (StarShipPtr->cur_status_flags & PLAY_VICTORY_DITTY)) { // StarShipPtr points to the surviving ship. MusicStarted = TRUE; PlayMusic ((MUSIC_REF)StarShipPtr->RaceDescPtr-> ship_data.victory_ditty, FALSE, 3); StarShipPtr->cur_status_flags &= ~PLAY_VICTORY_DITTY; } UnlockElement (hElement); } DeadShipPtr->life_span = MusicStarted ? (ONE_SECOND * 3) / BATTLE_FRAME_RATE : 1; DeadShipPtr->death_func = new_ship; DeadShipPtr->preprocess_func = new_ship; SetElementStarShip (DeadShipPtr, DeadStarShipPtr); } if (DeadShipPtr->life_span || !readyForBattleEnd ( WHICH_SIDE (DeadShipPtr->turn_wait))) { DeadShipPtr->state_flags &= ~DISAPPEARING; ++DeadShipPtr->life_span; return; } { BOOLEAN RestartMusic; StopMusic (); StopSound (); SetElementStarShip (DeadShipPtr, 0); RestartMusic = OpponentAlive (DeadStarShipPtr); if (DeadStarShipPtr->RaceDescPtr->uninit_func != NULL) (*DeadStarShipPtr->RaceDescPtr->uninit_func) ( DeadStarShipPtr->RaceDescPtr); free_ship (DeadStarShipPtr, TRUE); UnbatchGraphics (); #ifdef NETPLAY initBattleStateDataConnections (); { bool allOk = negotiateReadyConnections (true, NetState_interBattle); // We are already in NetState_interBattle, but all // sides just need to pass this checkpoint before // going on. if (!allOk) { // Some network connection has been reset. GLOBAL (CurrentActivity) &= ~IN_BATTLE; BatchGraphics (); return; } } #endif /* NETPLAY */ if (GetNextStarShip (DeadStarShipPtr, WHICH_SIDE (DeadShipPtr->turn_wait))) { #ifdef NETPLAY { bool allOk = negotiateReadyConnections (true, NetState_inBattle); if (!allOk) { // Some network connection has been reset. GLOBAL (CurrentActivity) &= ~IN_BATTLE; BatchGraphics (); return; } } #endif if (RestartMusic) BattleSong (TRUE); } else if (LOBYTE (battle_counter) == 0 || HIBYTE (battle_counter) == 0) { // One player is out of ships. The battle is over. GLOBAL (CurrentActivity) &= ~IN_BATTLE; } #ifdef NETPLAY else { // Battle has been aborted. GLOBAL (CurrentActivity) |= CHECK_ABORT; } #endif #ifdef NETPLAY // Turn_wait was abused to store the side this element was on. // We don't want this included in checksums, as it can be different // for both sides of a connection. // While preprocess_func == new_ship, turn_wait isn't included in // the checksum at all all, but now that new_ship is done, // it would be. As the value is irrelevant at this point, we can // just set it to the same value on either side. DeadShipPtr->turn_wait = 0; #endif BatchGraphics (); } } void explosion_preprocess (PELEMENT ShipPtr) { BYTE i; i = (NUM_EXPLOSION_FRAMES * 3) - ShipPtr->life_span; switch (i) { case 25: ShipPtr->preprocess_func = NULL_PTR; case 0: case 1: case 2: case 20: case 21: case 22: case 23: case 24: i = 1; break; case 3: case 4: case 5: case 18: case 19: i = 2; break; case 15: SetPrimType (&DisplayArray[ShipPtr->PrimIndex], NO_PRIM); ShipPtr->state_flags |= CHANGING; default: i = 3; break; } do { HELEMENT hElement; hElement = AllocElement (); if (hElement) { COUNT angle, dist; DWORD rand_val; ELEMENTPTR ElementPtr; extern FRAME explosion[]; PutElement (hElement); LockElement (hElement, &ElementPtr); ElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; ElementPtr->life_span = 9; SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM); ElementPtr->current.image.farray = explosion; ElementPtr->current.image.frame = explosion[0]; rand_val = TFB_Random (); angle = LOBYTE (HIWORD (rand_val)); dist = DISPLAY_TO_WORLD (LOBYTE (LOWORD (rand_val)) % 8); if (HIBYTE (LOWORD (rand_val)) < 256 * 1 / 3) dist += DISPLAY_TO_WORLD (8); ElementPtr->current.location.x = ShipPtr->current.location.x + COSINE (angle, dist); ElementPtr->current.location.y = ShipPtr->current.location.y + SINE (angle, dist); ElementPtr->preprocess_func = animation_preprocess; rand_val = TFB_Random (); angle = LOBYTE (LOWORD (rand_val)); dist = WORLD_TO_VELOCITY ( DISPLAY_TO_WORLD (HIBYTE (LOWORD (rand_val)) % 5)); SetVelocityComponents (&ElementPtr->velocity, COSINE (angle, dist), SINE (angle, dist)); UnlockElement (hElement); } } while (--i); } void ship_death (PELEMENT ShipPtr) { STARSHIPPTR StarShipPtr, VictoriousStarShipPtr; HELEMENT hElement, hNextElement; ELEMENTPTR ElementPtr; StopMusic (); if (ShipPtr->mass_points <= MAX_SHIP_MASS) { if (WHICH_SIDE (ShipPtr->state_flags)) battle_counter -= MAKE_WORD (0, 1); else battle_counter -= MAKE_WORD (1, 0); } VictoriousStarShipPtr = 0; for (hElement = GetHeadElement (); hElement; hElement = hNextElement) { LockElement (hElement, &ElementPtr); if ((ElementPtr->state_flags & PLAYER_SHIP) && ElementPtr != (ELEMENTPTR)ShipPtr /* and not running away */ && ElementPtr->mass_points <= MAX_SHIP_MASS) { GetElementStarShip (ElementPtr, &VictoriousStarShipPtr); if (VictoriousStarShipPtr->RaceDescPtr->ship_info.crew_level == 0) VictoriousStarShipPtr = 0; else VictoriousStarShipPtr->cur_status_flags |= PLAY_VICTORY_DITTY; UnlockElement (hElement); break; } hNextElement = GetSuccElement (ElementPtr); UnlockElement (hElement); } GetElementStarShip (ShipPtr, &StarShipPtr); StarShipPtr->cur_status_flags &= ~PLAY_VICTORY_DITTY; DeltaEnergy ((ELEMENTPTR)ShipPtr, -(SIZE)StarShipPtr->RaceDescPtr->ship_info.energy_level); ShipPtr->life_span = NUM_EXPLOSION_FRAMES * 3; ShipPtr->state_flags &= ~DISAPPEARING; ShipPtr->state_flags |= FINITE_LIFE | NONSOLID; ShipPtr->postprocess_func = PostProcessStatus; ShipPtr->death_func = new_ship; ShipPtr->hTarget = 0; ZeroVelocityComponents (&((ELEMENTPTR)ShipPtr)->velocity); if (ShipPtr->crew_level) /* only happens for shofixti self-destruct */ { PlaySound (SetAbsSoundIndex ( StarShipPtr->RaceDescPtr->ship_data.ship_sounds, 1), CalcSoundPosition (ShipPtr), ShipPtr, GAME_SOUND_PRIORITY + 1); DeltaCrew ((ELEMENTPTR)ShipPtr, -(SIZE)ShipPtr->crew_level); if (VictoriousStarShipPtr == 0) StarShipPtr->cur_status_flags |= PLAY_VICTORY_DITTY; } else { ShipPtr->preprocess_func = explosion_preprocess; PlaySound (SetAbsSoundIndex (GameSounds, SHIP_EXPLODES), CalcSoundPosition (ShipPtr), ShipPtr, GAME_SOUND_PRIORITY + 1); } } #define START_ION_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A) void spawn_ion_trail (PELEMENT ElementPtr) { if (ElementPtr->state_flags & PLAYER_SHIP) { HELEMENT hIonElement; hIonElement = AllocElement (); if (hIonElement) { #define ION_LIFE 1 COUNT angle; RECT r; ELEMENTPTR IonElementPtr; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing) + HALF_CIRCLE; GetFrameRect (StarShipPtr->RaceDescPtr->ship_data.ship[0], &r); r.extent.height = DISPLAY_TO_WORLD (r.extent.height + r.corner.y); InsertElement (hIonElement, GetHeadElement ()); LockElement (hIonElement, &IonElementPtr); IonElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; IonElementPtr->life_span = IonElementPtr->thrust_wait = ION_LIFE; SetPrimType (&DisplayArray[IonElementPtr->PrimIndex], POINT_PRIM); SetPrimColor (&DisplayArray[IonElementPtr->PrimIndex], START_ION_COLOR); IonElementPtr->current.image.frame = DecFrameIndex (stars_in_space); IonElementPtr->current.image.farray = &stars_in_space; IonElementPtr->current.location = ElementPtr->current.location; IonElementPtr->current.location.x += (COORD)COSINE (angle, r.extent.height); IonElementPtr->current.location.y += (COORD)SINE (angle, r.extent.height); IonElementPtr->death_func = spawn_ion_trail; SetElementStarShip (IonElementPtr, StarShipPtr); { /* normally done during preprocess, but because * object is being inserted at head rather than * appended after tail it may never get preprocessed. */ IonElementPtr->next = IonElementPtr->current; --IonElementPtr->life_span; IonElementPtr->state_flags |= PRE_PROCESS; } UnlockElement (hIonElement); } } else { static const COLOR color_tab[] = { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x2a), BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2b), BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2c), BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2d), BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2e), BUILD_COLOR (MAKE_RGB15 (0x0B, 0x00, 0x00), 0x2f), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7a), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7b), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7c), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7d), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7e), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7f), }; #define NUM_TAB_COLORS (sizeof (color_tab) / sizeof (color_tab[0])) COUNT color_index = 0; COLOR Color; Color = COLOR_256 (GetPrimColor (&DisplayArray[ElementPtr->PrimIndex])); if (Color != 0x2F) { ElementPtr->life_span = ElementPtr->thrust_wait; ++Color; if (Color > 0x7F) Color = 0x2A; if (Color <= 0x2f && Color >= 0x2a) color_index = (COUNT)Color - 0x2a; else /* color is between 0x7a and 0x7f */ color_index = (COUNT)(Color - 0x7a) + (NUM_TAB_COLORS >> 1); SetPrimColor (&DisplayArray[ElementPtr->PrimIndex], color_tab[color_index]); ElementPtr->state_flags &= ~DISAPPEARING; ElementPtr->state_flags |= CHANGING; } } } // Preprocess function for spawning a ship into or out of battle. // Used when a new ship warps in, or a ship escapes by warping out, but not // when a Pkunk ship is reborn. void ship_transition (PELEMENT ElementPtr) { if (ElementPtr->state_flags & PLAYER_SHIP) { if (ElementPtr->state_flags & APPEARING) { ElementPtr->life_span = HYPERJUMP_LIFE; ElementPtr->preprocess_func = ship_transition; ElementPtr->postprocess_func = NULL_PTR; SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; } else if (ElementPtr->life_span < HYPERJUMP_LIFE) { if (ElementPtr->life_span == NORMAL_LIFE && ElementPtr->crew_level) { ElementPtr->current.image.frame = ElementPtr->next.image.frame = SetEquFrameIndex ( ElementPtr->current.image.farray[0], ElementPtr->current.image.frame); SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM); InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); InitIntersectFrame (ElementPtr); ZeroVelocityComponents (&((ELEMENTPTR)ElementPtr)->velocity); ElementPtr->state_flags &= ~(NONSOLID | FINITE_LIFE); ElementPtr->state_flags |= CHANGING; ElementPtr->preprocess_func = ship_preprocess; ElementPtr->postprocess_func = ship_postprocess; } return; } } { HELEMENT hShipImage; ELEMENTPTR ShipImagePtr; STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); LockElement (StarShipPtr->hShip, &ShipImagePtr); if (!(ShipImagePtr->state_flags & NONSOLID)) { ElementPtr->preprocess_func = NULL_PTR; } else if ((hShipImage = AllocElement ())) { #define TRANSITION_SPEED DISPLAY_TO_WORLD (40) #define TRANSITION_LIFE 1 COUNT angle; PutElement (hShipImage); angle = FACING_TO_ANGLE (StarShipPtr->ShipFacing); LockElement (hShipImage, &ShipImagePtr); ShipImagePtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; ShipImagePtr->life_span = ShipImagePtr->thrust_wait = TRANSITION_LIFE; SetPrimType (&DisplayArray[ShipImagePtr->PrimIndex], STAMPFILL_PRIM); SetPrimColor (&DisplayArray[ShipImagePtr->PrimIndex], START_ION_COLOR); ShipImagePtr->current.image = ElementPtr->current.image; ShipImagePtr->current.location = ElementPtr->current.location; if (!(ElementPtr->state_flags & PLAYER_SHIP)) { ShipImagePtr->current.location.x += COSINE (angle, TRANSITION_SPEED); ShipImagePtr->current.location.y += SINE (angle, TRANSITION_SPEED); ElementPtr->preprocess_func = NULL_PTR; } else if (ElementPtr->crew_level) { ShipImagePtr->current.location.x -= COSINE (angle, TRANSITION_SPEED) * (ElementPtr->life_span - 1); ShipImagePtr->current.location.y -= SINE (angle, TRANSITION_SPEED) * (ElementPtr->life_span - 1); ShipImagePtr->current.location.x = WRAP_X (ShipImagePtr->current.location.x); ShipImagePtr->current.location.y = WRAP_Y (ShipImagePtr->current.location.y); } ShipImagePtr->preprocess_func = ship_transition; ShipImagePtr->death_func = spawn_ion_trail; SetElementStarShip (ShipImagePtr, StarShipPtr); UnlockElement (hShipImage); } UnlockElement (StarShipPtr->hShip); } } void flee_preprocess (PELEMENT ElementPtr) { STARSHIPPTR StarShipPtr; if (--ElementPtr->turn_wait == 0) { SIZE dir; COLOR c; static const COLOR color_tab[] = { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x19, 0x19), 0x24), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x13, 0x13), 0x25), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0F, 0x0F), 0x26), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x27), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x04, 0x04), 0x28), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x29), BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A), BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C), BUILD_COLOR (MAKE_RGB15 (0x0E, 0x00, 0x00), 0x2D), BUILD_COLOR (MAKE_RGB15 (0x0A, 0x00, 0x00), 0x2E), }; dir = HINIBBLE (ElementPtr->thrust_wait) - 1; c = COLOR_256 (GetPrimColor (&DisplayArray[ElementPtr->PrimIndex])); if (c == 0x24) dir = -dir; c += dir; c = color_tab[c - 0x24]; SetPrimColor (&DisplayArray[ElementPtr->PrimIndex], c); if (COLOR_256 (c) == 0x2E) { dir = -dir; --ElementPtr->thrust_wait; } dir += 1; ElementPtr->turn_wait = LONIBBLE (ElementPtr->thrust_wait); if (ElementPtr->turn_wait) { ElementPtr->thrust_wait = MAKE_BYTE (ElementPtr->turn_wait, dir); ElementPtr->turn_wait = ((ElementPtr->turn_wait - 1) >> 1) + 1; } else if (COLOR_256 (c) != 0x24) { ElementPtr->thrust_wait = MAKE_BYTE (0, dir); ElementPtr->turn_wait = 1; } else { ElementPtr->death_func = new_ship; ElementPtr->crew_level = 0; ElementPtr->life_span = HYPERJUMP_LIFE + 1; ElementPtr->preprocess_func = ship_transition; ElementPtr->postprocess_func = NULL_PTR; SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->state_flags |= NONSOLID | FINITE_LIFE | CHANGING; } } GetElementStarShip (ElementPtr, &StarShipPtr); StarShipPtr->cur_status_flags &= ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL); PreProcessStatus (ElementPtr); } uqm-0.6.2/sc2/src/sc2code/process.c0000600000175000017500000006652110543202103015431 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "collide.h" #include "options.h" #include "settings.h" #include "setup.h" #include "sounds.h" #include "element.h" #include "weapon.h" #include "libs/graphics/drawable.h" #include "libs/graphics/drawcmd.h" #include "libs/graphics/gfx_common.h" #include "libs/log.h" //#define DEBUG_PROCESS COUNT DisplayFreeList; PRIMITIVE DisplayArray[MAX_DISPLAY_PRIMS]; extern POINT SpaceOrg; SIZE zoom_out = 1 << ZOOM_SHIFT; static SIZE opt_max_zoom_out; #if 0 static inline void CALC_ZOOM_STUFF (COUNT* idx, COUNT* sc) { int i, z; z = 1 << ZOOM_SHIFT; for (i = 0; (z <<= 1) <= zoom_out; i++) ; *idx = i; *sc = ((1 << i) << (ZOOM_SHIFT + 8)) / zoom_out; } #else static inline void CALC_ZOOM_STUFF (COUNT* idx, COUNT* sc) { int i; if (zoom_out < 2 << ZOOM_SHIFT) i = 0; else if (zoom_out < 4 << ZOOM_SHIFT) i = 1; else i = 2; *idx = i; *sc = (1 << (i + ZOOM_SHIFT + 8)) / zoom_out; } #endif HELEMENT AllocElement (void) { HELEMENT hElement; hElement = AllocLink (&disp_q); if (hElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); memset (ElementPtr, 0, sizeof (*ElementPtr)); ElementPtr->PrimIndex = AllocDisplayPrim (); SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); UnlockElement (hElement); } return (hElement); } void FreeElement (HELEMENT hElement) { if (hElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); FreeDisplayPrim (ElementPtr->PrimIndex); UnlockElement (hElement); FreeLink (&disp_q, hElement); } } void SetUpElement (ELEMENTPTR ElementPtr) { ElementPtr->next = ElementPtr->current; if (CollidingElement (ElementPtr)) { InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); InitIntersectFrame (ElementPtr); } } static void PreProcess (ELEMENTPTR ElementPtr) { ELEMENT_FLAGS state_flags; if (ElementPtr->life_span == 0) { if (ElementPtr->pParent) /* untarget this dead element */ Untarget (ElementPtr); ElementPtr->state_flags |= DISAPPEARING; if (ElementPtr->death_func) (*ElementPtr->death_func) (ElementPtr); } state_flags = ElementPtr->state_flags; if (!(state_flags & DISAPPEARING)) { if (state_flags & APPEARING) { SetUpElement (ElementPtr); if (state_flags & PLAYER_SHIP) state_flags &= ~APPEARING; /* want to preprocess ship */ } if (ElementPtr->preprocess_func && !(state_flags & APPEARING)) { (*ElementPtr->preprocess_func) (ElementPtr); state_flags = ElementPtr->state_flags; if ((state_flags & CHANGING) && CollidingElement (ElementPtr)) InitIntersectFrame (ElementPtr); } if (!(state_flags & IGNORE_VELOCITY)) { SIZE delta_x, delta_y; GetNextVelocityComponents (&ElementPtr->velocity, &delta_x, &delta_y, 1); if (delta_x != 0 || delta_y != 0) { state_flags |= CHANGING; ElementPtr->next.location.x += delta_x; ElementPtr->next.location.y += delta_y; } } if (CollidingElement (ElementPtr)) InitIntersectEndPoint (ElementPtr); if (state_flags & FINITE_LIFE) --ElementPtr->life_span; } ElementPtr->state_flags = (state_flags & ~(POST_PROCESS | COLLISION)) | PRE_PROCESS; } static void PostProcess (ELEMENTPTR ElementPtr) { if (ElementPtr->postprocess_func) (*ElementPtr->postprocess_func) (ElementPtr); ElementPtr->current = ElementPtr->next; if (CollidingElement (ElementPtr)) { InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); } ElementPtr->state_flags = (ElementPtr->state_flags & ~(PRE_PROCESS | CHANGING | APPEARING)) | POST_PROCESS; } static COUNT CalcReduction (SIZE dx, SIZE dy) { COUNT next_reduction; #ifdef KDEBUG log_add (log_Debug, "CalcReduction:"); #endif if (optMeleeScale == TFB_SCALE_STEP) { SIZE sdx, sdy; if (LOBYTE (GLOBAL (CurrentActivity)) > IN_ENCOUNTER) return (0); sdx = dx; sdy = dy; for (next_reduction = MAX_VIS_REDUCTION; (dx <<= REDUCTION_SHIFT) <= TRANSITION_WIDTH && (dy <<= REDUCTION_SHIFT) <= TRANSITION_HEIGHT && next_reduction > 0; next_reduction -= REDUCTION_SHIFT) ; /* check for "real" zoom in */ if (next_reduction < zoom_out && zoom_out <= MAX_VIS_REDUCTION) { #define HYSTERESIS_X DISPLAY_TO_WORLD(24) #define HYSTERESIS_Y DISPLAY_TO_WORLD(20) if (((sdx + HYSTERESIS_X) << (MAX_VIS_REDUCTION - next_reduction)) > TRANSITION_WIDTH || ((sdy + HYSTERESIS_Y) << (MAX_VIS_REDUCTION - next_reduction)) > TRANSITION_HEIGHT) /* if we don't zoom in, we want to stay at next+1 */ next_reduction += REDUCTION_SHIFT; } if (next_reduction == 0 && LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) next_reduction += REDUCTION_SHIFT; } else { if (LOBYTE (GLOBAL (CurrentActivity)) > IN_ENCOUNTER) return (1 << ZOOM_SHIFT); dx = (dx * MAX_ZOOM_OUT) / (LOG_SPACE_WIDTH >> 2); if (dx < (1 << ZOOM_SHIFT)) dx = 1 << ZOOM_SHIFT; else if (dx > MAX_ZOOM_OUT) dx = MAX_ZOOM_OUT; dy = (dy * MAX_ZOOM_OUT) / (LOG_SPACE_HEIGHT >> 2); if (dy < (1 << ZOOM_SHIFT)) dy = 1 << ZOOM_SHIFT; else if (dy > MAX_ZOOM_OUT) dy = MAX_ZOOM_OUT; if (dy > dx) next_reduction = dy; else next_reduction = dx; if (next_reduction < (2 << ZOOM_SHIFT) && LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) next_reduction = (2 << ZOOM_SHIFT); } #ifdef KDEBUG log_add (log_Debug, "CalcReduction: exit"); #endif return (next_reduction); } static VIEW_STATE CalcView (PPOINT pNewScrollPt, SIZE next_reduction, PSIZE pdx, PSIZE pdy, COUNT ships_alive) { SIZE dx, dy; VIEW_STATE view_state; #ifdef KDEBUG log_add (log_Debug, "CalcView:"); #endif dx = ((COORD)(LOG_SPACE_WIDTH >> 1) - pNewScrollPt->x); dy = ((COORD)(LOG_SPACE_HEIGHT >> 1) - pNewScrollPt->y); dx = WRAP_DELTA_X (dx); dy = WRAP_DELTA_Y (dy); if (ships_alive == 1) { #define ORG_JUMP_X ((SIZE)DISPLAY_ALIGN(LOG_SPACE_WIDTH / 75)) #define ORG_JUMP_Y ((SIZE)DISPLAY_ALIGN(LOG_SPACE_HEIGHT / 75)) if (dx > ORG_JUMP_X) dx = ORG_JUMP_X; else if (dx < -ORG_JUMP_X) dx = -ORG_JUMP_X; if (dy > ORG_JUMP_Y) dy = ORG_JUMP_Y; else if (dy < -ORG_JUMP_Y) dy = -ORG_JUMP_Y; } if ((dx || dy) && LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) MoveSIS (&dx, &dy); if (zoom_out == next_reduction) view_state = dx == 0 && dy == 0 && LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE ? VIEW_STABLE : VIEW_SCROLL; else { if (optMeleeScale == TFB_SCALE_STEP) { SpaceOrg.x = (COORD)(LOG_SPACE_WIDTH >> 1) - (LOG_SPACE_WIDTH >> ((MAX_REDUCTION + 1) - next_reduction)); SpaceOrg.y = (COORD)(LOG_SPACE_HEIGHT >> 1) - (LOG_SPACE_HEIGHT >> ((MAX_REDUCTION + 1) - next_reduction)); } else { #define ZOOM_JUMP ((1 << ZOOM_SHIFT) >> 3) if (ships_alive == 1 && zoom_out > next_reduction && zoom_out <= MAX_ZOOM_OUT && zoom_out - next_reduction > ZOOM_JUMP) next_reduction = zoom_out - ZOOM_JUMP; SpaceOrg.x = (int)(LOG_SPACE_WIDTH >> 1) - (LOG_SPACE_WIDTH * next_reduction / (MAX_ZOOM_OUT << 2)); SpaceOrg.y = (int)(LOG_SPACE_HEIGHT >> 1) - (LOG_SPACE_HEIGHT * next_reduction / (MAX_ZOOM_OUT << 2)); } zoom_out = next_reduction; view_state = VIEW_CHANGE; } if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_HYPERSPACE) MoveGalaxy (view_state, dx, dy); *pdx = dx; *pdy = dy; #ifdef KDEBUG log_add (log_Debug, "CalcView: exit"); #endif return (view_state); } static ELEMENT_FLAGS ProcessCollisions (HELEMENT hSuccElement, ELEMENTPTR ElementPtr, TIME_VALUE min_time, ELEMENT_FLAGS process_flags) { HELEMENT hTestElement; while ((hTestElement = hSuccElement) != 0) { ELEMENTPTR TestElementPtr; LockElement (hTestElement, &TestElementPtr); if (!(TestElementPtr->state_flags & process_flags)) PreProcess (TestElementPtr); hSuccElement = GetSuccElement (TestElementPtr); if (TestElementPtr == ElementPtr) { UnlockElement (hTestElement); continue; } if (CollisionPossible (TestElementPtr, ElementPtr)) { ELEMENT_FLAGS state_flags, test_state_flags; TIME_VALUE time_val; state_flags = ElementPtr->state_flags; test_state_flags = TestElementPtr->state_flags; if (((state_flags | test_state_flags) & FINITE_LIFE) && (((state_flags & APPEARING) && ElementPtr->life_span > 1) || ((test_state_flags & APPEARING) && TestElementPtr->life_span > 1))) time_val = 0; else { while ((time_val = DrawablesIntersect (&ElementPtr->IntersectControl, &TestElementPtr->IntersectControl, min_time)) == 1 && !((state_flags | test_state_flags) & FINITE_LIFE)) { #ifdef DEBUG_PROCESS log_add (log_Debug, "BAD NEWS 0x%x <--> 0x%x", ElementPtr, TestElementPtr); #endif /* DEBUG_PROCESS */ if (state_flags & COLLISION) { InitIntersectEndPoint (TestElementPtr); TestElementPtr->IntersectControl.IntersectStamp.origin = TestElementPtr->IntersectControl.EndPoint; time_val = DrawablesIntersect (&ElementPtr->IntersectControl, &TestElementPtr->IntersectControl, 1); InitIntersectStartPoint (TestElementPtr); } if (time_val == 1) { FRAME CurFrame, NextFrame, TestCurFrame, TestNextFrame; CurFrame = ElementPtr->current.image.frame; NextFrame = ElementPtr->next.image.frame; TestCurFrame = TestElementPtr->current.image.frame; TestNextFrame = TestElementPtr->next.image.frame; if (NextFrame == CurFrame && TestNextFrame == TestCurFrame) { if (test_state_flags & APPEARING) { do_damage (TestElementPtr, TestElementPtr->hit_points); if (TestElementPtr->pParent) /* untarget this dead element */ Untarget (TestElementPtr); TestElementPtr->state_flags |= (COLLISION | DISAPPEARING); if (TestElementPtr->death_func) (*TestElementPtr->death_func) (TestElementPtr); } if (state_flags & APPEARING) { do_damage (ElementPtr, ElementPtr->hit_points); if (ElementPtr->pParent) /* untarget this dead element */ Untarget (ElementPtr); ElementPtr->state_flags |= (COLLISION | DISAPPEARING); if (ElementPtr->death_func) (*ElementPtr->death_func) (ElementPtr); UnlockElement (hTestElement); return (COLLISION); } time_val = 0; } else { if (GetFrameIndex (CurFrame) != GetFrameIndex (NextFrame)) ElementPtr->next.image.frame = SetEquFrameIndex (NextFrame, CurFrame); else if (NextFrame != CurFrame) { ElementPtr->next.image = ElementPtr->current.image; if (ElementPtr->life_span > NORMAL_LIFE) ElementPtr->life_span = NORMAL_LIFE; } if (GetFrameIndex (TestCurFrame) != GetFrameIndex (TestNextFrame)) TestElementPtr->next.image.frame = SetEquFrameIndex (TestNextFrame, TestCurFrame); else if (TestNextFrame != TestCurFrame) { TestElementPtr->next.image = TestElementPtr->current.image; if (TestElementPtr->life_span > NORMAL_LIFE) TestElementPtr->life_span = NORMAL_LIFE; } InitIntersectStartPoint (ElementPtr); InitIntersectEndPoint (ElementPtr); InitIntersectFrame (ElementPtr); if (state_flags & PLAYER_SHIP) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); StarShipPtr->ShipFacing = GetFrameIndex ( ElementPtr->next.image.frame); } InitIntersectStartPoint (TestElementPtr); InitIntersectEndPoint (TestElementPtr); InitIntersectFrame (TestElementPtr); if (test_state_flags & PLAYER_SHIP) { STARSHIPPTR StarShipPtr; GetElementStarShip (TestElementPtr, &StarShipPtr); StarShipPtr->ShipFacing = GetFrameIndex ( TestElementPtr->next.image.frame); } } } if (time_val == 0) { InitIntersectEndPoint (ElementPtr); InitIntersectEndPoint (TestElementPtr); break; } } } if (time_val > 0) { POINT SavePt, TestSavePt; #ifdef DEBUG_PROCESS log_add (log_Debug, "0x%x <--> 0x%x at %u", ElementPtr, TestElementPtr, time_val); #endif /* DEBUG_PROCESS */ SavePt = ElementPtr->IntersectControl.EndPoint; TestSavePt = TestElementPtr->IntersectControl.EndPoint; InitIntersectEndPoint (ElementPtr); InitIntersectEndPoint (TestElementPtr); if (time_val == 1 || (((state_flags & COLLISION) || !ProcessCollisions (hSuccElement, ElementPtr, time_val - 1, process_flags)) && ((test_state_flags & COLLISION) || !ProcessCollisions ( !(TestElementPtr->state_flags & APPEARING) ? GetSuccElement (ElementPtr) : GetHeadElement (), TestElementPtr, time_val - 1, process_flags)))) { state_flags = ElementPtr->state_flags; test_state_flags = TestElementPtr->state_flags; #ifdef DEBUG_PROCESS log_add (log_Debug, "PROCESSING 0x%x <--> 0x%x at %u", ElementPtr, TestElementPtr, time_val); #endif /* DEBUG_PROCESS */ if (test_state_flags & PLAYER_SHIP) { (*TestElementPtr->collision_func) ( TestElementPtr, &TestSavePt, ElementPtr, &SavePt ); (*ElementPtr->collision_func) ( ElementPtr, &SavePt, TestElementPtr, &TestSavePt ); } else { (*ElementPtr->collision_func) ( ElementPtr, &SavePt, TestElementPtr, &TestSavePt ); (*TestElementPtr->collision_func) ( TestElementPtr, &TestSavePt, ElementPtr, &SavePt ); } if (TestElementPtr->state_flags & COLLISION) { if (!(test_state_flags & COLLISION)) { TestElementPtr->IntersectControl.IntersectStamp.origin = TestSavePt; TestElementPtr->next.location.x = DISPLAY_TO_WORLD (TestSavePt.x); TestElementPtr->next.location.y = DISPLAY_TO_WORLD (TestSavePt.y); InitIntersectEndPoint (TestElementPtr); } } if (ElementPtr->state_flags & COLLISION) { if (!(state_flags & COLLISION)) { ElementPtr->IntersectControl.IntersectStamp.origin = SavePt; ElementPtr->next.location.x = DISPLAY_TO_WORLD (SavePt.x); ElementPtr->next.location.y = DISPLAY_TO_WORLD (SavePt.y); InitIntersectEndPoint (ElementPtr); if (!(state_flags & FINITE_LIFE) && !(test_state_flags & FINITE_LIFE)) { collide (ElementPtr, TestElementPtr); ProcessCollisions (GetHeadElement (), ElementPtr, MAX_TIME_VALUE, process_flags); ProcessCollisions (GetHeadElement (), TestElementPtr, MAX_TIME_VALUE, process_flags); } } UnlockElement (hTestElement); return (COLLISION); } if (!CollidingElement (ElementPtr)) { ElementPtr->state_flags |= COLLISION; UnlockElement (hTestElement); return (COLLISION); } } } } UnlockElement (hTestElement); } return (ElementPtr->state_flags & COLLISION); } static VIEW_STATE PreProcessQueue (PSIZE pscroll_x, PSIZE pscroll_y) { SIZE min_reduction, max_reduction; COUNT num_ships; POINT Origin; HELEMENT hElement; COUNT ships_alive; #ifdef KDEBUG log_add (log_Debug, "PreProcess:"); #endif num_ships = (LOBYTE (battle_counter) ? 1 : 0) + (HIBYTE (battle_counter) ? 1 : 0); if (optMeleeScale == TFB_SCALE_STEP) min_reduction = max_reduction = MAX_VIS_REDUCTION + 1; else min_reduction = max_reduction = MAX_ZOOM_OUT + (1 << ZOOM_SHIFT); Origin.x = (COORD)(LOG_SPACE_WIDTH >> 1); Origin.y = (COORD)(LOG_SPACE_HEIGHT >> 1); hElement = GetHeadElement (); ships_alive = 0; while (hElement != 0) { ELEMENTPTR ElementPtr; HELEMENT hNextElement; LockElement (hElement, &ElementPtr); if (!(ElementPtr->state_flags & PRE_PROCESS)) PreProcess (ElementPtr); hNextElement = GetSuccElement (ElementPtr); if (CollidingElement (ElementPtr) && !(ElementPtr->state_flags & COLLISION)) ProcessCollisions (hNextElement, ElementPtr, MAX_TIME_VALUE, PRE_PROCESS); if (ElementPtr->state_flags & PLAYER_SHIP) { SIZE dx, dy; ships_alive++; if (max_reduction > opt_max_zoom_out && min_reduction > opt_max_zoom_out) { Origin.x = DISPLAY_ALIGN (ElementPtr->next.location.x); Origin.y = DISPLAY_ALIGN (ElementPtr->next.location.y); } dx = DISPLAY_ALIGN (ElementPtr->next.location.x) - Origin.x; dx = WRAP_DELTA_X (dx); dy = DISPLAY_ALIGN (ElementPtr->next.location.y) - Origin.y; dy = WRAP_DELTA_Y (dy); if (num_ships <= 2 || !(ElementPtr->state_flags & BAD_GUY)) { Origin.x = DISPLAY_ALIGN (Origin.x + (dx >> 1)); Origin.y = DISPLAY_ALIGN (Origin.y + (dy >> 1)); if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; max_reduction = CalcReduction (dx, dy); } else if (max_reduction > opt_max_zoom_out && min_reduction <= opt_max_zoom_out) { Origin.x = DISPLAY_ALIGN (Origin.x + (dx >> 1)); Origin.y = DISPLAY_ALIGN (Origin.y + (dy >> 1)); if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; min_reduction = CalcReduction (dx, dy); } else { SIZE reduction; if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; reduction = CalcReduction (dx << 1, dy << 1); if (min_reduction > opt_max_zoom_out || reduction < min_reduction) min_reduction = reduction; } // log_add (log_Debug, "dx = %d dy = %d min_red = %d max_red = %d", // dx, dy, min_reduction, max_reduction); } UnlockElement (hElement); hElement = hNextElement; } if ((min_reduction > opt_max_zoom_out || min_reduction <= max_reduction) && (min_reduction = max_reduction) > opt_max_zoom_out && (min_reduction = zoom_out) > opt_max_zoom_out) { if (optMeleeScale == TFB_SCALE_STEP) min_reduction = 0; else min_reduction = 1 << ZOOM_SHIFT; } #ifdef KDEBUG log_add (log_Debug, "PreProcess: exit"); #endif return (CalcView (&Origin, min_reduction, pscroll_x, pscroll_y, ships_alive)); } void InsertPrim (PRIM_LINKS *pLinks, COUNT primIndex, COUNT iPI) { COUNT Link; PRIM_LINKS PL; if (iPI == END_OF_LIST) { Link = GetSuccLink (*pLinks); /* get tail */ if (Link == END_OF_LIST) *pLinks = MakeLinks (primIndex, primIndex); else *pLinks = MakeLinks (GetPredLink (*pLinks), primIndex); } else { PL = GetPrimLinks (&DisplayArray[iPI]); if (iPI != GetPredLink (*pLinks)) /* if not the head */ Link = GetPredLink (PL); else { Link = END_OF_LIST; *pLinks = MakeLinks (primIndex, GetSuccLink (*pLinks)); } SetPrimLinks (&DisplayArray[iPI], primIndex, GetSuccLink (PL)); } if (Link != END_OF_LIST) { PL = GetPrimLinks (&DisplayArray[Link]); SetPrimLinks (&DisplayArray[Link], GetPredLink (PL), primIndex); } SetPrimLinks (&DisplayArray[primIndex], Link, iPI); } PRIM_LINKS DisplayLinks; static inline COORD CalcDisplayCoord (COORD c, COORD orgc, SIZE reduction) { if (optMeleeScale == TFB_SCALE_STEP) { /* old fixed-step zoom style */ return (c - orgc) >> reduction; } else { /* new continuous zoom style */ return ((c - orgc) << ZOOM_SHIFT) / reduction; } } static void PostProcessQueue (VIEW_STATE view_state, SIZE scroll_x, SIZE scroll_y) { POINT delta; SIZE reduction; HELEMENT hElement; #ifdef KDEBUG log_add (log_Debug, "PostProcess:"); #endif if (optMeleeScale == TFB_SCALE_STEP) reduction = zoom_out + ONE_SHIFT; else reduction = zoom_out << ONE_SHIFT; hElement = GetHeadElement (); while (hElement != 0) { ELEMENT_FLAGS state_flags; ELEMENTPTR ElementPtr; HELEMENT hNextElement; LockElement (hElement, &ElementPtr); state_flags = ElementPtr->state_flags; if (state_flags & PRE_PROCESS) { if (!(state_flags & COLLISION)) ElementPtr->state_flags &= ~DEFY_PHYSICS; else ElementPtr->state_flags &= ~COLLISION; if (state_flags & POST_PROCESS) { delta.x = 0; delta.y = 0; } else { delta.x = scroll_x; delta.y = scroll_y; } } else { HELEMENT hPostElement; hPostElement = hElement; do { ELEMENTPTR PostElementPtr; LockElement (hPostElement, &PostElementPtr); if (!(PostElementPtr->state_flags & PRE_PROCESS)) PreProcess (PostElementPtr); hNextElement = GetSuccElement (PostElementPtr); if (CollidingElement (PostElementPtr) && !(PostElementPtr->state_flags & COLLISION)) ProcessCollisions (GetHeadElement (), PostElementPtr, MAX_TIME_VALUE, PRE_PROCESS | POST_PROCESS); UnlockElement (hPostElement); hPostElement = hNextElement; } while (hPostElement != 0); scroll_x = 0; scroll_y = 0; delta.x = 0; delta.y = 0; /* because these are newly added elements that are * already in adjusted coordinates */ state_flags = ElementPtr->state_flags; } if (state_flags & DISAPPEARING) { hNextElement = GetSuccElement (ElementPtr); UnlockElement (hElement); RemoveElement (hElement); FreeElement (hElement); } else { GRAPHICS_PRIM ObjType; ObjType = GetPrimType (&DisplayArray[ElementPtr->PrimIndex]); if (view_state != VIEW_STABLE || (state_flags & (APPEARING | CHANGING))) { POINT next; if (ObjType == LINE_PRIM) { SIZE dx, dy; dx = ElementPtr->next.location.x - ElementPtr->current.location.x; dy = ElementPtr->next.location.y - ElementPtr->current.location.y; next.x = WRAP_X (ElementPtr->current.location.x + delta.x); next.y = WRAP_Y (ElementPtr->current.location.y + delta.y); DisplayArray[ElementPtr->PrimIndex].Object.Line.first.x = CalcDisplayCoord (next.x, SpaceOrg.x, reduction); DisplayArray[ElementPtr->PrimIndex].Object.Line.first.y = CalcDisplayCoord (next.y, SpaceOrg.y, reduction); next.x += dx; next.y += dy; DisplayArray[ElementPtr->PrimIndex].Object.Line.second.x = CalcDisplayCoord (next.x, SpaceOrg.x, reduction); DisplayArray[ElementPtr->PrimIndex].Object.Line.second.y = CalcDisplayCoord (next.y, SpaceOrg.y, reduction); } else { next.x = WRAP_X (ElementPtr->next.location.x + delta.x); next.y = WRAP_Y (ElementPtr->next.location.y + delta.y); DisplayArray[ElementPtr->PrimIndex].Object.Point.x = CalcDisplayCoord (next.x, SpaceOrg.x, reduction); DisplayArray[ElementPtr->PrimIndex].Object.Point.y = CalcDisplayCoord (next.y, SpaceOrg.y, reduction); if (ObjType == STAMP_PRIM || ObjType == STAMPFILL_PRIM) { if (view_state == VIEW_CHANGE || (state_flags & (APPEARING | CHANGING))) { COUNT index, scale = GSCALE_IDENTITY; if (optMeleeScale == TFB_SCALE_STEP) index = zoom_out; else CALC_ZOOM_STUFF (&index, &scale); ElementPtr->next.image.frame = #ifdef SAFE SetAbsFrameIndex ( ElementPtr->next.image.farray[index], GetFrameIndex (ElementPtr->next.image.frame)); #else /* SAFE */ SetEquFrameIndex ( ElementPtr->next.image.farray[index], ElementPtr->next.image.frame); #endif /* SAFE */ if (optMeleeScale == TFB_SCALE_TRILINEAR && index < 2 && scale != 256) { // enqueues drawcommand to assign next // (smaller) zoom level image as mipmap, // needed for trilinear scaling PFRAME_DESC frame = SetAbsFrameIndex ( ElementPtr->next.image.farray [index + 1], GetFrameIndex (ElementPtr->next.image.frame)); if (frame && frame->image) { TFB_DrawCommand DC; TFB_Image *mmimg = frame->image; DC.Type = TFB_DRAWCOMMANDTYPE_SETMIPMAP; DC.data.setmipmap.image = ((PFRAME_DESC)ElementPtr->next.image.frame)->image; DC.data.setmipmap.hotx = frame->HotSpot.x; DC.data.setmipmap.hoty = frame->HotSpot.y; LockMutex (mmimg->mutex); DC.data.setmipmap.mipmap = mmimg->NormalImg; UnlockMutex (mmimg->mutex); TFB_EnqueueDrawCommand (&DC); } } } DisplayArray[ElementPtr->PrimIndex].Object.Stamp.frame = ElementPtr->next.image.frame; } } ElementPtr->next.location = next; } PostProcess (ElementPtr); if (ObjType < NUM_PRIMS) InsertPrim (&DisplayLinks, ElementPtr->PrimIndex, END_OF_LIST); hNextElement = GetSuccElement (ElementPtr); UnlockElement (hElement); } hElement = hNextElement; } #ifdef KDEBUG log_add (log_Debug, "PostProcess: exit"); #endif } void InitDisplayList (void) { COUNT i; if (optMeleeScale == TFB_SCALE_STEP) { zoom_out = MAX_VIS_REDUCTION + 1; opt_max_zoom_out = MAX_VIS_REDUCTION; } else { zoom_out = MAX_ZOOM_OUT + (1 << ZOOM_SHIFT); opt_max_zoom_out = MAX_ZOOM_OUT; } ReinitQueue (&disp_q); for (i = 0; i < MAX_DISPLAY_PRIMS; ++i) SetPrimLinks (&DisplayArray[i], END_OF_LIST, i + 1); SetPrimLinks (&DisplayArray[i - 1], END_OF_LIST, END_OF_LIST); DisplayFreeList = 0; DisplayLinks = MakeLinks (END_OF_LIST, END_OF_LIST); } UWORD nth_frame = 0; void RedrawQueue (BOOLEAN clear) { SIZE scroll_x, scroll_y; VIEW_STATE view_state; SetContext (StatusContext); view_state = PreProcessQueue (&scroll_x, &scroll_y); PostProcessQueue (view_state, scroll_x, scroll_y); if (optStereoSFX) UpdateSoundPositions (); SetContext (SpaceContext); if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE || !(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { BYTE skip_frames; skip_frames = HIBYTE (nth_frame); if (skip_frames != (BYTE)~0 && (skip_frames == 0 || (--nth_frame & 0x00FF) == 0)) { nth_frame += skip_frames; if (clear) ClearDrawable (); // this is for BATCH_BUILD_PAGE effect, but not scaled by SetGraphicScale if (optMeleeScale != TFB_SCALE_STEP) { COUNT index, scale; CALC_ZOOM_STUFF (&index, &scale); SetGraphicScale (scale); } DrawBatch (DisplayArray, DisplayLinks, 0);//BATCH_BUILD_PAGE); SetGraphicScale (0); } FlushSounds (); } else { // sfx queue needs to be flushed when aborting ProcessSound ((SOUND)~0, NULL); FlushSounds (); } DisplayLinks = MakeLinks (END_OF_LIST, END_OF_LIST); } void Untarget (ELEMENTPTR ElementPtr) { HELEMENT hElement, hNextElement; for (hElement = GetHeadElement (); hElement; hElement = hNextElement) { HELEMENT hTarget; ELEMENTPTR ListPtr; LockElement (hElement, &ListPtr); hNextElement = GetSuccElement (ListPtr); hTarget = ListPtr->hTarget; if (hTarget) { ELEMENTPTR TargetElementPtr; LockElement (hTarget, &TargetElementPtr); if (TargetElementPtr == ElementPtr) ListPtr->hTarget = 0; UnlockElement (hTarget); } UnlockElement (hElement); } } void RemoveElement (HLINK hLink) { if (optStereoSFX) { ELEMENTPTR ElementPtr; LockElement (hLink, &ElementPtr); if (ElementPtr != NULL) RemoveSoundsForObject(ElementPtr); UnlockElement (hLink); } RemoveQueue (&disp_q, hLink); } uqm-0.6.2/sc2/src/sc2code/coderes.h0000600000175000017500000000241210543202101015367 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _CODERES_H #define _CODERES_H #include "reslib.h" extern MEM_HANDLE LoadCodeResFile (PSTR pStr); extern BOOLEAN InstallCodeResType (COUNT code_type); extern MEM_HANDLE LoadCodeResInstance (RESOURCE res); extern PVOID CaptureCodeRes (MEM_HANDLE hCode, PVOID pData, PVOID *ppLocData); extern MEM_HANDLE ReleaseCodeRes (PVOID CodeRef); extern BOOLEAN DestroyCodeRes (MEM_HANDLE hCode); typedef struct { MEM_HANDLE hCode; UWORD size; } CODE_REF; typedef CODE_REF *PCODE_REF; #endif /* _CODERES_H */ uqm-0.6.2/sc2/src/sc2code/plandata.c0000600000175000017500000021734510543202103015541 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "encount.h" #include "resinst.h" #include "planets/elemdata.h" STAR_DESC starmap_array[] = { // postfix name index (like 'Normae') // prefix name index (like 'Alpha') | // alien presence | | // owner (unused) | | | // x, y star type colour | | | | {{5007, 35}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 74}, {{ 708, 41}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 7, 91}, {{4714, 78}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 7, 74}, {{2187, 83}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 0, 126}, {{2814, 89}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 82}, {{4244, 91}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 125}, {{5652, 98}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 124}, {{2939, 116}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 82}, {{2771, 146}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 82}, {{5313, 150}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 6, 73}, {{ 265, 156}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 92}, {{4529, 169}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 8, 74}, {{4911, 180}, MAKE_STAR (GIANT_STAR, ORANGE_BODY, -1), 0, 1, 74}, {{4747, 221}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 74}, {{9708, 250}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 112}, {{4861, 262}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 74}, {{2908, 269}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), SHOFIXTI_DEFINED, 4, 82}, {{1855, 270}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 81}, {{7958, 270}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 8}, {{5160, 280}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 73}, {{ 570, 289}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 92}, {{4923, 294}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), YEHAT_DEFINED, 3, 74}, {{2820, 301}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 82}, {{7934, 318}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 8}, {{8062, 318}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 8}, {{1116, 334}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 91}, {{ 803, 337}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 91}, {{1787, 338}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 81}, {{ 877, 340}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 91}, {{5338, 355}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 5, 73}, {{5039, 373}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 73}, {{ 843, 380}, MAKE_STAR (GIANT_STAR, ORANGE_BODY, -1), 0, 1, 91}, {{4872, 408}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 74}, {{1740, 423}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 7, 81}, {{4596, 429}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 9, 74}, {{ 843, 431}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 91}, {{2156, 440}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 81}, {{2004, 441}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 81}, {{ 530, 442}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 92}, {{ 958, 468}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 5, 91}, {{2058, 475}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 81}, {{ 304, 477}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 1, 92}, {{ 522, 525}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), PKUNK_DEFINED, 3, 92}, {{2100, 554}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 81}, {{ 134, 565}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 92}, {{6858, 577}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), MYCON_TRAP_DEFINED, 0, 123}, {{5014, 584}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 73}, {{5256, 608}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 73}, {{2411, 718}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 9}, {{2589, 741}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 9}, {{ 675, 742}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 8, 91}, {{9292, 750}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 5}, {{1463, 779}, MAKE_STAR (GIANT_STAR, RED_BODY, -1), 0, 6, 80}, {{3089, 782}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 9}, {{2854, 787}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 9}, {{3333, 801}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 9}, {{9237, 821}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 5, 5}, {{9339, 843}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 5}, {{ 242, 857}, MAKE_STAR (GIANT_STAR, ORANGE_BODY, -1), 0, 3, 90}, {{1515, 866}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 80}, {{4770, 895}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 5, 75}, {{1412, 905}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 80}, {{4681, 916}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), RAINBOW_DEFINED, 6, 75}, {{9333, 937}, MAKE_STAR (SUPER_GIANT_STAR, YELLOW_BODY, -1), MELNORME0_DEFINED, 2, 5}, {{9419, 942}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 5}, {{ 230, 952}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 90}, {{ 146, 955}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 90}, {{4873, 968}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 75}, {{1559, 993}, MAKE_STAR (SUPER_GIANT_STAR, RED_BODY, -1), MELNORME1_DEFINED, 1, 80}, {{1895, 1041}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 93}, {{4337, 1066}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 75}, {{3732, 1067}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 0, 122}, {{1579, 1115}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 80}, {{4875, 1145}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 75}, {{4604, 1187}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 75}, {{5812, 1208}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 72}, {{1312, 1260}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 80}, {{1916, 1270}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 93}, {{6562, 1270}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 0, 121}, {{ 416, 1301}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 0, 120}, {{3958, 1354}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 89}, {{4000, 1363}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 89}, {{1752, 1450}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), SOL_DEFINED, 0, 129}, {{2187, 1500}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 127}, {{1806, 1507}, MAKE_STAR (GIANT_STAR, WHITE_BODY, -1), 0, 0, 128}, {{5708, 1520}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 72}, {{9469, 1548}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 6}, {{4333, 1562}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 88}, {{6041, 1562}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 72}, {{9375, 1583}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 6}, {{2881, 1614}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 96}, {{6083, 1625}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 72}, {{4250, 1645}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 88}, {{ 650, 1646}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 7, 85}, {{9477, 1670}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 6}, {{2840, 1676}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 96}, {{9541, 1687}, MAKE_STAR (GIANT_STAR, RED_BODY, -1), 0, 4, 6}, {{7395, 1687}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 69}, {{4333, 1687}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), VUX_DEFINED, 2, 88}, {{9559, 1735}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 6}, {{ 736, 1737}, MAKE_STAR (GIANT_STAR, BLUE_BODY, -1), 0, 6, 85}, {{1601, 1746}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 94}, {{7395, 1750}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 69}, {{ 951, 1770}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 1, 85}, {{1666, 1812}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 94}, {{7187, 1833}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 69}, {{ 705, 1838}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 85}, {{1140, 1847}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 85}, {{6467, 1878}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 71}, {{2791, 1895}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 96}, {{6500, 1916}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 71}, {{5458, 1916}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 0, 119}, {{1048, 1919}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 85}, {{3678, 1926}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 99}, {{3345, 1931}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), START_COLONY_DEFINED, 0, 98}, {{8187, 1937}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 4, 7}, {{3352, 1940}, MAKE_STAR (SUPER_GIANT_STAR, WHITE_BODY, -1), MELNORME2_DEFINED, 0, 97}, {{ 977, 1953}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 85}, {{4221, 1986}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), MAIDENS_DEFINED, 1, 100}, {{4500, 2000}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 100}, {{6833, 2000}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 70}, {{8163, 2009}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 7}, {{8080, 2011}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 7}, {{6036, 2035}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 4, 71}, {{6479, 2062}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), EGG_CASE1_DEFINED, 3, 71}, {{2104, 2083}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), ZOQ_SCOUT_DEFINED, 0, 118}, {{8062, 2083}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 7}, {{ 270, 2187}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 79}, {{6500, 2208}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 6, 71}, {{6291, 2208}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), MYCON_DEFINED, 5, 71}, {{ 125, 2229}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 79}, {{ 312, 2250}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 79}, {{3884, 2262}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 99}, {{ 742, 2268}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), CHMMR_DEFINED, 0, 117}, {{2306, 2285}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 95}, {{2402, 2309}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 95}, {{6395, 2312}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), SUN_DEVICE_DEFINED, 2, 12}, {{8875, 2312}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 9, 61}, {{3551, 2320}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 99}, {{6208, 2333}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 12}, {{3354, 2354}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 99}, {{9909, 2359}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 111}, {{2298, 2385}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 95}, {{7020, 2395}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 70}, {{9038, 2407}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 61}, {{9375, 2416}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 8, 61}, {{6500, 2458}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 12}, {{ 217, 2509}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 78}, {{3641, 2512}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 86}, {{5625, 2520}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 14}, {{3713, 2537}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), ORZ_DEFINED, 3, 86}, {{3587, 2566}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), ANDROSYNTH_DEFINED, 7, 86}, {{9291, 2583}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 61}, {{3654, 2587}, MAKE_STAR (SUPER_GIANT_STAR, GREEN_BODY, -1), MELNORME3_DEFINED, 1, 86}, {{3721, 2619}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), TAALO_PROTECTOR_DEFINED, 4, 86}, {{5791, 2625}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 14}, {{6416, 2625}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 12}, {{6008, 2631}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), EGG_CASE0_DEFINED, 2, 14}, {{3608, 2637}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 86}, {{3499, 2648}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 87}, {{9479, 2666}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 61}, {{3668, 2666}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 86}, {{ 229, 2666}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 78}, {{8895, 2687}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 61}, {{ 138, 2696}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 78}, {{5375, 2729}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 116}, {{6354, 2729}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), EGG_CASE2_DEFINED, 3, 12}, {{6458, 2750}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 12}, {{2458, 2750}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 106}, {{ 351, 2758}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 78}, {{7083, 2770}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 70}, {{3759, 2778}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 87}, {{9333, 2791}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 61}, {{3400, 2804}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 87}, {{9469, 2806}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), DRUUGE_DEFINED, 6, 61}, {{3619, 2830}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 87}, {{2208, 2854}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 106}, {{9250, 2854}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 4, 61}, {{ 672, 2863}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 78}, {{ 167, 2875}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 78}, {{4030, 2887}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 105}, {{ 384, 2900}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 78}, {{2727, 2951}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 5, 106}, {{4645, 2958}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 105}, {{5625, 2958}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 13}, {{8270, 2958}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 66}, {{8291, 2979}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 66}, {{6020, 2979}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), RAINBOW_DEFINED, 3, 13}, {{6562, 3020}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 4, 70}, {{2011, 3043}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 8, 106}, {{8125, 3083}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 66}, {{2354, 3166}, MAKE_STAR (GIANT_STAR, YELLOW_BODY, -1), 0, 4, 106}, {{3833, 3187}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 105}, {{5812, 3208}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 1, 13}, {{9000, 3250}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 0, 113}, {{ 291, 3250}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 84}, {{ 501, 3259}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 84}, {{ 791, 3270}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 84}, {{2354, 3291}, MAKE_STAR (SUPER_GIANT_STAR, RED_BODY, -1), MELNORME4_DEFINED, 1, 106}, {{1104, 3333}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 4, 84}, {{2687, 3333}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 106}, {{3187, 3375}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 107}, {{1758, 3418}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 108}, {{2520, 3437}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 106}, {{8437, 3458}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 64}, {{8770, 3458}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 64}, {{3000, 3500}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 107}, {{ 149, 3519}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 76}, {{8791, 3541}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 64}, {{2148, 3551}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 109}, {{7375, 3562}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 115}, {{9312, 3562}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 63}, {{9599, 3583}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 63}, {{9375, 3604}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 63}, {{ 90, 3614}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 6, 76}, {{2770, 3625}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 107}, {{8708, 3625}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 64}, {{ 267, 3645}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 76}, {{1604, 3645}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 108}, {{2274, 3663}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 109}, {{ 229, 3666}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), ILWRATH_DEFINED, 1, 76}, {{3083, 3674}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 107}, {{2416, 3687}, MAKE_STAR (GIANT_STAR, ORANGE_BODY, -1), SPATHI_DEFINED, 5, 109}, {{9333, 3708}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 63}, {{2250, 3708}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 109}, {{ 288, 3735}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 76}, {{2354, 3741}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 109}, {{2583, 3750}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 6, 109}, {{4125, 3770}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), SYREEN_DEFINED, 0, 114}, {{ 166, 3770}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 4, 76}, {{6270, 3833}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 10}, {{2145, 3916}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 110}, {{6125, 3937}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 10}, {{6291, 3937}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 9, 10}, {{5937, 3937}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), SHIP_VAULT_DEFINED, 5, 10}, {{2479, 3958}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 109}, {{ 926, 3972}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 83}, {{2062, 3991}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 110}, {{5895, 4020}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 8, 10}, {{ 285, 4020}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 77}, {{6062, 4041}, MAKE_STAR (GIANT_STAR, YELLOW_BODY, -1), 0, 1, 10}, {{2875, 4041}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 20}, {{8645, 4062}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 65}, {{ 860, 4065}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 83}, {{5958, 4083}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 10}, {{3038, 4083}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 20}, {{ 291, 4104}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 77}, {{6166, 4125}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 10}, {{9812, 4145}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 62}, {{8520, 4166}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 65}, {{9573, 4182}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 62}, {{ 500, 4187}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 77}, {{2145, 4208}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 110}, {{6208, 4229}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 10}, {{2812, 4250}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 20}, {{2937, 4306}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 4, 20}, {{9416, 4395}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 62}, {{2875, 4479}, MAKE_STAR (GIANT_STAR, WHITE_BODY, -1), 0, 1, 20}, {{ 250, 4583}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 26}, {{7250, 4583}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 68}, {{ 479, 4583}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 26}, {{5708, 4604}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 0, 104}, {{ 479, 4645}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 26}, {{2895, 4687}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 20}, {{2708, 4708}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 5, 20}, {{ 562, 4708}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 26}, {{ 416, 4717}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 26}, {{5094, 4931}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 11}, {{9000, 5000}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 67}, {{8958, 5000}, MAKE_STAR (GIANT_STAR, BLUE_BODY, -1), 0, 1, 67}, {{5006, 5011}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 11}, {{7312, 5062}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 68}, {{3679, 5068}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 17}, {{9062, 5083}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 67}, {{7416, 5083}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), RAINBOW_DEFINED, 3, 68}, {{5155, 5122}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 11}, {{3875, 5145}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 17}, {{4937, 5145}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 11}, {{2979, 5166}, MAKE_STAR (GIANT_STAR, ORANGE_BODY, -1), 0, 1, 15}, {{3035, 5178}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 15}, {{3994, 5185}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 17}, {{3541, 5187}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 17}, {{5977, 5246}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 102}, {{3770, 5250}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 17}, {{1520, 5261}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 55}, {{1613, 5279}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 55}, {{7020, 5291}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 68}, {{1416, 5315}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 55}, {{2993, 5318}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 15}, {{1425, 5404}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 55}, {{1854, 5416}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 5, 55}, {{3625, 5437}, MAKE_STAR (GIANT_STAR, GREEN_BODY, -1), 0, 1, 16}, {{3416, 5437}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 16}, {{4000, 5437}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), ZOQFOT_DEFINED, 1, 18}, {{6270, 5479}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 102}, {{3583, 5479}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 16}, {{4083, 5513}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 18}, {{2159, 5614}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 55}, {{3937, 5625}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 18}, {{6014, 5632}, MAKE_STAR (GIANT_STAR, BLUE_BODY, -1), 0, 1, 21}, {{ 250, 5687}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 25}, {{3625, 5750}, MAKE_STAR (GIANT_STAR, RED_BODY, -1), 0, 2, 19}, {{ 371, 5772}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 25}, {{6107, 5785}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 21}, {{9645, 5791}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), BURVIXESE_DEFINED, 0, 130}, {{1545, 5818}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 54}, {{3750, 5833}, MAKE_STAR (GIANT_STAR, GREEN_BODY, -1), 0, 1, 19}, {{6301, 5875}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 5, 21}, {{1923, 5878}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 54}, {{4625, 5895}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 131}, {{ 152, 5900}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 25}, {{5437, 5916}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 33}, {{1714, 5926}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 54}, {{6200, 5935}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), SAMATRA_DEFINED, 4, 21}, {{6429, 5958}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 7, 21}, {{4729, 5958}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 131}, {{1978, 5968}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), TALKING_PET_DEFINED, 2, 54}, {{ 395, 5979}, MAKE_STAR (GIANT_STAR, GREEN_BODY, -1), 0, 1, 22}, {{ 563, 5980}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 22}, {{ 456, 5989}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 22}, {{4625, 6000}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 131}, {{6166, 6000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 21}, {{6496, 6032}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 21}, {{2228, 6038}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 12, 54}, {{4583, 6041}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 131}, {{1558, 6058}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 6, 54}, {{1902, 6065}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 54}, {{2159, 6073}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 11, 54}, {{ 365, 6093}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 22}, {{ 541, 6145}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 22}, {{2200, 6176}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 10, 54}, {{ 729, 6208}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 23}, {{5250, 6229}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 33}, {{8166, 6250}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 40}, {{6215, 6255}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 8, 21}, {{ 437, 6270}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 22}, {{5583, 6291}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 33}, {{1881, 6308}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 8, 54}, {{1795, 6329}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 7, 54}, {{2118, 6379}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 9, 54}, {{ 750, 6458}, MAKE_STAR (GIANT_STAR, WHITE_BODY, -1), 0, 1, 23}, {{3716, 6458}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 30}, {{1360, 6489}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 56}, {{7333, 6500}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 40}, {{3770, 6500}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 30}, {{4500, 6500}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 0, 37}, {{ 187, 6520}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 24}, {{ 125, 6541}, MAKE_STAR (GIANT_STAR, RED_BODY, -1), 0, 1, 24}, {{7812, 6562}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 40}, {{ 770, 6602}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 23}, {{5910, 6624}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 29}, {{ 208, 6625}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 24}, {{2604, 6645}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 101}, {{1578, 6668}, MAKE_STAR (SUPER_GIANT_STAR, GREEN_BODY, -1), MELNORME5_DEFINED, 1, 56}, {{5479, 6687}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 33}, {{ 375, 6716}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 24}, {{ 312, 6728}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 24}, {{6020, 6729}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 29}, {{5062, 6750}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 10, 28}, {{4208, 6854}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 31}, {{5145, 6875}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 9, 28}, {{4291, 6937}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 31}, {{5145, 6958}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 8, 28}, {{7208, 7000}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 39}, {{8625, 7000}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), RAINBOW_DEFINED, 1, 41}, {{4955, 7034}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 28}, {{4895, 7041}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 28}, {{4971, 7104}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 28}, {{8666, 7104}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 41}, {{4854, 7125}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 28}, {{5083, 7145}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 7, 28}, {{7360, 7184}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 39}, {{1020, 7187}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 58}, {{3875, 7187}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 32}, {{4879, 7201}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 5, 28}, {{4958, 7229}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 6, 28}, {{7125, 7250}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 39}, {{7532, 7258}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 39}, {{2416, 7291}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 101}, {{3854, 7291}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 2, 32}, {{9687, 7333}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 44}, {{ 395, 7458}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), RAINBOW_DEFINED, 2, 60}, {{4895, 7458}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 36}, {{4645, 7479}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 36}, {{6940, 7514}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 11, 39}, {{7443, 7538}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 39}, {{6479, 7541}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 0, 38}, {{7208, 7541}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 1, 39}, {{5791, 7583}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 34}, {{ 333, 7625}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 60}, {{5958, 7645}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 34}, {{1041, 7708}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 58}, {{5875, 7729}, MAKE_STAR (SUPER_GIANT_STAR, YELLOW_BODY, -1), MELNORME6_DEFINED, 1, 34}, {{1125, 7791}, MAKE_STAR (GIANT_STAR, BLUE_BODY, -1), 0, 1, 58}, {{4979, 7791}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 2, 36}, {{4958, 7791}, MAKE_STAR (GIANT_STAR, WHITE_BODY, -1), 0, 1, 36}, {{6889, 7803}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 10, 39}, {{7200, 7849}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 8, 39}, {{7395, 7854}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 7, 39}, {{9437, 7854}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 44}, {{2836, 7857}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), RAINBOW_DEFINED, 5, 53}, {{5375, 7875}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 35}, {{6187, 7875}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 7, 35}, {{6041, 7916}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 35}, {{5979, 7979}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 35}, {{7083, 7993}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 9, 39}, {{3270, 8000}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 8, 53}, {{6104, 8000}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 35}, {{ 687, 8000}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 59}, {{ 562, 8000}, MAKE_STAR (GIANT_STAR, GREEN_BODY, -1), URQUAN_WRECK_DEFINED, 1, 59}, {{5645, 8020}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 35}, {{1395, 8041}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 58}, {{8229, 8041}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 43}, {{2518, 8056}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 3, 53}, {{5875, 8062}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 35}, {{8416, 8083}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 43}, {{9000, 8229}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 44}, {{3562, 8250}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 9, 53}, {{5437, 8270}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), RAINBOW_DEFINED, 5, 48}, {{1520, 8333}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 58}, {{2771, 8351}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 53}, {{2535, 8358}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), THRADD_DEFINED, 4, 53}, {{3151, 8390}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 7, 53}, {{2362, 8395}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 11, 53}, {{2822, 8395}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 53}, {{5500, 8395}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 48}, {{2536, 8504}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 4, 2}, {{2582, 8507}, MAKE_STAR (SUPER_GIANT_STAR, YELLOW_BODY, -1), MELNORME7_DEFINED, 1, 2}, {{8625, 8562}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 3}, {{4375, 8562}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 0, 50}, {{2593, 8569}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 2}, {{2562, 8572}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 2}, {{8492, 8578}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 7, 3}, {{1125, 8583}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 6, 58}, {{8073, 8588}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 46}, {{8560, 8638}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 3}, {{8750, 8645}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 5, 3}, {{5562, 8645}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 1, 48}, {{2588, 8653}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 14, 53}, {{2458, 8666}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 10, 53}, {{7666, 8666}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), RAINBOW_DEFINED, 2, 46}, {{2776, 8673}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), AQUA_HELIX_DEFINED, 6, 53}, {{8630, 8693}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), UTWIG_DEFINED, 2, 3}, {{2310, 8702}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 12, 53}, {{ 437, 8770}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 57}, {{8534, 8797}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), RAINBOW_DEFINED, 3, 3}, {{8588, 8812}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 4, 3}, {{7187, 8812}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 3, 46}, {{5475, 8823}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 48}, {{3050, 8833}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 4, 1}, {{2831, 8854}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 1}, {{2300, 8861}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 13, 53}, {{ 479, 8875}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 57}, {{2706, 8910}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 2, 1}, {{ 333, 8916}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 57}, {{2535, 8917}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 5, 1}, {{8322, 8934}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 1, 45}, {{8249, 8958}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 45}, {{8375, 8958}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 2, 45}, {{5645, 8979}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 4, 48}, {{2687, 9000}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 1}, {{8375, 9041}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 45}, {{9960, 9042}, MAKE_STAR (GIANT_STAR, WHITE_BODY, -1), RAINBOW_DEFINED, 0, 42}, {{7354, 9062}, MAKE_STAR (DWARF_STAR, BLUE_BODY, -1), 0, 1, 47}, {{7833, 9083}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 6, 47}, {{2581, 9105}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 1}, {{7545, 9107}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 3, 47}, {{7414, 9124}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), SUPOX_DEFINED, 2, 47}, {{8500, 9125}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 45}, {{ 104, 9125}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 5, 27}, {{7889, 9181}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 7, 47}, {{7791, 9187}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 47}, {{7791, 9229}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 5, 47}, {{4812, 9270}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 0, 51}, {{8500, 9372}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), BOMB_DEFINED, 6, 45}, {{7255, 9374}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 11, 45}, {{8458, 9393}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 7, 45}, {{1000, 9395}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 4, 27}, {{5711, 9475}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 2, 49}, {{ 62, 9479}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 3, 27}, {{5989, 9496}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 7, 49}, {{8000, 9505}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 9, 45}, {{5329, 9538}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 5, 49}, {{2916, 9541}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 103}, {{8296, 9548}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 8, 45}, {{5600, 9552}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 1, 49}, {{7664, 9589}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 10, 45}, {{6125, 9604}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 8, 49}, {{9144, 9686}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 4, 4}, {{5781, 9711}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 3, 49}, {{5229, 9729}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 49}, {{9120, 9741}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 3, 4}, {{9186, 9741}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 2, 4}, {{9159, 9745}, MAKE_STAR (SUPER_GIANT_STAR, BLUE_BODY, -1), MELNORME8_DEFINED, 1, 4}, {{ 333, 9750}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 0, 0}, {{9147, 9790}, MAKE_STAR (DWARF_STAR, ORANGE_BODY, -1), 0, 5, 4}, {{5704, 9795}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), VUX_BEAST_DEFINED, 4, 49}, {{ 333, 9812}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), SLYLANDRO_DEFINED, 2, 27}, {{1020, 9937}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 7, 27}, {{ 83, 9979}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 6, 27}, {{1937, 9979}, MAKE_STAR (DWARF_STAR, RED_BODY, -1), 0, 1, 103}, {{4395, 9979}, MAKE_STAR (DWARF_STAR, GREEN_BODY, -1), 0, 0, 52}, {{MAX_X_UNIVERSE << 1, MAX_Y_UNIVERSE << 1}, 0, 0, 0, 0}, // QuasiSpace locations #define VORTEX_SCALE 20 {{(-12* VORTEX_SCALE) + 5000, (-21 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{( 1 * VORTEX_SCALE) + 5000, (-20 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(-16 * VORTEX_SCALE) + 5000, (-18 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{( 8 * VORTEX_SCALE) + 5000, (-17 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{( 3 * VORTEX_SCALE) + 5000, (-13 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(-21 * VORTEX_SCALE) + 5000, (-4 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(-4 * VORTEX_SCALE) + 5000, (-4 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(-12 * VORTEX_SCALE) + 5000, (-2 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(-26 * VORTEX_SCALE) + 5000, (2 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(-17 * VORTEX_SCALE) + 5000, (7 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(10 * VORTEX_SCALE) + 5000, (7 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(15 * VORTEX_SCALE) + 5000, (14 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(22 * VORTEX_SCALE) + 5000, (16 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(-6 * VORTEX_SCALE) + 5000, (19 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{(10 * VORTEX_SCALE) + 5000, (20 * VORTEX_SCALE) + 5000}, MAKE_STAR (DWARF_STAR, WHITE_BODY, -1), 0, 0, 132}, {{6134, 5900}, MAKE_STAR (DWARF_STAR, YELLOW_BODY, -1), 0, 0, 132}, {{MAX_X_UNIVERSE << 1, MAX_Y_UNIVERSE << 1}, 0, 0, 0, 0}, }; const BYTE element_array[NUMBER_OF_ELEMENTS] = { COMMON, /* HYDROGEN */ COMMON, /* HELIUM */ COMMON, /* LITHIUM */ BASE_METAL, /* BERYLLIUM */ BASE_METAL, /* BORON */ COMMON, /* CARBON */ COMMON, /* NITROGEN */ CORROSIVE, /* OXYGEN */ CORROSIVE, /* FLUORINE */ NOBLE, /* NEON */ BASE_METAL, /* SODIUM */ BASE_METAL, /* MAGNESIUM */ BASE_METAL, /* ALUMINUM */ COMMON, /* SILICON */ COMMON, /* PHOSPHORUS */ CORROSIVE, /* SULFUR */ CORROSIVE, /* CHLORINE */ NOBLE, /* ARGON */ BASE_METAL, /* POTASSIUM */ BASE_METAL, /* CALCIUM */ BASE_METAL, /* SCANDIUM */ BASE_METAL, /* TITANIUM */ BASE_METAL, /* VANADIUM */ BASE_METAL, /* CHROMIUM */ BASE_METAL, /* MANGANESE */ BASE_METAL, /* IRON */ BASE_METAL, /* COBALT */ BASE_METAL, /* NICKEL */ BASE_METAL, /* COPPER */ BASE_METAL, /* ZINC */ BASE_METAL, /* GALLIUM */ BASE_METAL, /* GERMANIUM */ COMMON, /* ARSENIC */ COMMON, /* SELENIUM */ CORROSIVE, /* BROMINE */ NOBLE, /* KRYPTON */ BASE_METAL, /* RUBIDIUM */ BASE_METAL, /* STRONTIUM */ BASE_METAL, /* YTTRIUM */ BASE_METAL, /* ZIRCONIUM */ BASE_METAL, /* NIOBIUM */ BASE_METAL, /* MOLYBDENUM */ RADIOACTIVE, /* TECHNETIUM */ BASE_METAL, /* RUTHENIUM */ BASE_METAL, /* RHODIUM */ PRECIOUS, /* PALLADIUM */ PRECIOUS, /* SILVER */ BASE_METAL, /* CADMIUM */ BASE_METAL, /* INDIUM */ BASE_METAL, /* TIN */ BASE_METAL, /* ANTIMONY */ BASE_METAL, /* TELLURIUM */ CORROSIVE, /* IODINE */ NOBLE, /* XENON */ BASE_METAL, /* CESIUM */ BASE_METAL, /* BARIUM */ RARE_EARTH, /* LANTHANUM */ RARE_EARTH, /* CERIUM */ RARE_EARTH, /* PRASEODYMIUM */ RARE_EARTH, /* NEODYMIUM */ RARE_EARTH, /* PROMETHIUM */ RARE_EARTH, /* SAMARIUM */ RARE_EARTH, /* EUROPIUM */ RARE_EARTH, /* GADOLINIUM */ RARE_EARTH, /* TERBIUM */ RARE_EARTH, /* DYPROSIUM */ RARE_EARTH, /* HOLMIUM */ RARE_EARTH, /* ERBIUM */ RARE_EARTH, /* THULIUM */ RARE_EARTH, /* YTTERBIUM */ RARE_EARTH, /* LUTETIUM */ BASE_METAL, /* HAFNIUM */ BASE_METAL, /* TANTALUM */ BASE_METAL, /* TUNGSTEN */ BASE_METAL, /* RHENIUM */ BASE_METAL, /* OSMIUM */ PRECIOUS, /* IRIDIUM */ PRECIOUS, /* PLATINUM */ PRECIOUS, /* GOLD */ BASE_METAL, /* MERCURY */ BASE_METAL, /* THALLIUM */ BASE_METAL, /* LEAD */ BASE_METAL, /* BISMUTH */ RADIOACTIVE, /* POLONIUM */ RADIOACTIVE, /* ASTATINE */ NOBLE, /* RADON */ RADIOACTIVE, /* FRANCIUM */ RADIOACTIVE, /* RADIUM */ RADIOACTIVE, /* ACTINIUM */ RADIOACTIVE, /* THORIUM */ RADIOACTIVE, /* PROTACTINIUM */ RADIOACTIVE, /* URANIUM */ RADIOACTIVE, /* NEPTUNIUM */ RADIOACTIVE, /* PLUTONIUM */ COMMON, /* OZONE */ COMMON, /* FREE RADICALS */ COMMON, /* CARBON DIOXIDE */ COMMON, /* CARBON MONOXIDE */ COMMON, /* AMMONIA */ COMMON, /* METHANE */ COMMON, /* SULFURIC ACID */ COMMON, /* HYDROCHLORIC ACID */ COMMON, /* HYDROCYANIC ACID */ COMMON, /* FORMIC ACID */ COMMON, /* PHOSPHORIC ACID */ COMMON, /* FORMALDEHYDE */ COMMON, /* CYANOACETYLENE */ COMMON, /* METHANOL */ COMMON, /* ETHANOL */ COMMON, /* SILICON MONOXIDE */ COMMON, /* TITANIUM OXIDE */ COMMON, /* ZIRCONIUM OXIDE */ COMMON, /* WATER */ COMMON, /* SILICON COMPOUNDS */ COMMON, /* METAL OXIDES */ EXOTIC, /* QUANTUM BLACK HOLES */ EXOTIC, /* NEUTRONIUM */ EXOTIC, /* MAGNETIC MONOPOLES */ EXOTIC, /* DEGENERATE MATTER */ EXOTIC, /* SUPER FLUIDS */ EXOTIC, /* AGUUTI NODULES */ COMMON, /* IRON COMPOUNDS */ COMMON, /* ALUMINUM COMPOUNDS */ COMMON, /* NITROUS OXIDE */ COMMON, /* RADIOACTIVES */ COMMON, /* HYDROCARBONS */ COMMON, /* CARBON COMPOUNDS */ EXOTIC, /* ANTIMATTER */ EXOTIC, /* CHARON DUST */ EXOTIC, /* REISBURG HELICES */ EXOTIC, /* TZO CRYSTALS */ COMMON, /* CALCIUM COMPOUNDS */ COMMON, /* NITRIC ACID */ }; /*------------------------------ Global Data ------------------------------ */ #define NO_DEPOSIT 0 #define TRACE_USEFUL MINERAL_DEPOSIT (FEW, LIGHT) #define LIGHT_USEFUL MINERAL_DEPOSIT (MODERATE, LIGHT) #define MEDIUM_USEFUL MINERAL_DEPOSIT (MODERATE, MEDIUM) #define HEAVY_USEFUL MINERAL_DEPOSIT (MODERATE, HEAVY) #define HUGE_USEFUL MINERAL_DEPOSIT (NUMEROUS, HEAVY) const PlanetFrame planet_array[NUMBER_OF_PLANET_TYPES] = { { /* OOLITE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, VIOLET_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, HEAVY), /* Atmosphere and density */ { {HOLMIUM, MEDIUM_USEFUL}, {ERBIUM, MEDIUM_USEFUL}, {THULIUM, MEDIUM_USEFUL}, {YTTERBIUM, MEDIUM_USEFUL}, {LUTETIUM, MEDIUM_USEFUL}, {PALLADIUM, MEDIUM_USEFUL}, {SILVER, MEDIUM_USEFUL}, {IRIDIUM, MEDIUM_USEFUL}, }, OOLITE_COLOR_TAB, OOLITE_XLAT_TAB, 230, 2, 200, 150, }, { /* YTTRIC_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, VIOLET_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, MEDIUM), /* Atmosphere and density */ { {YTTERBIUM, HUGE_USEFUL}, {YTTRIUM, HUGE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, YTTRIC_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* QUASI_DEGENERATE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, GREEN_BODY), /* Color and type/size of planet */ MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, NOTHING), /* Atmosphere and density */ { {DEGENERATE_MATTER, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, QUASI_DEGENERATE_COLOR_TAB, QUASI_DEGENERATE_XLAT_TAB, 500, 1, 0, 160, }, { /* LANTHANIDE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, YELLOW_BODY), /* Color and type/size of planet */ HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, LIGHT), /* Atmosphere and density */ { {LANTHANUM, MEDIUM_USEFUL}, {CERIUM, MEDIUM_USEFUL}, {PRASEODYMIUM, MEDIUM_USEFUL}, {NEODYMIUM, MEDIUM_USEFUL}, {PROMETHIUM, MEDIUM_USEFUL}, {SAMARIUM, MEDIUM_USEFUL}, {GADOLINIUM, MEDIUM_USEFUL}, {TERBIUM, MEDIUM_USEFUL}, }, LANTHANIDE_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* TREASURE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, YELLOW_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (SUPER_DENSITY, LIGHT), /* Atmosphere and density */ { {PALLADIUM, HEAVY_USEFUL}, {SILVER, HEAVY_USEFUL}, {SILVER, HEAVY_USEFUL}, {IRIDIUM, HEAVY_USEFUL}, {GOLD, HEAVY_USEFUL}, {PLATINUM, HEAVY_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, TREASURE_COLOR_TAB, QUASI_DEGENERATE_XLAT_TAB, 500, 1, 0, 160, }, { /* UREA_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, YELLOW_BODY), /* Color and type/size of planet */ HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, HEAVY), /* Atmosphere and density */ { {AMMONIA, LIGHT_USEFUL}, {FORMALDEHYDE, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, UREA_COLOR_TAB, UREA_XLAT_TAB, 230, 2, 200, 150, }, { /* METAL_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, ORANGE_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, HEAVY), /* Atmosphere and density */ { {IRON, HUGE_USEFUL}, {NICKEL, HEAVY_USEFUL}, {VANADIUM, MEDIUM_USEFUL}, {SILVER, MEDIUM_USEFUL}, {URANIUM, HEAVY_USEFUL}, {SULFUR, MEDIUM_USEFUL}, {COPPER, HEAVY_USEFUL}, {NOTHING, NO_DEPOSIT}, }, METAL_COLOR_TAB, METAL_XLAT_TAB, 230, 2, 200, 150, }, { /* RADIOACTIVE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, ORANGE_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (SUPER_DENSITY, LIGHT), /* Atmosphere and density */ { {ASTATINE, MEDIUM_USEFUL}, {FRANCIUM, MEDIUM_USEFUL}, {RADIUM, MEDIUM_USEFUL}, {ACTINIUM, MEDIUM_USEFUL}, {THORIUM, MEDIUM_USEFUL}, {PROTACTINIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, RADIOACTIVE_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* OPALESCENT_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, CYAN_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, NOTHING), /* Atmosphere and density */ { {SAMARIUM, LIGHT_USEFUL}, {GADOLINIUM, LIGHT_USEFUL}, {ARGON, LIGHT_USEFUL}, {LITHIUM, LIGHT_USEFUL}, {SILICON, LIGHT_USEFUL}, {ARSENIC, LIGHT_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, OPALESCENT_COLOR_TAB, OPALESCENT_XLAT_TAB, 400, 1, 100, 190, }, { /* CYANIC_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, GREEN_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LIGHT_DENSITY, LIGHT), /* Atmosphere and density */ { {CYANOACETYLENE, HUGE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, CYANIC_COLOR_TAB, QUASI_DEGENERATE_XLAT_TAB, 500, 1, 0, 160, }, { /* ACID_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, GREEN_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ { {SULFURIC_ACID, HEAVY_USEFUL}, {HYDROCHLORIC_ACID, HEAVY_USEFUL}, {FORMIC_ACID, HEAVY_USEFUL}, {HYDROCYANIC_ACID, HEAVY_USEFUL}, {PHOSPHORIC_ACID, HEAVY_USEFUL}, {NITRIC_ACID, HEAVY_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, ACID_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* ALKALI_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, GREEN_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, MEDIUM), /* Atmosphere and density */ { {CALCIUM, MEDIUM_USEFUL}, {BARIUM, MEDIUM_USEFUL}, {STRONTIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, ALKALI_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* HALIDE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, GREEN_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ { {FLUORINE, MEDIUM_USEFUL}, {BROMINE, MEDIUM_USEFUL}, {BROMINE, MEDIUM_USEFUL}, {ASTATINE, MEDIUM_USEFUL}, {IODINE, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, HALIDE_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* GREEN_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, GREEN_BODY), /* Color and type/size of planet */ MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, HEAVY), /* Atmosphere and density */ { {PRASEODYMIUM, HEAVY_USEFUL}, {NEODYMIUM, HEAVY_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, GREEN_COLOR_TAB, UREA_XLAT_TAB, 230, 2, 200, 150, }, { /* COPPER_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, GREEN_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, MEDIUM), /* Atmosphere and density */ { {COPPER, HUGE_USEFUL}, {COPPER, HUGE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, COPPER_COLOR_TAB, QUASI_DEGENERATE_XLAT_TAB, 500, 1, 0, 160, }, { /* CARBIDE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, RED_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ { {CARBON, HEAVY_USEFUL}, {CARBON, HEAVY_USEFUL}, {CARBON, HEAVY_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, CARBIDE_COLOR_TAB, OPALESCENT_XLAT_TAB, 400, 1, 100, 190, }, { /* ULTRAMARINE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, BLUE_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LIGHT_DENSITY, HEAVY), /* Atmosphere and density */ { {KRYPTON, MEDIUM_USEFUL}, {COBALT, MEDIUM_USEFUL}, {HOLMIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, ULTRAMARINE_COLOR_TAB, UREA_XLAT_TAB, 200, 2, 100, 100, }, { /* NOBLE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, BLUE_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LIGHT_DENSITY, LIGHT), /* Atmosphere and density */ { {NEON, LIGHT_USEFUL}, {RADON, LIGHT_USEFUL}, {ARGON, LIGHT_USEFUL}, {KRYPTON, LIGHT_USEFUL}, {XENON, LIGHT_USEFUL}, {HELIUM, LIGHT_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, NOBLE_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* AZURE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, BLUE_BODY), /* Color and type/size of planet */ MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, MEDIUM), /* Atmosphere and density */ { {INDIUM, LIGHT_USEFUL}, {MOLYBDENUM, LIGHT_USEFUL}, {VANADIUM, LIGHT_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, AZURE_COLOR_TAB, UREA_XLAT_TAB, 230, 2, 200, 150, }, { /* CHONDRITE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, PURPLE_BODY), /* Color and type/size of planet */ HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, NOTHING), /* Atmosphere and density */ { {ETHANOL, HEAVY_USEFUL}, {FREE_RADICALS, HEAVY_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, CHONDRITE_COLOR_TAB, CHONDRITE_XLAT_TAB, 500, 1, 100, 190, }, { /* PURPLE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, PURPLE_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ { {RHENIUM, MEDIUM_USEFUL}, {CADMIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, PURPLE_COLOR_TAB, UREA_XLAT_TAB, 230, 2, 200, 150, }, { /* SUPER_DENSE_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, PURPLE_BODY), /* Color and type/size of planet */ HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (SUPER_DENSITY, HEAVY), /* Atmosphere and density */ { {LEAD, MEDIUM_USEFUL}, {OSMIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, SUPER_DENSE_COLOR_TAB, QUASI_DEGENERATE_XLAT_TAB, 500, 1, 0, 160, }, { /* PELLUCID_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, PURPLE_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ { {TZO_CRYSTALS, TRACE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, PELLUCID_COLOR_TAB, OPALESCENT_XLAT_TAB, 400, 1, 100, 190, }, { /* DUST_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, RED_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, MEDIUM), /* Atmosphere and density */ { {BISMUTH, LIGHT_USEFUL}, {ALUMINUM, LIGHT_USEFUL}, {POTASSIUM, LIGHT_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, DUST_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* CRIMSON_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, RED_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, HEAVY), /* Atmosphere and density */ { {BARIUM, LIGHT_USEFUL}, {BORON, LIGHT_USEFUL}, {BERYLLIUM, LIGHT_USEFUL}, {BISMUTH, LIGHT_USEFUL}, {BROMINE, LIGHT_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, MAROON_COLOR_TAB, UREA_XLAT_TAB, 230, 2, 200, 150, }, { /* CIMMERIAN_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, RED_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, NOTHING), /* Atmosphere and density */ { {METHANE, MEDIUM_USEFUL}, {AMMONIA, MEDIUM_USEFUL}, {METHANOL, MEDIUM_USEFUL}, {LITHIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, CIMMERIAN_COLOR_TAB, QUASI_DEGENERATE_XLAT_TAB, 500, 1, 0, 160, }, { /* INFRARED_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, RED_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, HEAVY), /* Atmosphere and density */ { {MERCURY, HEAVY_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, INFRARED_COLOR_TAB, OPALESCENT_XLAT_TAB, 400, 1, 100, 190, }, { /* SELENIC_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + CRATERED_ALGO, WHITE_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ { {IRON, LIGHT_USEFUL}, {ALUMINUM, LIGHT_USEFUL}, {CALCIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, SELENIC_COLOR_TAB, UREA_XLAT_TAB, 230, 2, 200, 150, }, { /* AURIC_WORLD */ MAKE_BYTE (SMALL_ROCKY_WORLD + TOPO_ALGO, YELLOW_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, MEDIUM), /* Atmosphere and density */ { {GOLD, HUGE_USEFUL}, {GOLD, HUGE_USEFUL}, {GOLD, HUGE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, AURIC_COLOR_TAB, QUASI_DEGENERATE_XLAT_TAB, 500, 1, 0, 160, }, { /* FLUORESCENT_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, VIOLET_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, LIGHT), /* Atmosphere and density */ { {TECHNETIUM, HUGE_USEFUL}, {NEON, HUGE_USEFUL}, {RADON, LIGHT_USEFUL}, {POTASSIUM, LIGHT_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, FLUORESCENT_COLOR_TAB, OPALESCENT_XLAT_TAB, 400, 1, 100, 190, }, { /* ULTRAVIOLET_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, VIOLET_BODY), /* Color and type/size of planet */ MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, HEAVY), /* Atmosphere and density */ { {POLONIUM, HUGE_USEFUL}, {GOLD, HUGE_USEFUL}, {PHOSPHORUS, HUGE_USEFUL}, {SCANDIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, ULTRAVIOLET_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* PLUTONIC_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, YELLOW_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, HEAVY), /* Atmosphere and density */ { {BERYLLIUM, HUGE_USEFUL}, {BORON, HUGE_USEFUL}, {LANTHANUM, MEDIUM_USEFUL}, {ASTATINE, MEDIUM_USEFUL}, {FRANCIUM, MEDIUM_USEFUL}, {TITANIUM, LIGHT_USEFUL}, {CERIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, }, PLUTONIC_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* RAINBOW_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, YELLOW_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ { {ACTINIUM, HEAVY_USEFUL}, {THORIUM, HEAVY_USEFUL}, {PROTACTINIUM, HEAVY_USEFUL}, {NEPTUNIUM, HEAVY_USEFUL}, {PLUTONIUM, HEAVY_USEFUL}, {OZONE, HUGE_USEFUL}, {OZONE, HUGE_USEFUL}, {NOTHING, NO_DEPOSIT}, }, RAINBOW_COLOR_TAB, RAINBOW_XLAT_TAB, 500, 1, 20, 100, }, { /* CRACKED_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, ORANGE_BODY), /* Color and type/size of planet */ SUPER_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, NOTHING), /* Atmosphere and density */ { {PALLADIUM, HUGE_USEFUL}, {IRIDIUM, HUGE_USEFUL}, {TECHNETIUM, HUGE_USEFUL}, {POLONIUM, HUGE_USEFUL}, {SODIUM, HUGE_USEFUL}, {MANGANESE, HUGE_USEFUL}, {CHROMIUM, HUGE_USEFUL}, {NOTHING, NO_DEPOSIT}, }, CRACKED_COLOR_TAB, CRACKED_XLAT_TAB, 500, 1, 0, 185, }, { /* SAPPHIRE_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, CYAN_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, NOTHING), /* Atmosphere and density */ { {REISBURG_HELICES, HUGE_USEFUL}, {RT_SUPER_FLUID, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, SAPPHIRE_COLOR_TAB, SAPPHIRE_XLAT_TAB, 80, 1, 0, 128, }, { /* ORGANIC_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, CYAN_BODY), /* Color and type/size of planet */ MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ { {FREE_RADICALS, HEAVY_USEFUL}, {FORMALDEHYDE, HEAVY_USEFUL}, {CARBON, HEAVY_USEFUL}, {CARBON_DIOXIDE, HEAVY_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, ORGANIC_COLOR_TAB, QUASI_DEGENERATE_XLAT_TAB, 500, 1, 0, 160, }, { /* XENOLITHIC_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, CYAN_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, MEDIUM), /* Atmosphere and density */ { {ALUMINUM, HUGE_USEFUL}, {PLATINUM, LIGHT_USEFUL}, {GERMANIUM, TRACE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, XENOLITHIC_COLOR_TAB, OPALESCENT_XLAT_TAB, 400, 1, 100, 190, }, { /* REDUX_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, GREEN_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ { {BROMINE, MEDIUM_USEFUL}, {OXYGEN, MEDIUM_USEFUL}, {FLUORINE, MEDIUM_USEFUL}, {SULFUR, MEDIUM_USEFUL}, {CHLORINE, MEDIUM_USEFUL}, {IODINE, MEDIUM_USEFUL}, {ZIRCONIUM, LIGHT_USEFUL}, {NOTHING, NO_DEPOSIT}, }, REDUX_COLOR_TAB, REDUX_XLAT_TAB, 500, 1, 0, 190, }, { /* PRIMORDIAL_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, GREEN_BODY), /* Color and type/size of planet */ SUPER_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, HEAVY), /* Atmosphere and density */ { {CESIUM, MEDIUM_USEFUL}, {BARIUM, MEDIUM_USEFUL}, {RUBIDIUM, MEDIUM_USEFUL}, {METHANE, HUGE_USEFUL}, {AMMONIA, HUGE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, PRIMORDIAL_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 10, 200, }, { /* EMERALD_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, GREEN_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, NOTHING), /* Atmosphere and density */ { {AGUUTI_NODULES, HUGE_USEFUL}, {ANTIMATTER, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, EMERALD_COLOR_TAB, SAPPHIRE_XLAT_TAB, 80, 1, 0, 128, }, { /* CHLORINE_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, GREEN_BODY), /* Color and type/size of planet */ HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ { {CHLORINE, HEAVY_USEFUL}, {CHLORINE, HEAVY_USEFUL}, {HYDROCHLORIC_ACID, HEAVY_USEFUL}, {HYDROCHLORIC_ACID, HEAVY_USEFUL}, {ZINC, LIGHT_USEFUL}, {GALLIUM, TRACE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, CHLORINE_COLOR_TAB, CHLORINE_XLAT_TAB, 500, 1, 0, 190, }, { /* MAGNETIC_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, GREEN_BODY), /* Color and type/size of planet */ HIGH_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, NOTHING), /* Atmosphere and density */ { {ZINC, HEAVY_USEFUL}, {NICKEL, MEDIUM_USEFUL}, {MAGNETIC_MONOPOLES, TRACE_USEFUL}, {NIOBIUM, LIGHT_USEFUL}, {IRON, HEAVY_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, MAGNETIC_COLOR_TAB, OPALESCENT_XLAT_TAB, 400, 1, 100, 190, }, { /* WATER_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, BLUE_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, MEDIUM), /* Atmosphere and density */ { {IRON, LIGHT_USEFUL}, {ALUMINUM, LIGHT_USEFUL}, {TIN, LIGHT_USEFUL}, {LEAD, LIGHT_USEFUL}, {URANIUM, TRACE_USEFUL}, {MOLYBDENUM, TRACE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, WATER_COLOR_TAB, CHLORINE_XLAT_TAB, 500, 1, 0, 190, }, { /* TELLURIC_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, BLUE_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, HEAVY), /* Atmosphere and density */ { {IRIDIUM, MEDIUM_USEFUL}, {RUTHENIUM, MEDIUM_USEFUL}, {THALLIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, TELLURIC_COLOR_TAB, YTTRIC_XLAT_TAB, 250, 2, 80, 200, }, { /* HYDROCARBON_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, BLUE_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, LIGHT), /* Atmosphere and density */ { {HYDROCARBONS, HUGE_USEFUL}, {BISMUTH, LIGHT_USEFUL}, {TANTALUM, TRACE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, HYDROCARBON_COLOR_TAB, QUASI_DEGENERATE_XLAT_TAB, 500, 1, 0, 160, }, { /* IODINE_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, GREEN_BODY), /* Color and type/size of planet */ MED_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, MEDIUM), /* Atmosphere and density */ { {IODINE, HEAVY_USEFUL}, {MAGNESIUM, LIGHT_USEFUL}, {TUNGSTEN, TRACE_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, IODINE_COLOR_TAB, UREA_XLAT_TAB, 230, 2, 200, 150, }, { /* VINYLOGOUS_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, PURPLE_BODY), /* Color and type/size of planet */ LOW_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (NORMAL_DENSITY, NOTHING), /* Atmosphere and density */ { {TITANIUM, LIGHT_USEFUL}, {ARSENIC, LIGHT_USEFUL}, {POTASSIUM, LIGHT_USEFUL}, {RHENIUM, LIGHT_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, VINYLOGOUS_COLOR_TAB, OPALESCENT_XLAT_TAB, 400, 1, 100, 190, }, { /* RUBY_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, RED_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, LIGHT), /* Atmosphere and density */ { {TZO_CRYSTALS, HUGE_USEFUL}, {NEUTRONIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, RUBY_COLOR_TAB, SAPPHIRE_XLAT_TAB, 80, 1, 0, 128, }, { /* MAGMA_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + TOPO_ALGO, RED_BODY), /* Color and type/size of planet */ SUPER_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (HIGH_DENSITY, LIGHT), /* Atmosphere and density */ { {LEAD, LIGHT_USEFUL}, {NICKEL, LIGHT_USEFUL}, {IRON, LIGHT_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, MAGMA_COLOR_TAB, QUASI_DEGENERATE_XLAT_TAB, 500, 1, 0, 160, }, { /* MAROON_WORLD */ MAKE_BYTE (LARGE_ROCKY_WORLD + CRATERED_ALGO, RED_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (LOW_DENSITY, MEDIUM), /* Atmosphere and density */ { {CESIUM, MEDIUM_USEFUL}, {SILICON, MEDIUM_USEFUL}, {PHOSPHORUS, MEDIUM_USEFUL}, {RHODIUM, MEDIUM_USEFUL}, {CADMIUM, MEDIUM_USEFUL}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, CRIMSON_COLOR_TAB, UREA_XLAT_TAB, 230, 2, 200, 150, }, { MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, BLUE_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ { {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, BLU_GAS_COLOR_TAB, GAS_XLAT_TAB, 10, 2, 8, 29, }, { MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, CYAN_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ { {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, CYA_GAS_COLOR_TAB, GAS_XLAT_TAB, 10, 2, 8, 29, }, { MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, GREEN_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ { {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, GRN_GAS_COLOR_TAB, GAS_XLAT_TAB, 10, 2, 8, 29, }, { MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, GRAY_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ { {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, GRY_GAS_COLOR_TAB, GAS_XLAT_TAB, 10, 2, 8, 29, }, { MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, ORANGE_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ { {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, ORA_GAS_COLOR_TAB, GAS_XLAT_TAB, 10, 2, 8, 29, }, { MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, PURPLE_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ { {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, PUR_GAS_COLOR_TAB, GAS_XLAT_TAB, 10, 2, 8, 29, }, { MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, RED_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ { {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, RED_GAS_COLOR_TAB, GAS_XLAT_TAB, 10, 2, 8, 29, }, { MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, VIOLET_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ { {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, VIO_GAS_COLOR_TAB, GAS_XLAT_TAB, 10, 2, 8, 29, }, { /* A Jupiter-like World */ MAKE_BYTE (GAS_GIANT + GAS_GIANT_ALGO, YELLOW_BODY), /* Color and type/size of planet */ NO_TECTONICS, /* Tectonics - Scaled with Earth at 82 */ MAKE_BYTE (GAS_DENSITY, HEAVY), /* Atmosphere and density */ { {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, {NOTHING, NO_DEPOSIT}, }, YEL_GAS_COLOR_TAB, GAS_XLAT_TAB, 10, 2, 8, 29, }, }; uqm-0.6.2/sc2/src/sc2code/battle.c0000600000175000017500000003031310543202102015213 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "battle.h" #include "controls.h" #include "init.h" #include "intel.h" #ifdef NETPLAY # include "netplay/netmelee.h" # ifdef NETPLAY_CHECKSUM # include "netplay/checksum.h" # endif #endif #include "resinst.h" #include "nameref.h" #include "setup.h" #include "settings.h" #include "sounds.h" #include "libs/graphics/gfx_common.h" #include "libs/log.h" #include "libs/mathlib.h" QUEUE disp_q; SIZE battle_counter; BOOLEAN instantVictory; size_t battleInputOrder[NUM_SIDES]; // Indices of the sides in the order their input is processed. // Network sides are last so that the sides will never be waiting // on eachother, and games with a 0 frame delay are theoretically // possible. #ifdef NETPLAY BattleFrameCounter battleFrameCount; // Used for synchronisation purposes during netplay. COUNT currentDeadSide; // When a ship has been destroyed, each side of a network // connection waits until the other side is ready. // When two ships die at the same time, this is handled for one // ship after the other. This variable indicate for which player // we're currently doing this. #endif static BOOLEAN RunAwayAllowed (void) { return (LOBYTE (GLOBAL (CurrentActivity)) == IN_ENCOUNTER || LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) && GET_GAME_STATE (STARBASE_AVAILABLE) && !GET_GAME_STATE (BOMB_CARRIER); } static void DoRunAway (STARSHIPPTR StarShipPtr) { ELEMENTPTR ElementPtr; LockElement (StarShipPtr->hShip, &ElementPtr); if (GetPrimType (&DisplayArray[ElementPtr->PrimIndex]) == STAMP_PRIM && ElementPtr->life_span == NORMAL_LIFE && !(ElementPtr->state_flags & FINITE_LIFE) && ElementPtr->mass_points != MAX_SHIP_MASS * 10 && !(ElementPtr->state_flags & APPEARING)) { extern void flee_preprocess (PELEMENT); battle_counter -= MAKE_WORD (1, 0); ElementPtr->turn_wait = 3; ElementPtr->thrust_wait = MAKE_BYTE (4, 0); ElementPtr->preprocess_func = flee_preprocess; ElementPtr->mass_points = MAX_SHIP_MASS * 10; ZeroVelocityComponents (&ElementPtr->velocity); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); SetPrimColor (&DisplayArray[ElementPtr->PrimIndex], BUILD_COLOR (MAKE_RGB15 (0x0B, 0x00, 0x00), 0x2E)); SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMPFILL_PRIM); CyborgDescPtr->ship_input_state = 0; } UnlockElement (StarShipPtr->hShip); } static void setupBattleInputOrder(void) { size_t i; #ifndef NETPLAY for (i = 0; i < NUM_SIDES; i++) battleInputOrder[i] = i; #else int j; i = 0; // First put the locally controlled players in the array. for (j = 0; j < NUM_SIDES; j++) { if (!(PlayerControl[j] & NETWORK_CONTROL)) { battleInputOrder[i] = j; i++; } } // Next put the network controlled players in the array. for (j = 0; j < NUM_SIDES; j++) { if (PlayerControl[j] & NETWORK_CONTROL) { battleInputOrder[i] = j; i++; } } #endif } static void ProcessInput (void) { BOOLEAN CanRunAway; size_t sideI; #ifdef NETPLAY netInput (); #endif CanRunAway = RunAwayAllowed (); for (sideI = 0; sideI < NUM_SIDES; sideI++) { HSTARSHIP hBattleShip, hNextShip; cur_player = battleInputOrder[sideI]; for (hBattleShip = GetHeadLink (&race_q[cur_player]); hBattleShip != 0; hBattleShip = hNextShip) { BATTLE_INPUT_STATE InputState; STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip (&race_q[cur_player], hBattleShip); hNextShip = _GetSuccLink (StarShipPtr); if (StarShipPtr->hShip) { CyborgDescPtr = StarShipPtr; InputState = (*(PlayerInput[cur_player]))(cur_player, StarShipPtr); #if CREATE_JOURNAL JournalInput (InputState); #endif /* CREATE_JOURNAL */ #ifdef NETPLAY if (!(PlayerControl[cur_player] & NETWORK_CONTROL)) { BattleInputBuffer *bib = getBattleInputBuffer(cur_player); sendBattleInputConnections (InputState); flushPacketQueues (); BattleInputBuffer_push (bib, InputState); // Add this input to the end of the buffer. BattleInputBuffer_pop (bib, &InputState); // Get the input from the front of the buffer. } #endif CyborgDescPtr->ship_input_state = 0; if (CyborgDescPtr->RaceDescPtr->ship_info.crew_level) { if (InputState & BATTLE_LEFT) CyborgDescPtr->ship_input_state |= LEFT; else if (InputState & BATTLE_RIGHT) CyborgDescPtr->ship_input_state |= RIGHT; if (InputState & BATTLE_THRUST) CyborgDescPtr->ship_input_state |= THRUST; if (InputState & BATTLE_WEAPON) CyborgDescPtr->ship_input_state |= WEAPON; if (InputState & BATTLE_SPECIAL) CyborgDescPtr->ship_input_state |= SPECIAL; if (CanRunAway && cur_player == 0 && (InputState & BATTLE_ESCAPE)) DoRunAway (StarShipPtr); } } UnlockStarShip (&race_q[cur_player], hBattleShip); } } #ifdef NETPLAY flushPacketQueues (); #endif if (GLOBAL (CurrentActivity) & (CHECK_LOAD | CHECK_ABORT)) GLOBAL (CurrentActivity) &= ~IN_BATTLE; } #if DEMO_MODE || CREATE_JOURNAL DWORD BattleSeed; #endif /* DEMO_MODE */ static MUSIC_REF BattleRef; void BattleSong (BOOLEAN DoPlay) { if (BattleRef == 0) { if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) BattleRef = LoadMusic (BATTLE_MUSIC); else if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) BattleRef = LoadMusic (HYPERSPACE_MUSIC); else BattleRef = LoadMusic (QUASISPACE_MUSIC); } if (DoPlay) PlayMusic (BattleRef, TRUE, 1); } void FreeBattleSong (void) { DestroyMusic (BattleRef); BattleRef = 0; } static BOOLEAN DoBattle (BATTLE_STATE *bs) { extern UWORD nth_frame; RECT r; BYTE battle_speed; bs->MenuRepeatDelay = 0; SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); #if defined (NETPLAY) && defined (NETPLAY_CHECKSUM) if (getNumNetConnections() > 0 && battleFrameCount % NETPLAY_CHECKSUM_INTERVAL == 0) { crc_State state; Checksum checksum; crc_init(&state); crc_processState (&state); checksum = (Checksum) crc_finish (&state); sendChecksumConnections ((uint32) battleFrameCount, (uint32) checksum); flushPacketQueues (); addLocalChecksum (battleFrameCount, checksum); } #endif ProcessInput (); // Also calls NetInput() #if defined (NETPLAY) && defined (NETPLAY_CHECKSUM) if (getNumNetConnections() > 0) { size_t delay = getBattleInputDelay(); if (battleFrameCount >= delay && (battleFrameCount - delay) % NETPLAY_CHECKSUM_INTERVAL == 0) { if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) { if (!verifyChecksums (battleFrameCount - delay)) { GLOBAL(CurrentActivity) |= CHECK_ABORT; resetConnections (ResetReason_syncLoss); } } } } #endif LockMutex (GraphicsLock); if (bs->first_time) { r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT; SetTransitionSource (&r); } BatchGraphics (); if ((LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) && !(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) SeedUniverse (); RedrawQueue (TRUE); if (bs->first_time) { bs->first_time = FALSE; ScreenTransition (3, &r); } UnbatchGraphics (); UnlockMutex (GraphicsLock); if ((!(GLOBAL (CurrentActivity) & IN_BATTLE)) || (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { return FALSE; } battle_speed = HIBYTE (nth_frame); if (battle_speed == (BYTE)~0) { // maximum speed, nothing rendered at all TaskSwitch (); } else { SleepThreadUntil (bs->NextTime + BATTLE_FRAME_RATE / (battle_speed + 1)); bs->NextTime = GetTimeCounter (); } if ((GLOBAL (CurrentActivity) & IN_BATTLE) == 0) return FALSE; #ifdef NETPLAY battleFrameCount++; #endif return TRUE; } // Let each player pick his ship. static BOOLEAN selectAllShips (SIZE num_ships) { #ifndef NETPLAY while (num_ships--) { if (!GetNextStarShip (NULL_PTR, num_ships == 1)) return FALSE; } return TRUE; #else // On network play, what is the top player to one party may be // the bottom player the other. To keep both sides synchronised // the order is always the same. SIZE order[2]; if (num_ships == 1) { // HyperSpace in full game. return GetNextStarShip (NULL_PTR, 0); } if (num_ships != 2) { log_add (log_Error, "More than two players is not supported.\n"); return FALSE; } if ((PlayerControl[0] & NETWORK_CONTROL) && (PlayerControl[1] & NETWORK_CONTROL)) { log_add (log_Error, "Only one side at a time can be network " "controlled.\n"); return FALSE; } // Iff 'myTurn' is set on a connection, the local party will be // processed first. // If neither is network controlled, the top player (1) is handled first. if (((PlayerControl[0] & NETWORK_CONTROL) && !NetConnection_getDiscriminant (netConnections[0])) || ((PlayerControl[1] & NETWORK_CONTROL) && NetConnection_getDiscriminant (netConnections[1]))) { order[0] = 0; order[1] = 1; } else { order[0] = 1; order[1] = 0; } { size_t i; for (i = 0; i < 2; i++) { if (!GetNextStarShip (NULL_PTR, order[i])) return FALSE; } } return TRUE; #endif } BOOLEAN Battle (void) { SIZE num_ships; LockMutex (GraphicsLock); SetResourceIndex (hResIndex); #if !(DEMO_MODE || CREATE_JOURNAL) if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE) { // In Supermelee, the RNG is already initialised. TFB_SeedRandom (GetTimeCounter ()); } #else /* DEMO_MODE */ if (BattleSeed == 0) BattleSeed = TFB_Random (); TFB_SeedRandom (BattleSeed); BattleSeed = TFB_Random (); /* get next battle seed */ #endif /* DEMO_MODE */ BattleSong (FALSE); num_ships = InitShips (); if (instantVictory) { num_ships = 0; // no ships were harmed in the making of this battle battle_counter = 1; // a winner is you! instantVictory = FALSE; } if (num_ships) { BATTLE_STATE bs; GLOBAL (CurrentActivity) |= IN_BATTLE; battle_counter = MAKE_WORD ( CountLinks (&race_q[0]), CountLinks (&race_q[1]) ); setupBattleInputOrder (); #ifdef NETPLAY initBattleInputBuffers (); #ifdef NETPLAY_CHECKSUM initChecksumBuffers (); #endif /* NETPLAY_CHECKSUM */ battleFrameCount = 0; currentDeadSide = (COUNT)~0; setBattleStateConnections (&bs); #endif /* NETPLAY */ if (!selectAllShips (num_ships)) { GLOBAL (CurrentActivity) |= CHECK_ABORT; goto AbortBattle; } BattleSong (TRUE); bs.NextTime = 0; #ifdef NETPLAY initBattleStateDataConnections (); { bool allOk = negotiateReadyConnections (true, NetState_inBattle); if (!allOk) { GLOBAL (CurrentActivity) |= CHECK_ABORT; goto AbortBattle; } } #endif /* NETPLAY */ bs.InputFunc = DoBattle; bs.first_time = (BOOLEAN)(LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE); UnlockMutex (GraphicsLock); DoInput ((PVOID)&bs, FALSE); LockMutex (GraphicsLock); AbortBattle: if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE && (GLOBAL (CurrentActivity) & CHECK_ABORT)) { // Do not return to the main menu when a game is aborted, // (just to the supermelee menu). #ifdef NETPLAY UnlockMutex (GraphicsLock); waitResetConnections(NetState_inSetup); // A connection may already be in inSetup (set from // GetMeleeStarship). This is not a problem, although // it will generate a warning in debug mode. LockMutex (GraphicsLock); #endif GLOBAL (CurrentActivity) &= ~CHECK_ABORT; } #ifdef NETPLAY uninitBattleInputBuffers(); #ifdef NETPLAY_CHECKSUM uninitChecksumBuffers (); #endif /* NETPLAY_CHECKSUM */ setBattleStateConnections (NULL); #endif /* NETPLAY */ StopMusic (); StopSound (); } UninitShips (); FreeBattleSong (); UnlockMutex (GraphicsLock); return (BOOLEAN) (num_ships < 0); } uqm-0.6.2/sc2/src/sc2code/cnctdlg.h0000600000175000017500000000165110543202101015365 0ustar joeyjoey//Copyright Michael Martin, 2006 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef NETPLAY #ifndef _CNCTDLG_H #define _CNCTDLG_H #include "libs/compiler.h" BOOLEAN MeleeConnectDialog (int side); #endif /* _CNCTDLG_H */ #endif /* NETPLAY */ uqm-0.6.2/sc2/src/sc2code/confirm.c0000644000175000017500000001621210552135701015421 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "controls.h" #include "commglue.h" #include "comm.h" #include "colors.h" #include "settings.h" #include "setup.h" #include "sounds.h" #include "gamestr.h" #include "libs/graphics/widgets.h" #include "libs/inplib.h" #include "libs/sound/trackplayer.h" #include "libs/log.h" #include "libs/resource/stringbank.h" #include #include #define CONFIRM_WIN_WIDTH 80 #define CONFIRM_WIN_HEIGHT 22 static void DrawConfirmationWindow (BOOLEAN answer) { COLOR oldfg = SetContextForeGroundColor (MENU_TEXT_COLOR); FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); RECT r; TEXT t; BatchGraphics (); r.corner.x = (SCREEN_WIDTH - CONFIRM_WIN_WIDTH) >> 1; r.corner.y = (SCREEN_HEIGHT - CONFIRM_WIN_HEIGHT) >> 1; r.extent.width = CONFIRM_WIN_WIDTH; r.extent.height = CONFIRM_WIN_HEIGHT; DrawShadowedBox (&r, SHADOWBOX_BACKGROUND_COLOR, SHADOWBOX_DARK_COLOR, SHADOWBOX_MEDIUM_COLOR); t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.y = r.corner.y + 8; t.pStr = GAME_STRING (QUITMENU_STRING_BASE); // "Really Quit?" t.align = ALIGN_CENTER; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += 10; t.baseline.x = r.corner.x + (r.extent.width >> 2); t.pStr = GAME_STRING (QUITMENU_STRING_BASE + 1); // "Yes" SetContextForeGroundColor (answer ? MENU_HIGHLIGHT_COLOR : MENU_TEXT_COLOR); font_DrawText (&t); t.baseline.x += (r.extent.width >> 1); t.pStr = GAME_STRING (QUITMENU_STRING_BASE + 2); // "No" SetContextForeGroundColor (answer ? MENU_TEXT_COLOR : MENU_HIGHLIGHT_COLOR); font_DrawText (&t); UnbatchGraphics (); SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldfg); } /* This code assumes that you aren't in Character Mode. This is * currently safe because VControl doesn't see keystrokes when you * are, and thus cannot conclude that an exit is necessary. */ BOOLEAN DoConfirmExit (void) { BOOLEAN result; static BOOLEAN in_confirm = FALSE; if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE && !(LastActivity & CHECK_RESTART)) SuspendGameClock (); if (CommData.ConversationPhrases && PlayingTrack ()) PauseTrack (); LockMutex (GraphicsLock); if (in_confirm) { result = FALSE; ExitRequested = FALSE; } else { RECT r; STAMP s; FRAME F; CONTEXT oldContext; RECT oldRect; BOOLEAN response = FALSE, done; in_confirm = TRUE; oldContext = SetContext (ScreenContext); GetContextClipRect (&oldRect); SetContextClipRect (NULL_PTR); r.extent.width = CONFIRM_WIN_WIDTH + 4; r.extent.height = CONFIRM_WIN_HEIGHT + 4; r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; s.origin = r.corner; F = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); SetSystemRect (&r); DrawConfirmationWindow (response); // Releasing the lock lets the rotate_planet_task // draw a frame. PauseRotate can still allow one more frame // to be drawn, so it is safer to just not release the lock //UnlockMutex (GraphicsLock); FlushGraphics (); //LockMutex (GraphicsLock); GLOBAL (CurrentActivity) |= CHECK_ABORT; FlushInput (); done = FALSE; do { // Forbid recursive calls or pausing here! ExitRequested = FALSE; GamePaused = FALSE; UpdateInputState (); if (PulsedInputState.menu[KEY_MENU_SELECT]) { done = TRUE; PlayMenuSound (MENU_SOUND_SUCCESS); } else if (PulsedInputState.menu[KEY_MENU_CANCEL]) { done = TRUE; response = FALSE; } else if (PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_RIGHT]) { response = !response; DrawConfirmationWindow (response); PlayMenuSound (MENU_SOUND_MOVE); } TaskSwitch (); } while (!done); s.frame = F; DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); ClearSystemRect (); if (response) { result = TRUE; } else { result = FALSE; GLOBAL (CurrentActivity) &= ~CHECK_ABORT; } ExitRequested = FALSE; GamePaused = FALSE; FlushInput (); SetContextClipRect (&oldRect); SetContext (oldContext); } UnlockMutex (GraphicsLock); if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE && !(LastActivity & CHECK_RESTART)) ResumeGameClock (); if (CommData.ConversationPhrases && PlayingTrack ()) { ResumeTrack (); if (CommData.AlienTransitionDesc.AnimFlags & TALK_DONE) do_subtitles ((void *)~0); } in_confirm = FALSE; return (result); } typedef struct popup_state { // standard state required by DoInput BOOLEAN (*InputFunc) (struct popup_state *self); COUNT MenuRepeatDelay; } POPUP_STATE; static BOOLEAN DoPopup (struct popup_state *self) { (void)self; SleepThread (ONE_SECOND / 20); return !(PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_CANCEL]); } void DoPopupWindow(const char *msg) { stringbank *bank = StringBank_Create (); const char *lines[30]; WIDGET_LABEL label; RECT r; STAMP s; FRAME F; CONTEXT oldContext; RECT oldRect; POPUP_STATE state; MENU_SOUND_FLAGS s0, s1; if (!bank) { log_add (log_Fatal, "FATAL: Memory exhaustion when preparing popup window"); exit (EXIT_FAILURE); } label.tag = WIDGET_TYPE_LABEL; label.parent = NULL; label.handleEvent = Widget_HandleEventIgnoreAll; label.receiveFocus = Widget_ReceiveFocusRefuseFocus; label.draw = Widget_DrawLabel; label.height = Widget_HeightLabel; label.width = Widget_WidthFullScreen; label.line_count = SplitString (msg, '\n', 30, lines, bank); label.lines = lines; LockMutex (GraphicsLock); oldContext = SetContext (ScreenContext); GetContextClipRect (&oldRect); SetContextClipRect (NULL_PTR); /* TODO: Better measure of dimensions than this */ r.extent.width = SCREEN_WIDTH; r.extent.height = SCREEN_HEIGHT; r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; F = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); s.origin = r.corner; s.frame = F; DrawLabelAsWindow (&label); GetMenuSounds (&s0, &s1); SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); state.InputFunc = DoPopup; DoInput (&state, TRUE); DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); FlushInput (); SetContextClipRect (&oldRect); SetContext (oldContext); UnlockMutex (GraphicsLock); SetMenuSounds (s0, s1); StringBank_Free (bank); } uqm-0.6.2/sc2/src/sc2code/shipyard.c0000600000175000017500000010223110543202103015563 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "colors.h" #include "controls.h" #include "fmv.h" #include "gameopt.h" #include "gamestr.h" #include "melee.h" #include "options.h" #include "races.h" #include "nameref.h" #include "resinst.h" #include "settings.h" #include "starbase.h" #include "setup.h" #include "sis.h" #include "sounds.h" #include "state.h" #include "libs/graphics/gfx_common.h" #include "libs/inplib.h" #ifdef USE_3DO_HANGAR // 3DO 4x3 hangar layout # define HANGAR_SHIPS_ROW 4 # define HANGAR_Y 64 # define HANGAR_DY 44 static const COORD hangar_x_coords[HANGAR_SHIPS_ROW] = { 19, 60, 116, 157 }; #else // use PC hangar // modified PC 6x2 hangar layout # define HANGAR_SHIPS_ROW 6 # define HANGAR_Y 88 # define HANGAR_DY 84 static const COORD hangar_x_coords[HANGAR_SHIPS_ROW] = { 0, 38, 76, 131, 169, 207 }; # define WANT_HANGAR_ANIMATION #endif // USE_3DO_HANGAR #define HANGAR_SHIPS 12 #define HANGAR_ROWS (HANGAR_SHIPS / HANGAR_SHIPS_ROW) #define HANGAR_ANIM_RATE 15 // fps enum { SHIPYARD_CREW, SHIPYARD_SAVELOAD, SHIPYARD_EXIT }; static int hangar_anim_func (void *data) { DWORD TimeIn; STAMP s; Task task = (Task) data; COLORMAP ColorMap; RECT ClipRect; if (!pMenuState->CurString) { FinishTask (task); return -1; } s.origin.x = s.origin.y = 0; s.frame = SetAbsFrameIndex (pMenuState->CurFrame, 24); ClipRect = pMenuState->flash_rect1; ColorMap = SetAbsColorMapIndex (pMenuState->CurString, 0); TimeIn = GetTimeCounter (); while (!Task_ReadState (task, TASK_EXIT)) { CONTEXT OldContext; RECT OldClipRect; LockMutex (GraphicsLock); OldContext = SetContext (ScreenContext); GetContextClipRect (&OldClipRect); SetContextClipRect (&ClipRect); ColorMap = SetRelColorMapIndex (ColorMap, 1); SetColorMap (GetColorMapAddress (ColorMap)); DrawStamp (&s); SetContextClipRect (&OldClipRect); SetContext (OldContext); UnlockMutex (GraphicsLock); SleepThreadUntil (TimeIn + ONE_SECOND / HANGAR_ANIM_RATE); TimeIn = GetTimeCounter (); } FinishTask (task); return 0; } #ifdef WANT_SHIP_SPINS static void SpinStarShip (HSTARSHIP hStarShip) { COUNT Index; HSTARSHIP hNextShip, hShip; STARSHIPPTR StarShipPtr; extern QUEUE master_q; StarShipPtr = LockStarShip (&GLOBAL (built_ship_q), hStarShip); for (Index = 0, hShip = GetHeadLink (&master_q); hShip; hShip = hNextShip, ++Index) { STARSHIPPTR SSPtr; SSPtr = LockStarShip (&master_q, hShip); if (StarShipPtr->RaceResIndex == SSPtr->RaceResIndex) break; hNextShip = _GetSuccLink (SSPtr); UnlockStarShip (&master_q, hShip); } UnlockStarShip (&master_q, hStarShip); if (Index < NUM_MELEE_SHIPS) DoShipSpin (Index, pMenuState->hMusic); } #endif // Count the ships which can be built by the player. static COUNT GetAvailableRaceCount (void) { COUNT Index; HSTARSHIP hStarShip, hNextShip; Index = 0; for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); hStarShip; hStarShip = hNextShip) { SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip); if (StarShipPtr->ShipInfo.ship_flags & GOOD_GUY) ++Index; hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } return Index; } static HSTARSHIP GetAvailableRaceFromIndex (BYTE Index) { HSTARSHIP hStarShip, hNextShip; for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); hStarShip; hStarShip = hNextShip) { SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip (&GLOBAL (avail_race_q), hStarShip); if ((StarShipPtr->ShipInfo.ship_flags & GOOD_GUY) && Index-- == 0) { UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); return hStarShip; } hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } return 0; } static void DrawRaceStrings (BYTE NewRaceItem) { RECT r; STAMP s; CONTEXT OldContext; LockMutex (GraphicsLock); OldContext = SetContext (StatusContext); GetContextClipRect (&r); s.origin.x = RADAR_X - r.corner.x; s.origin.y = RADAR_Y - r.corner.y; r.corner.x = s.origin.x - 1; r.corner.y = s.origin.y - 11; r.extent.width = RADAR_WIDTH + 2; r.extent.height = 11; BatchGraphics (); ClearSISRect (CLEAR_SIS_RADAR); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); DrawFilledRectangle (&r); r.corner = s.origin; r.extent.width = RADAR_WIDTH; r.extent.height = RADAR_HEIGHT; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); DrawFilledRectangle (&r); if (NewRaceItem != (BYTE)~0) { TEXT t; HSTARSHIP hStarShip; STARSHIPPTR StarShipPtr; UNICODE buf[30]; COUNT ShipCost[] = { RACE_SHIP_COST }; hStarShip = GetAvailableRaceFromIndex (NewRaceItem); NewRaceItem = GetIndexFromStarShip (&GLOBAL (avail_race_q), hStarShip); s.frame = SetAbsFrameIndex (pMenuState->ModuleFrame, 3 + NewRaceItem); DrawStamp (&s); StarShipPtr = LockStarShip (&GLOBAL (avail_race_q), hStarShip); s.frame = StarShipPtr->RaceDescPtr->ship_info.melee_icon; UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); t.baseline.x = s.origin.x + RADAR_WIDTH - 2; t.baseline.y = s.origin.y + RADAR_HEIGHT - 2; s.origin.x += (RADAR_WIDTH >> 1); s.origin.y += (RADAR_HEIGHT >> 1); DrawStamp (&s); t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; t.pStr = buf; sprintf (buf, "%u", ShipCost[NewRaceItem]); SetContextFont (TinyFont); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x1F, 0x00), 0x02)); font_DrawText (&t); } UnbatchGraphics (); SetContext (OldContext); // Flash the ship purchase menu even when optMenu == OPT_PC SetFlashRect (SFR_MENU_ANY, (FRAME)0); UnlockMutex (GraphicsLock); } #define SHIP_WIN_WIDTH 34 #define SHIP_WIN_HEIGHT (SHIP_WIN_WIDTH + 6) #define SHIP_WIN_FRAMES ((SHIP_WIN_WIDTH >> 1) + 1) static void ShowShipCrew (SHIP_FRAGMENTPTR StarShipPtr, PRECT pRect) { RECT r; TEXT t; UNICODE buf[80]; HSTARSHIP hTemplate; SHIP_FRAGMENTPTR TemplatePtr; hTemplate = GetStarShipFromIndex (&GLOBAL (avail_race_q), GET_RACE_ID (StarShipPtr)); TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hTemplate); if (StarShipPtr->ShipInfo.crew_level >= TemplatePtr->RaceDescPtr->ship_info.crew_level) sprintf (buf, "%u", StarShipPtr->ShipInfo.crew_level); else if (StarShipPtr->ShipInfo.crew_level == 0) utf8StringCopy (buf, sizeof (buf), "SCRAP"); else sprintf (buf, "%u/%u", StarShipPtr->ShipInfo.crew_level, TemplatePtr->RaceDescPtr->ship_info.crew_level); UnlockStarShip (&GLOBAL (avail_race_q), hTemplate); r = *pRect; t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.y = r.corner.y + r.extent.height - 1; t.align = ALIGN_CENTER; t.pStr = buf; t.CharCount = (COUNT)~0; if (r.corner.y) { r.corner.y = t.baseline.y - 6; r.extent.width = SHIP_WIN_WIDTH; r.extent.height = 6; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); } SetContextForeGroundColor ((StarShipPtr->ShipInfo.crew_level != 0) ? (BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02)): (BUILD_COLOR (MAKE_RGB15 (0x12, 0x00, 0x00), 0x2B))); font_DrawText (&t); } static void ShowCombatShip (COUNT which_window, SHIP_FRAGMENTPTR YankedStarShipPtr) { COUNT i, num_ships; HSTARSHIP hStarShip, hNextShip; SHIP_FRAGMENTPTR StarShipPtr; struct { SHIP_FRAGMENTPTR StarShipPtr; POINT finished_s; STAMP ship_s, lfdoor_s, rtdoor_s; } ship_win_info[MAX_COMBAT_SHIPS], *pship_win_info; num_ships = 1; pship_win_info = &ship_win_info[0]; if (YankedStarShipPtr) { pship_win_info->StarShipPtr = YankedStarShipPtr; pship_win_info->lfdoor_s.origin.x = -(SHIP_WIN_WIDTH >> 1); pship_win_info->rtdoor_s.origin.x = (SHIP_WIN_WIDTH >> 1); pship_win_info->lfdoor_s.origin.y = pship_win_info->rtdoor_s.origin.y = 0; pship_win_info->lfdoor_s.frame = IncFrameIndex (pMenuState->ModuleFrame); pship_win_info->rtdoor_s.frame = IncFrameIndex (pship_win_info->lfdoor_s.frame); pship_win_info->ship_s.origin.x = (SHIP_WIN_WIDTH >> 1) + 1; pship_win_info->ship_s.origin.y = (SHIP_WIN_WIDTH >> 1); pship_win_info->ship_s.frame = YankedStarShipPtr->ShipInfo.melee_icon; pship_win_info->finished_s.x = hangar_x_coords[ which_window % HANGAR_SHIPS_ROW]; pship_win_info->finished_s.y = HANGAR_Y + (HANGAR_DY * (which_window / HANGAR_SHIPS_ROW)); } else { if (which_window == (COUNT)~0) { hStarShip = GetHeadLink (&GLOBAL (built_ship_q)); num_ships = CountLinks (&GLOBAL (built_ship_q)); } else { HSTARSHIP hTailShip; hTailShip = GetTailLink (&GLOBAL (built_ship_q)); RemoveQueue (&GLOBAL (built_ship_q), hTailShip); hStarShip = GetHeadLink (&GLOBAL (built_ship_q)); while (hStarShip) { StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip); if (GET_GROUP_LOC (StarShipPtr) > which_window) { UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); break; } hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); hStarShip = hNextShip; } InsertQueue (&GLOBAL (built_ship_q), hTailShip, hStarShip); hStarShip = hTailShip; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip); SET_GROUP_LOC (StarShipPtr, which_window); UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); } for (i = 0; i < num_ships; ++i) { StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip); hNextShip = _GetSuccLink (StarShipPtr); pship_win_info->StarShipPtr = StarShipPtr; pship_win_info->lfdoor_s.origin.x = -1; pship_win_info->rtdoor_s.origin.x = 1; pship_win_info->lfdoor_s.origin.y = pship_win_info->rtdoor_s.origin.y = 0; pship_win_info->lfdoor_s.frame = IncFrameIndex (pMenuState->ModuleFrame); pship_win_info->rtdoor_s.frame = IncFrameIndex (pship_win_info->lfdoor_s.frame); pship_win_info->ship_s.origin.x = (SHIP_WIN_WIDTH >> 1) + 1; pship_win_info->ship_s.origin.y = (SHIP_WIN_WIDTH >> 1); pship_win_info->ship_s.frame = StarShipPtr->ShipInfo.melee_icon; which_window = GET_GROUP_LOC (StarShipPtr); pship_win_info->finished_s.x = hangar_x_coords[ which_window % HANGAR_SHIPS_ROW]; pship_win_info->finished_s.y = HANGAR_Y + (HANGAR_DY * (which_window / HANGAR_SHIPS_ROW)); ++pship_win_info; UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); hStarShip = hNextShip; } } if (num_ships) { BOOLEAN AllDoorsFinished; DWORD TimeIn; RECT r; CONTEXT OldContext; int j; AllDoorsFinished = FALSE; r.corner.x = r.corner.y = 0; r.extent.width = SHIP_WIN_WIDTH; r.extent.height = SHIP_WIN_HEIGHT; FlushInput (); TimeIn = GetTimeCounter (); for (j = 0; (j < SHIP_WIN_FRAMES) && !AllDoorsFinished; j++) { SleepThreadUntil (TimeIn + ONE_SECOND / 24); TimeIn = GetTimeCounter (); if (AnyButtonPress (FALSE)) { if (YankedStarShipPtr != 0) { ship_win_info[0].lfdoor_s.origin.x = 0; ship_win_info[0].rtdoor_s.origin.x = 0; } AllDoorsFinished = TRUE; } LockMutex (GraphicsLock); OldContext = SetContext (OffScreenContext); SetContextFGFrame (Screen); SetContextBackGroundColor (BLACK_COLOR); BatchGraphics (); pship_win_info = &ship_win_info[0]; for (i = 0; i < num_ships; ++i) { { RECT ClipRect; ClipRect.corner.x = SIS_ORG_X + pship_win_info->finished_s.x; ClipRect.corner.y = SIS_ORG_Y + pship_win_info->finished_s.y; ClipRect.extent.width = SHIP_WIN_WIDTH; ClipRect.extent.height = SHIP_WIN_HEIGHT; SetContextClipRect (&ClipRect); ClearDrawable (); DrawStamp (&pship_win_info->ship_s); ShowShipCrew (pship_win_info->StarShipPtr, &r); if (!AllDoorsFinished || YankedStarShipPtr) { DrawStamp (&pship_win_info->lfdoor_s); DrawStamp (&pship_win_info->rtdoor_s); if (YankedStarShipPtr) { ++pship_win_info->lfdoor_s.origin.x; --pship_win_info->rtdoor_s.origin.x; } else { --pship_win_info->lfdoor_s.origin.x; ++pship_win_info->rtdoor_s.origin.x; } } } ++pship_win_info; } UnbatchGraphics (); SetContextClipRect (NULL_PTR); SetContext (OldContext); UnlockMutex (GraphicsLock); } } } static void CrewTransaction (SIZE crew_delta) { if (crew_delta) { SIZE crew_bought; crew_bought = (SIZE)MAKE_WORD ( GET_GAME_STATE (CREW_PURCHASED0), GET_GAME_STATE (CREW_PURCHASED1)) + crew_delta; if (crew_bought < 0) { if (crew_delta < 0) crew_bought = 0; else crew_bought = 0x7FFF; } else if (crew_delta > 0) { if (crew_bought >= CREW_EXPENSE_THRESHOLD && crew_bought - crew_delta < CREW_EXPENSE_THRESHOLD) { GLOBAL (CrewCost) += 2; UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); LockMutex (GraphicsLock); } } else { if (crew_bought < CREW_EXPENSE_THRESHOLD && crew_bought - crew_delta >= CREW_EXPENSE_THRESHOLD) { GLOBAL (CrewCost) -= 2; UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); LockMutex (GraphicsLock); } } if (!(ActivateStarShip (SHOFIXTI_SHIP, CHECK_ALLIANCE) & GOOD_GUY)) { SET_GAME_STATE (CREW_PURCHASED0, LOBYTE (crew_bought)); SET_GAME_STATE (CREW_PURCHASED1, HIBYTE (crew_bought)); } } } /* in this routine, the least significant byte of pMS->CurState is used * to store the current selected ship index * a special case for the row is hi-nibble == -1 (0xf), which specifies * SIS as the selected ship * some bitwise math is still done to scroll through ships, for it to work * ships per row number must divide 0xf0 without remainder */ static BOOLEAN DoModifyShips (PMENU_STATE pMS) { #define MODIFY_CREW_FLAG (1 << 8) RECT r; HSTARSHIP hStarShip, hNextShip; SHIP_FRAGMENTPTR StarShipPtr; BOOLEAN select, cancel; #ifdef WANT_SHIP_SPINS BOOLEAN special; special = PulsedInputState.menu[KEY_MENU_SPECIAL]; #endif /* WANT_SHIP_SPINS */ select = PulsedInputState.menu[KEY_MENU_SELECT]; cancel = PulsedInputState.menu[KEY_MENU_CANCEL]; if (GLOBAL (CurrentActivity) & CHECK_ABORT) { pMS->InputFunc = DoShipyard; return TRUE; } if (!pMS->Initialized) { pMS->InputFunc = DoModifyShips; pMS->Initialized = TRUE; pMS->CurState = MAKE_BYTE (0, 0xF); pMS->delta_item = 0; LockMutex (GraphicsLock); SetContext (SpaceContext); goto ChangeFlashRect; } else { SBYTE dx = 0; SBYTE dy = 0; BYTE NewState; if (!(pMS->delta_item & MODIFY_CREW_FLAG)) { SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); } if (PulsedInputState.menu[KEY_MENU_RIGHT]) dx = 1; if (PulsedInputState.menu[KEY_MENU_LEFT]) dx = -1; if (PulsedInputState.menu[KEY_MENU_UP]) dy = -1; if (PulsedInputState.menu[KEY_MENU_DOWN]) dy = 1; NewState = pMS->CurState; if (pMS->delta_item & MODIFY_CREW_FLAG) { } else if (dy) { if (HINIBBLE (NewState)) NewState = pMS->CurState % HANGAR_SHIPS_ROW; else NewState = (unsigned char)(pMS->CurState + HANGAR_SHIPS_ROW); NewState += dy * HANGAR_SHIPS_ROW; if (NewState / HANGAR_SHIPS_ROW > 0 && NewState / HANGAR_SHIPS_ROW <= HANGAR_ROWS) NewState -= HANGAR_SHIPS_ROW; else if (NewState / HANGAR_SHIPS_ROW > HANGAR_ROWS + 1) /* negative number - select last row */ NewState = pMS->CurState % HANGAR_SHIPS_ROW + HANGAR_SHIPS_ROW * (HANGAR_ROWS - 1); else // select SIS NewState = MAKE_BYTE (pMS->CurState, 0xF); } else if (dx && !HINIBBLE (NewState)) { NewState = NewState % HANGAR_SHIPS_ROW; if ((dx += NewState) < 0) NewState = (BYTE)(pMS->CurState + (HANGAR_SHIPS_ROW - 1)); else if (dx > HANGAR_SHIPS_ROW - 1) NewState = (BYTE)(pMS->CurState - (HANGAR_SHIPS_ROW - 1)); else NewState = (BYTE)(pMS->CurState - NewState + dx); } if (select || cancel #ifdef WANT_SHIP_SPINS || special #endif || NewState != pMS->CurState || ((pMS->delta_item & MODIFY_CREW_FLAG) && (dx || dy))) { for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)); hStarShip; hStarShip = hNextShip) { StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip); if (GET_GROUP_LOC (StarShipPtr) == pMS->CurState) { UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); break; } hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); } if ((pMS->delta_item & MODIFY_CREW_FLAG) && (hStarShip)) { SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT | MENU_SOUND_CANCEL); } else { SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); } LockMutex (GraphicsLock); #ifdef WANT_SHIP_SPINS if (special) { HSTARSHIP hSpinShip; if ((hSpinShip = hStarShip) || (HINIBBLE (pMS->CurState) == 0 && (hSpinShip = GetAvailableRaceFromIndex ( LOBYTE (pMS->delta_item))))) { SetFlashRect (NULL_PTR, (FRAME)0); SpinStarShip (hSpinShip); if (hStarShip) goto ChangeFlashRect; SetFlashRect (SFR_MENU_3DO, (FRAME)0); } } else #endif if (select || ((pMS->delta_item & MODIFY_CREW_FLAG) && (dx || dy || cancel))) { COUNT ShipCost[] = { RACE_SHIP_COST }; if (hStarShip == 0 && HINIBBLE (pMS->CurState) == 0) { COUNT Index; // SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); if (!(pMS->delta_item & MODIFY_CREW_FLAG)) { pMS->delta_item = MODIFY_CREW_FLAG; DrawRaceStrings (0); return TRUE; } else if (cancel) { pMS->delta_item ^= MODIFY_CREW_FLAG; LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); } else if (select) { Index = GetIndexFromStarShip (&GLOBAL (avail_race_q), GetAvailableRaceFromIndex ( LOBYTE (pMS->delta_item))); if (GLOBAL_SIS (ResUnits) >= (DWORD)ShipCost[Index] && CloneShipFragment (Index, &GLOBAL (built_ship_q), 1)) { ShowCombatShip ((COUNT)pMS->CurState, (SHIP_FRAGMENTPTR) 0); //Reset flash rectangle LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_CREW, SHIPYARD_CREW); LockMutex (GraphicsLock); DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, -((int)ShipCost[Index])); r.corner.x = pMS->flash_rect0.corner.x; r.corner.y = pMS->flash_rect0.corner.y + pMS->flash_rect0.extent.height - 6; r.extent.width = SHIP_WIN_WIDTH; r.extent.height = 5; SetContext (SpaceContext); SetFlashRect (&r, (FRAME)0); UnlockMutex (GraphicsLock); } else { // not enough RUs to build PlayMenuSound (MENU_SOUND_FAILURE); } SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT | MENU_SOUND_CANCEL); return TRUE; } else { Index = GetAvailableRaceCount (); NewState = LOBYTE (pMS->delta_item); if (dx < 0 || dy < 0) { if (NewState-- == 0) NewState = Index - 1; } else if (dx > 0 || dy > 0) { if (++NewState == Index) NewState = 0; } if (NewState != LOBYTE (pMS->delta_item)) { DrawRaceStrings (NewState); pMS->delta_item = NewState | MODIFY_CREW_FLAG; } return TRUE; } LockMutex (GraphicsLock); goto ChangeFlashRect; } else if (select || cancel) { if ((pMS->delta_item & MODIFY_CREW_FLAG) && hStarShip != 0) { StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip); if (StarShipPtr->ShipInfo.crew_level == 0) { SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); ShowCombatShip ((COUNT)pMS->CurState, StarShipPtr); LockMutex (GraphicsLock); UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); RemoveQueue (&GLOBAL (built_ship_q), hStarShip); FreeStarShip (&GLOBAL (built_ship_q), hStarShip); // refresh SIS display DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, UNDEFINED_DELTA); DrawStatusMessage ((UNICODE *)~0); r.corner.x = pMS->flash_rect0.corner.x; r.corner.y = pMS->flash_rect0.corner.y; r.extent.width = SHIP_WIN_WIDTH; r.extent.height = SHIP_WIN_HEIGHT; SetContext (SpaceContext); SetFlashRect (&r, (FRAME)0); } else { UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); } } if (!(pMS->delta_item ^= MODIFY_CREW_FLAG)) { goto ChangeFlashRect; } else if (hStarShip == 0) { SetContext (StatusContext); GetGaugeRect (&r, TRUE); SetFlashRect (&r, (FRAME)0); SetContext (SpaceContext); SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT | MENU_SOUND_CANCEL); } else { r.corner.x = pMS->flash_rect0.corner.x; r.corner.y = pMS->flash_rect0.corner.y + pMS->flash_rect0.extent.height - 6; r.extent.width = SHIP_WIN_WIDTH; r.extent.height = 5; SetContext (SpaceContext); SetFlashRect (&r, (FRAME)0); SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT | MENU_SOUND_CANCEL); } } else if (pMS->delta_item & MODIFY_CREW_FLAG) { SIZE crew_delta, crew_bought; if (hStarShip) StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip); else StarShipPtr = NULL; // Keeping compiler quiet. SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT | MENU_SOUND_CANCEL); crew_delta = 0; if (dy < 0) { if (hStarShip == 0) { if (GetCPodCapacity (&r.corner) > GetCrewCount () && GLOBAL_SIS (ResUnits) >= (DWORD)GLOBAL (CrewCost)) { DrawPoint (&r.corner); DeltaSISGauges (1, 0, -GLOBAL (CrewCost)); crew_delta = 1; SetContext (StatusContext); GetGaugeRect (&r, TRUE); SetFlashRect (&r, (FRAME)0); SetContext (SpaceContext); } else { // at capacity or not enough RUs PlayMenuSound (MENU_SOUND_FAILURE); } } else { HSTARSHIP hTemplate; SHIP_FRAGMENTPTR TemplatePtr; hTemplate = GetStarShipFromIndex ( &GLOBAL (avail_race_q), GET_RACE_ID (StarShipPtr)); TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hTemplate); if (GLOBAL_SIS (ResUnits) >= (DWORD)GLOBAL (CrewCost) && StarShipPtr->ShipInfo.crew_level < StarShipPtr->ShipInfo.max_crew && StarShipPtr->ShipInfo.crew_level < TemplatePtr->RaceDescPtr->ship_info. crew_level) { if (StarShipPtr->ShipInfo.crew_level > 0) DeltaSISGauges (0, 0, -GLOBAL (CrewCost)); else DeltaSISGauges (0, 0, -(COUNT)ShipCost[ GET_RACE_ID (StarShipPtr) ]); ++StarShipPtr->ShipInfo.crew_level; crew_delta = 1; ShowShipCrew (StarShipPtr, &pMS->flash_rect0); r.corner.x = pMS->flash_rect0.corner.x; r.corner.y = pMS->flash_rect0.corner.y + pMS->flash_rect0.extent.height - 6; r.extent.width = SHIP_WIN_WIDTH; r.extent.height = 5; SetContext (SpaceContext); SetFlashRect (&r, (FRAME)0); } else { // at capacity or not enough RUs PlayMenuSound (MENU_SOUND_FAILURE); } UnlockStarShip (&GLOBAL (avail_race_q), hTemplate); } } else if (dy > 0) { crew_bought = (SIZE)MAKE_WORD ( GET_GAME_STATE (CREW_PURCHASED0), GET_GAME_STATE (CREW_PURCHASED1)); if (hStarShip == 0) { if (GetCrewCount ()) { DeltaSISGauges (-1, 0, GLOBAL (CrewCost) - (crew_bought == CREW_EXPENSE_THRESHOLD ? 2 : 0)); crew_delta = -1; GetCPodCapacity (&r.corner); SetContextForeGroundColor (BLACK_COLOR); DrawPoint (&r.corner); SetContext (StatusContext); GetGaugeRect (&r, TRUE); SetFlashRect (&r, (FRAME)0); SetContext (SpaceContext); } else { // no crew to dismiss PlayMenuSound (MENU_SOUND_FAILURE); } } else { if (StarShipPtr->ShipInfo.crew_level > 0) { if (StarShipPtr->ShipInfo.crew_level > 1) DeltaSISGauges (0, 0, GLOBAL (CrewCost) - (crew_bought == CREW_EXPENSE_THRESHOLD ? 2 : 0)); else DeltaSISGauges (0, 0, (COUNT)ShipCost[ GET_RACE_ID (StarShipPtr)]); crew_delta = -1; --StarShipPtr->ShipInfo.crew_level; } else { // no crew to dismiss PlayMenuSound (MENU_SOUND_FAILURE); } ShowShipCrew (StarShipPtr, &pMS->flash_rect0); r.corner.x = pMS->flash_rect0.corner.x; r.corner.y = pMS->flash_rect0.corner.y + pMS->flash_rect0.extent.height - 6; r.extent.width = SHIP_WIN_WIDTH; r.extent.height = 5; SetContext (SpaceContext); SetFlashRect (&r, (FRAME)0); } } if (hStarShip) { UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); // clear out the bought ship index // so that flash rects work correctly pMS->delta_item &= MODIFY_CREW_FLAG; } CrewTransaction (crew_delta); } } else if (cancel) { UnlockMutex (GraphicsLock); pMS->InputFunc = DoShipyard; pMS->CurState = SHIPYARD_CREW; DrawMenuStateStrings (PM_CREW, pMS->CurState); LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); return TRUE; } else { pMS->CurState = NewState; ChangeFlashRect: if (HINIBBLE (pMS->CurState)) { pMS->flash_rect0.corner.x = pMS->flash_rect0.corner.y = 0; pMS->flash_rect0.extent.width = SIS_SCREEN_WIDTH; pMS->flash_rect0.extent.height = 61; } else { pMS->flash_rect0.corner.x = hangar_x_coords[ pMS->CurState % HANGAR_SHIPS_ROW]; pMS->flash_rect0.corner.y = HANGAR_Y + (HANGAR_DY * (pMS->CurState / HANGAR_SHIPS_ROW)); pMS->flash_rect0.extent.width = SHIP_WIN_WIDTH; pMS->flash_rect0.extent.height = SHIP_WIN_HEIGHT; } SetFlashRect (&pMS->flash_rect0, (FRAME)0); } UnlockMutex (GraphicsLock); } } return TRUE; } static void DrawBluePrint (PMENU_STATE pMS) { COUNT num_frames; STAMP s; LockMutex (GraphicsLock); SetContext (SpaceContext); pMS->ModuleFrame = CaptureDrawable ( LoadGraphic (SISBLU_MASK_ANIM) ); BatchGraphics (); s.origin.x = s.origin.y = 0; s.frame = DecFrameIndex (pMS->ModuleFrame); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x16), 0x01)); DrawFilledStamp (&s); for (num_frames = 0; num_frames < NUM_DRIVE_SLOTS; ++num_frames) { DrawShipPiece (pMS, GLOBAL_SIS (DriveSlots[num_frames]), num_frames, TRUE); } for (num_frames = 0; num_frames < NUM_JET_SLOTS; ++num_frames) { DrawShipPiece (pMS, GLOBAL_SIS (JetSlots[num_frames]), num_frames, TRUE); } for (num_frames = 0; num_frames < NUM_MODULE_SLOTS; ++num_frames) { BYTE which_piece; which_piece = GLOBAL_SIS (ModuleSlots[num_frames]); if (!(pMS->CurState == SHIPYARD && which_piece == CREW_POD)) DrawShipPiece (pMS, which_piece, num_frames, TRUE); } SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); for (num_frames = 0; num_frames < NUM_MODULE_SLOTS; ++num_frames) { BYTE which_piece; which_piece = GLOBAL_SIS (ModuleSlots[num_frames]); if (pMS->CurState == SHIPYARD && which_piece == CREW_POD) DrawShipPiece (pMS, which_piece, num_frames, TRUE); } { num_frames = GLOBAL_SIS (CrewEnlisted); GLOBAL_SIS (CrewEnlisted) = 0; while (num_frames--) { POINT pt; GetCPodCapacity (&pt); DrawPoint (&pt); ++GLOBAL_SIS (CrewEnlisted); } } { RECT r; num_frames = GLOBAL_SIS (TotalElementMass); GLOBAL_SIS (TotalElementMass) = 0; r.extent.width = 9; r.extent.height = 1; while (num_frames) { COUNT m; m = num_frames < SBAY_MASS_PER_ROW ? num_frames : SBAY_MASS_PER_ROW; GLOBAL_SIS (TotalElementMass) += m; GetSBayCapacity (&r.corner); DrawFilledRectangle (&r); num_frames -= m; } } if (GLOBAL_SIS (FuelOnBoard) > FUEL_RESERVE) { DWORD FuelVolume; RECT r; FuelVolume = GLOBAL_SIS (FuelOnBoard) - FUEL_RESERVE; GLOBAL_SIS (FuelOnBoard) = FUEL_RESERVE; r.extent.width = 3; r.extent.height = 1; while (FuelVolume) { COUNT m; GetFTankCapacity (&r.corner); DrawPoint (&r.corner); r.corner.x += r.extent.width + 1; DrawPoint (&r.corner); r.corner.x -= r.extent.width; SetContextForeGroundColor ( SetContextBackGroundColor (BLACK_COLOR)); DrawFilledRectangle (&r); m = FuelVolume < FUEL_VOLUME_PER_ROW ? (COUNT)FuelVolume : FUEL_VOLUME_PER_ROW; GLOBAL_SIS (FuelOnBoard) += m; FuelVolume -= m; } } UnbatchGraphics (); DestroyDrawable (ReleaseDrawable (pMS->ModuleFrame)); pMS->ModuleFrame = 0; UnlockMutex (GraphicsLock); } static void BeginHangarAnim (PMENU_STATE pMS) { #ifdef WANT_HANGAR_ANIMATION CONTEXT OldContext; RECT ClipRect; OldContext = SetContext (SpaceContext); GetContextClipRect (&ClipRect); // start hangar power-lines animation GetContextClipRect (&ClipRect); pMS->flash_rect1 = ClipRect; pMS->CurFrame = pMS->ModuleFrame; pMS->flash_task = AssignTask (hangar_anim_func, 4096, "hangar pal-rot animation"); SetContext (OldContext); #endif } static void EndHangarAnim (PMENU_STATE pMS) { if (pMS->flash_task) { ConcludeTask (pMS->flash_task); pMS->flash_task = 0; } } BOOLEAN DoShipyard (PMENU_STATE pMS) { BOOLEAN select, cancel; if (GLOBAL (CurrentActivity) & CHECK_ABORT) goto ExitShipyard; select = PulsedInputState.menu[KEY_MENU_SELECT]; cancel = PulsedInputState.menu[KEY_MENU_CANCEL]; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); if (!pMS->Initialized) { pMS->InputFunc = DoShipyard; { STAMP s; RECT r, old_r; s.frame = CaptureDrawable (LoadGraphic (SHIPYARD_PMAP_ANIM)); pMS->CurString = CaptureColorMap ( LoadColorMap (HANGAR_COLOR_TAB)); pMS->hMusic = LoadMusic (SHIPYARD_MUSIC); LockMutex (GraphicsLock); SetTransitionSource (NULL); BatchGraphics (); DrawSISFrame (); DrawSISMessage (GAME_STRING (STARBASE_STRING_BASE + 3)); DrawSISTitle (GAME_STRING (STARBASE_STRING_BASE)); UnlockMutex (GraphicsLock); DrawBluePrint (pMS); pMS->ModuleFrame = s.frame; DrawMenuStateStrings (PM_CREW, pMS->CurState = SHIPYARD_CREW); LockMutex (GraphicsLock); SetContext (SpaceContext); s.origin.x = s.origin.y = 0; #ifdef USE_3DO_HANGAR DrawStamp (&s); #else // PC hangar // the PC ship dock needs to overwrite the border // expand the clipping rect by 1 pixel GetContextClipRect (&old_r); r = old_r; r.corner.x--; r.extent.width += 2; r.extent.height += 1; SetContextClipRect (&r); DrawStamp (&s); SetContextClipRect (&old_r); #endif // USE_3DO_HANGAR SetContextFont (TinyFont); { RECT r; r.corner.x = 0; r.corner.y = 0; r.extent.width = SCREEN_WIDTH; r.extent.height = SCREEN_HEIGHT; ScreenTransition (3, &r); } PlayMusic (pMS->hMusic, TRUE, 1); UnbatchGraphics (); BeginHangarAnim (pMS); UnlockMutex (GraphicsLock); ShowCombatShip ((COUNT)~0, (SHIP_FRAGMENTPTR)0); LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); } pMS->Initialized = TRUE; } else if (cancel || (select && pMS->CurState == SHIPYARD_EXIT)) { ExitShipyard: EndHangarAnim (pMS); LockMutex (GraphicsLock); DestroyDrawable (ReleaseDrawable (pMS->ModuleFrame)); pMS->ModuleFrame = 0; pMS->CurFrame = 0; DestroyColorMap (ReleaseColorMap (pMS->CurString)); pMS->CurString = 0; UnlockMutex (GraphicsLock); return FALSE; } else if (select) { if (pMS->CurState != SHIPYARD_SAVELOAD) { pMS->Initialized = FALSE; DoModifyShips (pMS); } else { EndHangarAnim (pMS); if (GameOptions () == 0) goto ExitShipyard; DrawMenuStateStrings (PM_CREW, pMS->CurState); LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); BeginHangarAnim (pMS); UnlockMutex (GraphicsLock); } } else DoMenuChooser (pMS, PM_CREW); return TRUE; } uqm-0.6.2/sc2/src/sc2code/starbase.h0000600000175000017500000000267710543202102015565 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STARBASE_H #define _STARBASE_H #include "menustat.h" enum { TALK_COMMANDER = 0, OUTFIT_STARSHIP, SHIPYARD, DEPART_BASE }; typedef BYTE STARBASE_STATE; extern void InstallBombAtEarth (void); extern void VisitStarBase (void); extern BOOLEAN DoStarBase (PMENU_STATE pMS); extern BOOLEAN DoOutfit (PMENU_STATE pMS); extern BOOLEAN DoShipyard (PMENU_STATE pMS); extern void DrawShipPiece (PMENU_STATE pMS, COUNT which_piece, COUNT which_slot, BOOLEAN DrawBluePrint); extern COUNT WrapText (const UNICODE *pStr, COUNT len, TEXT *tarray, SIZE field_width); // XXX: Doesn't really belong in this file. extern const char starbase_str_array[][20]; #endif /* _STARBASE_H */ uqm-0.6.2/sc2/src/sc2code/master.c0000600000175000017500000000764210543202101015243 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "master.h" #include "build.h" #include "resinst.h" #include "displist.h" #include "melee.h" QUEUE master_q; void LoadMasterShipList (void) { COUNT num_entries; RES_TYPE rt; RES_INSTANCE ri; RES_PACKAGE rp; rt = GET_TYPE (ARILOU_SHIP_INDEX); ri = GET_INSTANCE (ARILOU_SHIP_INDEX); rp = GET_PACKAGE (ARILOU_SHIP_INDEX); InitQueue (&master_q, num_entries = NUM_MELEE_SHIPS, sizeof (SHIP_FRAGMENT)); while (num_entries--) { HSTARSHIP hBuiltShip; hBuiltShip = Build (&master_q, MAKE_RESOURCE (rp++, rt, ri++), 0, 0); if (hBuiltShip) { char built_buf[30]; HSTARSHIP hStarShip, hNextShip; STARSHIPPTR BuiltShipPtr; SHIP_INFOPTR ShipInfoPtr; TaskSwitch (); // XXX: what is this doing here? BuiltShipPtr = LockStarShip (&master_q, hBuiltShip); load_ship (BuiltShipPtr, FALSE); ShipInfoPtr = &((SHIP_FRAGMENTPTR)BuiltShipPtr)->ShipInfo; *ShipInfoPtr = BuiltShipPtr->RaceDescPtr->ship_info; BuiltShipPtr->RaceDescPtr->ship_info.melee_icon = 0; BuiltShipPtr->RaceDescPtr->ship_info.icons = 0; BuiltShipPtr->RaceDescPtr->ship_info.race_strings = 0; free_ship (BuiltShipPtr, FALSE); BuiltShipPtr->RaceDescPtr = (RACE_DESCPTR)ShipInfoPtr; GetStringContents (SetAbsStringTableIndex ( BuiltShipPtr->RaceDescPtr->ship_info.race_strings, 2 ), (STRINGPTR)built_buf, FALSE); UnlockStarShip (&master_q, hBuiltShip); RemoveQueue (&master_q, hBuiltShip); // Insert the ship in the master queue in the right location // to keep the list sorted on the name of the race. for (hStarShip = GetHeadLink (&master_q); hStarShip; hStarShip = hNextShip) { char ship_buf[30]; STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip (&master_q, hStarShip); hNextShip = _GetSuccLink (StarShipPtr); GetStringContents (SetAbsStringTableIndex ( StarShipPtr->RaceDescPtr->ship_info.race_strings, 2 ), (STRINGPTR)ship_buf, FALSE); UnlockStarShip (&master_q, hStarShip); if (strcmp (built_buf, ship_buf) < 0) break; } InsertQueue (&master_q, hBuiltShip, hStarShip); } } } void FreeMasterShipList (void) { HSTARSHIP hStarShip, hNextShip; for (hStarShip = GetHeadLink (&master_q); hStarShip != 0; hStarShip = hNextShip) { STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip (&master_q, hStarShip); hNextShip = _GetSuccLink (StarShipPtr); DestroyDrawable (ReleaseDrawable ( StarShipPtr->RaceDescPtr->ship_info.melee_icon)); DestroyDrawable (ReleaseDrawable ( StarShipPtr->RaceDescPtr->ship_info.icons)); DestroyStringTable (ReleaseStringTable ( StarShipPtr->RaceDescPtr->ship_info.race_strings)); UnlockStarShip (&master_q, hStarShip); } UninitQueue (&master_q); } HSTARSHIP FindMasterShip (DWORD ship_ref) { HSTARSHIP hStarShip; hStarShip = GetHeadLink (&master_q); if (hStarShip) { do { DWORD ref; HSTARSHIP hNextShip; STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip (&master_q, hStarShip); hNextShip = _GetSuccLink (StarShipPtr); ref = StarShipPtr->RaceResIndex; UnlockStarShip (&master_q, hStarShip); if (ref == ship_ref) break; hStarShip = hNextShip; } while (hStarShip); } return (hStarShip); } uqm-0.6.2/sc2/src/sc2code/globdata.h0000600000175000017500000007617310543202103015541 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GLOBDATA_H #define _GLOBDATA_H #include "clock.h" #include "libs/gfxlib.h" #include "sis.h" #include "velocity.h" // Animation types: #define RANDOM_ANIM (1 << 0) // Next index is randomly chose #define CIRCULAR_ANIM (1 << 1) // #define YOYO_ANIM (1 << 2) #define ANIM_MASK (RANDOM_ANIM | CIRCULAR_ANIM | YOYO_ANIM) #define WAIT_TALKING (1 << 3) #define PAUSE_TALKING (1 << 4) #define TALK_INTRO (1 << 5) #define TALK_DONE (1 << 6) #define ANIM_DISABLED (1 << 7) #define COLORXFORM_ANIM PAUSE_TALKING typedef struct { COUNT StartIndex; // Index of the first image (for image animation) or // index of the first color map (for palette animation) BYTE NumFrames; // number of frames BYTE AnimFlags; // One of RANDOM_ANIM, CIRCULAR_ANIM, or YOYO_ANIM COUNT BaseFrameRate; COUNT RandomFrameRate; COUNT BaseRestartRate; COUNT RandomRestartRate; DWORD BlockMask; } ANIMATION_DESC; typedef ANIMATION_DESC *PANIMATION_DESC; #define ANIMATION_DESCPTR PANIMATION_DESC #define MAX_ANIMATIONS 20 // general numbers-speech generator info // should accomodate most common base-10 languages // many languages require various plural forms // for digit names like "hundred" // possibly needs reworking for others typedef struct { // an array of these structs must be in ascending remainder order // terminate the array with Divider == 0 // digit divider, i.e. 1, 10, 100, etc. int Divider; // maximum remainder for this name // name will be used if Number % Divider <= MaxRemainder int MaxRemainder; // string table index for this name // i.e. "hundred" in English COUNT StrIndex; } SPEECH_DIGITNAME; typedef struct { // digit divider, i.e. 1, 10, 100, etc. int Divider; // digit sub, i.e. 10 for teens // subtracted from the value to get an index into StrDigits int Subtrahend; // ptr to 10 indices for this digit // index is string table ptr when > 0 // is invalid (should not happen) or // is a a 'skip digit' indicator when == 0 // StrDigits can be NULL, in which case // the value is interpreted recursively COUNT *StrDigits; // digit Names, can be NULL, in which case // CommonNameIndex is used SPEECH_DIGITNAME *Names; // common digit name string table index // i.e. "hundred" in English COUNT CommonNameIndex; } SPEECH_DIGIT; // this accomodates up to "billions" in english #define MAX_SPEECH_DIGITS 7 typedef struct { // slots used in Digits array COUNT NumDigits; // slots for each digit in numbers // teens is exception // 0-9, 10-19, ..20-90, ..100-900, etc. SPEECH_DIGIT Digits[MAX_SPEECH_DIGITS]; } NUMBER_SPEECH_DESC; typedef NUMBER_SPEECH_DESC *PNUMBER_SPEECH_DESC; #define NUMBER_SPEECH_DESCPTR PNUMBER_SPEECH_DESC typedef NUMBER_SPEECH_DESC *NUMBER_SPEECH; typedef DWORD LDAS_FLAGS; #define LDASF_NONE ((LDAS_FLAGS) 0 ) #define LDASF_USE_ALTERNATE ((LDAS_FLAGS)(1 << 0)) typedef struct { void (*init_encounter_func) (void); /* Called when entering communications */ void (*post_encounter_func) (void); /* Called when leaving communications or combat normally */ COUNT (*uninit_encounter_func) (void); /* Called when encounter is done for cleanup */ FRAME AlienFrame; FONT AlienFont; COLOR AlienTextFColor, AlienTextBColor; POINT AlienTextBaseline; COUNT AlienTextWidth; TEXT_ALIGN AlienTextAlign; TEXT_VALIGN AlienTextValign; COLORMAP AlienColorMap; DWORD AlienSong; DWORD AlienAltSong; LDAS_FLAGS AlienSongFlags; STRING ConversationPhrases; COUNT NumAnimations; ANIMATION_DESC AlienAmbientArray[MAX_ANIMATIONS]; ANIMATION_DESC AlienTransitionDesc; ANIMATION_DESC AlienTalkDesc; NUMBER_SPEECH AlienNumberSpeech; } LOCDATA; typedef LOCDATA *PLOCDATA; #define LOCDATAPTR PLOCDATA enum { PORTAL_SPAWNER_DEVICE = 0, TALKING_PET_DEVICE, UTWIG_BOMB_DEVICE, SUN_EFFICIENCY_DEVICE, ROSY_SPHERE_DEVICE, AQUA_HELIX_DEVICE, CLEAR_SPINDLE_DEVICE, ULTRON_0_DEVICE, ULTRON_1_DEVICE, ULTRON_2_DEVICE, ULTRON_3_DEVICE, MAIDENS_DEVICE, UMGAH_HYPERWAVE_DEVICE, BURVIX_HYPERWAVE_DEVICE, DATA_PLATE_1_DEVICE, DATA_PLATE_2_DEVICE, DATA_PLATE_3_DEVICE, TAALO_PROTECTOR_DEVICE, EGG_CASING0_DEVICE, EGG_CASING1_DEVICE, EGG_CASING2_DEVICE, SYREEN_SHUTTLE_DEVICE, VUX_BEAST_DEVICE, DESTRUCT_CODE_DEVICE, URQUAN_WARP_DEVICE, ARTIFACT_2_DEVICE, ARTIFACT_3_DEVICE, LUNAR_BASE_DEVICE, NUM_DEVICES }; #define YEARS_TO_KOHRAH_VICTORY 4 #define START_GAME_STATE enum { #define ADD_GAME_STATE(SName,NumBits) SName, END_##SName = SName + NumBits - 1, #define END_GAME_STATE NUM_GAME_STATE_BITS }; START_GAME_STATE /* Shofixti states */ ADD_GAME_STATE (SHOFIXTI_VISITS, 3) ADD_GAME_STATE (SHOFIXTI_STACK1, 2) ADD_GAME_STATE (SHOFIXTI_STACK2, 3) ADD_GAME_STATE (SHOFIXTI_STACK3, 2) ADD_GAME_STATE (SHOFIXTI_KIA, 1) ADD_GAME_STATE (SHOFIXTI_BRO_KIA, 1) ADD_GAME_STATE (SHOFIXTI_RECRUITED, 1) ADD_GAME_STATE (SHOFIXTI_MAIDENS, 1) /* Did you find the babes yet? */ ADD_GAME_STATE (MAIDENS_ON_SHIP, 1) ADD_GAME_STATE (BATTLE_SEGUE, 1) /* Set to 0 in init_xxx_comm() if communications directly * follows an encounter. * Set to 1 in init_xxx_comm() if the player gets to decide * whether to attack or talk. * Set to 1 in communication when battle follows the * communication. It is still valid when uninit_xxx_comm() gets * called after combat or communication. */ ADD_GAME_STATE (PLANETARY_LANDING, 1) ADD_GAME_STATE (PLANETARY_CHANGE, 1) /* Flag set to 1 when the planet information for the current * world is changed since it was last saved to the starinfo.dat * file. Set when picking up bio, mineral, or energy nodes. * When there's no current world, it should be 0. */ /* Spathi states */ ADD_GAME_STATE (SPATHI_VISITS, 3) ADD_GAME_STATE (SPATHI_HOME_VISITS, 3) ADD_GAME_STATE (FOUND_PLUTO_SPATHI, 2) /* 0 - Haven't met Fwiffo. * 1 - Met Fwiffo on Pluto, now talking to him. * 2 - Met Fwiffo on Pluto, after dialog. * 3 - Met Fwiffo, and have reported to the Safe Ones on * the Spathi moon that he was either killed, or that * you have him on board. */ ADD_GAME_STATE (SPATHI_SHIELDED_SELVES, 1) ADD_GAME_STATE (SPATHI_CREATURES_EXAMINED, 1) ADD_GAME_STATE (SPATHI_CREATURES_ELIMINATED, 1) ADD_GAME_STATE (UMGAH_BROADCASTERS, 1) ADD_GAME_STATE (SPATHI_MANNER, 2) ADD_GAME_STATE (SPATHI_QUEST, 1) ADD_GAME_STATE (LIED_ABOUT_CREATURES, 2) ADD_GAME_STATE (SPATHI_PARTY, 1) ADD_GAME_STATE (KNOW_SPATHI_PASSWORD, 1) ADD_GAME_STATE (ILWRATH_HOME_VISITS, 3) ADD_GAME_STATE (ILWRATH_CHMMR_VISITS, 1) ADD_GAME_STATE (ARILOU_SPACE, 1) /* 0 if the periodically opening QuasiSpace portal is * closed or closing. * 1 if the periodically opening QuasiSpace portal is * open or opening. */ ADD_GAME_STATE (ARILOU_SPACE_SIDE, 2) /* 0 if in HyperSpace and not just emerged from the periodically * opening QuasiSpace portal. * 1 if in HyperSpace and just emerged from the periodically * QuasiSpace portal (still on the portal). * 2 if in QuasiSpace and just emerged from the periodically * opening portal (still on the portal). * 3 if in QuasiSpace and not just emerged from the * periodically opening portal. */ ADD_GAME_STATE (ARILOU_SPACE_COUNTER, 4) /* Keeps track of how far the periodically opening QuasiSpace * portal is open. (This determines the image) * 0 <= ARILOU_SPACE_COUNTER <= 9 * 0 means totally closed. * 9 means completely open. */ ADD_GAME_STATE (LANDER_SHIELDS, 4) ADD_GAME_STATE (SHOFIXTI_GRPOFFS0, 8) ADD_GAME_STATE (SHOFIXTI_GRPOFFS1, 8) ADD_GAME_STATE (SHOFIXTI_GRPOFFS2, 8) ADD_GAME_STATE (SHOFIXTI_GRPOFFS3, 8) ADD_GAME_STATE (ZOQFOT_GRPOFFS0, 8) ADD_GAME_STATE (ZOQFOT_GRPOFFS1, 8) ADD_GAME_STATE (ZOQFOT_GRPOFFS2, 8) ADD_GAME_STATE (ZOQFOT_GRPOFFS3, 8) ADD_GAME_STATE (MELNORME0_GRPOFFS0, 8) ADD_GAME_STATE (MELNORME0_GRPOFFS1, 8) ADD_GAME_STATE (MELNORME0_GRPOFFS2, 8) ADD_GAME_STATE (MELNORME0_GRPOFFS3, 8) ADD_GAME_STATE (MELNORME1_GRPOFFS0, 8) ADD_GAME_STATE (MELNORME1_GRPOFFS1, 8) ADD_GAME_STATE (MELNORME1_GRPOFFS2, 8) ADD_GAME_STATE (MELNORME1_GRPOFFS3, 8) ADD_GAME_STATE (MELNORME2_GRPOFFS0, 8) ADD_GAME_STATE (MELNORME2_GRPOFFS1, 8) ADD_GAME_STATE (MELNORME2_GRPOFFS2, 8) ADD_GAME_STATE (MELNORME2_GRPOFFS3, 8) ADD_GAME_STATE (MELNORME3_GRPOFFS0, 8) ADD_GAME_STATE (MELNORME3_GRPOFFS1, 8) ADD_GAME_STATE (MELNORME3_GRPOFFS2, 8) ADD_GAME_STATE (MELNORME3_GRPOFFS3, 8) ADD_GAME_STATE (MELNORME4_GRPOFFS0, 8) ADD_GAME_STATE (MELNORME4_GRPOFFS1, 8) ADD_GAME_STATE (MELNORME4_GRPOFFS2, 8) ADD_GAME_STATE (MELNORME4_GRPOFFS3, 8) ADD_GAME_STATE (MELNORME5_GRPOFFS0, 8) ADD_GAME_STATE (MELNORME5_GRPOFFS1, 8) ADD_GAME_STATE (MELNORME5_GRPOFFS2, 8) ADD_GAME_STATE (MELNORME5_GRPOFFS3, 8) ADD_GAME_STATE (MELNORME6_GRPOFFS0, 8) ADD_GAME_STATE (MELNORME6_GRPOFFS1, 8) ADD_GAME_STATE (MELNORME6_GRPOFFS2, 8) ADD_GAME_STATE (MELNORME6_GRPOFFS3, 8) ADD_GAME_STATE (MELNORME7_GRPOFFS0, 8) ADD_GAME_STATE (MELNORME7_GRPOFFS1, 8) ADD_GAME_STATE (MELNORME7_GRPOFFS2, 8) ADD_GAME_STATE (MELNORME7_GRPOFFS3, 8) ADD_GAME_STATE (MELNORME8_GRPOFFS0, 8) ADD_GAME_STATE (MELNORME8_GRPOFFS1, 8) ADD_GAME_STATE (MELNORME8_GRPOFFS2, 8) ADD_GAME_STATE (MELNORME8_GRPOFFS3, 8) ADD_GAME_STATE (MET_MELNORME, 1) ADD_GAME_STATE (MELNORME_RESCUE_REFUSED, 1) ADD_GAME_STATE (MELNORME_RESCUE_COUNT, 3) ADD_GAME_STATE (TRADED_WITH_MELNORME, 1) ADD_GAME_STATE (WHY_MELNORME_PURPLE, 1) ADD_GAME_STATE (MELNORME_CREDIT0, 8) ADD_GAME_STATE (MELNORME_CREDIT1, 8) ADD_GAME_STATE (MELNORME_BUSINESS_COUNT, 2) ADD_GAME_STATE (MELNORME_YACK_STACK0, 2) ADD_GAME_STATE (MELNORME_YACK_STACK1, 2) ADD_GAME_STATE (MELNORME_YACK_STACK2, 4) ADD_GAME_STATE (MELNORME_YACK_STACK3, 3) ADD_GAME_STATE (MELNORME_YACK_STACK4, 2) ADD_GAME_STATE (WHY_MELNORME_BLUE, 1) ADD_GAME_STATE (MELNORME_ANGER, 2) ADD_GAME_STATE (MELNORME_MIFFED_COUNT, 2) ADD_GAME_STATE (MELNORME_PISSED_COUNT, 2) ADD_GAME_STATE (MELNORME_HATE_COUNT, 2) ADD_GAME_STATE (URQUAN_PROBE_GRPOFFS0, 8) ADD_GAME_STATE (URQUAN_PROBE_GRPOFFS1, 8) ADD_GAME_STATE (URQUAN_PROBE_GRPOFFS2, 8) ADD_GAME_STATE (URQUAN_PROBE_GRPOFFS3, 8) ADD_GAME_STATE (PROBE_MESSAGE_DELIVERED, 1) ADD_GAME_STATE (PROBE_ILWRATH_ENCOUNTER, 1) ADD_GAME_STATE (STARBASE_AVAILABLE, 1) ADD_GAME_STATE (STARBASE_VISITED, 1) ADD_GAME_STATE (RADIOACTIVES_PROVIDED, 1) ADD_GAME_STATE (LANDERS_LOST, 1) ADD_GAME_STATE (GIVEN_FUEL_BEFORE, 1) ADD_GAME_STATE (AWARE_OF_SAMATRA, 1) ADD_GAME_STATE (YEHAT_CAVALRY_ARRIVED, 1) ADD_GAME_STATE (URQUAN_MESSED_UP, 1) ADD_GAME_STATE (MOONBASE_DESTROYED, 1) ADD_GAME_STATE (WILL_DESTROY_BASE, 1) ADD_GAME_STATE (ARTIFACT_2_ON_SHIP, 1) ADD_GAME_STATE (ARTIFACT_3_ON_SHIP, 1) ADD_GAME_STATE (KOHR_AH_KILLED_ALL, 1) ADD_GAME_STATE (STARBASE_YACK_STACK1, 1) ADD_GAME_STATE (DISCUSSED_PORTAL_SPAWNER, 1) ADD_GAME_STATE (DISCUSSED_TALKING_PET, 1) ADD_GAME_STATE (DISCUSSED_UTWIG_BOMB, 1) ADD_GAME_STATE (DISCUSSED_SUN_EFFICIENCY, 1) ADD_GAME_STATE (DISCUSSED_ROSY_SPHERE, 1) ADD_GAME_STATE (DISCUSSED_AQUA_HELIX, 1) ADD_GAME_STATE (DISCUSSED_CLEAR_SPINDLE, 1) ADD_GAME_STATE (DISCUSSED_ULTRON, 1) ADD_GAME_STATE (DISCUSSED_MAIDENS, 1) ADD_GAME_STATE (DISCUSSED_UMGAH_HYPERWAVE, 1) ADD_GAME_STATE (DISCUSSED_BURVIX_HYPERWAVE, 1) ADD_GAME_STATE (SYREEN_WANT_PROOF, 1) ADD_GAME_STATE (PLAYER_HAVING_SEX, 1) ADD_GAME_STATE (MET_ARILOU, 1) ADD_GAME_STATE (DISCUSSED_TAALO_PROTECTOR, 1) ADD_GAME_STATE (DISCUSSED_EGG_CASING0, 1) ADD_GAME_STATE (DISCUSSED_EGG_CASING1, 1) ADD_GAME_STATE (DISCUSSED_EGG_CASING2, 1) ADD_GAME_STATE (DISCUSSED_SYREEN_SHUTTLE, 1) ADD_GAME_STATE (DISCUSSED_VUX_BEAST, 1) ADD_GAME_STATE (DISCUSSED_DESTRUCT_CODE, 1) ADD_GAME_STATE (DISCUSSED_URQUAN_WARP, 1) ADD_GAME_STATE (DISCUSSED_ARTIFACT_2, 1) ADD_GAME_STATE (DISCUSSED_ARTIFACT_3, 1) ADD_GAME_STATE (ATTACKED_DRUUGE, 1) ADD_GAME_STATE (NEW_ALLIANCE_NAME, 2) ADD_GAME_STATE (PORTAL_COUNTER, 4) /* Set to 1 when the player opens a QuasiSpace portal. * It will then be increased to 10, at which time * the portal is completely open. (This determines the image). */ ADD_GAME_STATE (BURVIXESE_BROADCASTERS, 1) ADD_GAME_STATE (BURV_BROADCASTERS_ON_SHIP, 1) ADD_GAME_STATE (UTWIG_BOMB, 1) ADD_GAME_STATE (UTWIG_BOMB_ON_SHIP, 1) ADD_GAME_STATE (AQUA_HELIX, 1) ADD_GAME_STATE (AQUA_HELIX_ON_SHIP, 1) ADD_GAME_STATE (SUN_DEVICE, 1) ADD_GAME_STATE (SUN_DEVICE_ON_SHIP, 1) ADD_GAME_STATE (TAALO_PROTECTOR, 1) ADD_GAME_STATE (TAALO_PROTECTOR_ON_SHIP, 1) ADD_GAME_STATE (SHIP_VAULT_UNLOCKED, 1) ADD_GAME_STATE (SYREEN_SHUTTLE, 1) ADD_GAME_STATE (PORTAL_KEY, 1) ADD_GAME_STATE (PORTAL_KEY_ON_SHIP, 1) ADD_GAME_STATE (VUX_BEAST, 1) ADD_GAME_STATE (VUX_BEAST_ON_SHIP, 1) ADD_GAME_STATE (TALKING_PET, 1) ADD_GAME_STATE (TALKING_PET_ON_SHIP, 1) ADD_GAME_STATE (MOONBASE_ON_SHIP, 1) ADD_GAME_STATE (KOHR_AH_FRENZY, 1) ADD_GAME_STATE (KOHR_AH_VISITS, 2) ADD_GAME_STATE (KOHR_AH_BYES, 1) ADD_GAME_STATE (SLYLANDRO_HOME_VISITS, 3) ADD_GAME_STATE (DESTRUCT_CODE_ON_SHIP, 1) ADD_GAME_STATE (ILWRATH_VISITS, 3) ADD_GAME_STATE (ILWRATH_DECEIVED, 1) ADD_GAME_STATE (FLAGSHIP_CLOAKED, 1) ADD_GAME_STATE (MYCON_VISITS, 3) ADD_GAME_STATE (MYCON_HOME_VISITS, 3) ADD_GAME_STATE (MYCON_AMBUSH, 1) ADD_GAME_STATE (MYCON_FELL_FOR_AMBUSH, 1) /* Set to 1 when the Mycon have been told about Organon * and are moving towards it. */ ADD_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 8) /* This state seems to be used to distinguish between different * places where one may have an conversation with an alien. * Like home world, other world, space. * Why this needs 8 bits I don't know. Only specific * combinations of bits seem to be used (0, 1, or all bits). * A closer investigation is desirable. - SvdB * Bit 4 is set when initiating communication with the Ilwrath * homeworld by means of a HyperWave Broadcaster. * Bit 5 is set when initiating communication with an Ilwrath * ship by means of a HyperWave Broadcaster. * All bits are cleared when communication is over. */ ADD_GAME_STATE (ORZ_VISITS, 3) ADD_GAME_STATE (TAALO_VISITS, 3) ADD_GAME_STATE (ORZ_MANNER, 2) ADD_GAME_STATE (PROBE_EXHIBITED_BUG, 1) ADD_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 1) ADD_GAME_STATE (URQUAN_VISITS, 3) ADD_GAME_STATE (PLAYER_HYPNOTIZED, 1) ADD_GAME_STATE (VUX_VISITS, 3) ADD_GAME_STATE (VUX_HOME_VISITS, 3) ADD_GAME_STATE (ZEX_VISITS, 3) ADD_GAME_STATE (ZEX_IS_DEAD, 1) ADD_GAME_STATE (KNOW_ZEX_WANTS_MONSTER, 1) ADD_GAME_STATE (UTWIG_VISITS, 3) ADD_GAME_STATE (UTWIG_HOME_VISITS, 3) ADD_GAME_STATE (BOMB_VISITS, 3) ADD_GAME_STATE (ULTRON_CONDITION, 3) /* 0 if the Supox still have the Ultron * 1 if the Captain has the Ultron, completely broken * 2 if the Captain has the Ultron, with 1 fix * 3 if the Captain has the Ultron, with 2 fixes * 4 if the Captain has the Ultron, completely restored * 5 if the Ultron has been returned to the Utwig */ ADD_GAME_STATE (UTWIG_HAVE_ULTRON, 1) ADD_GAME_STATE (BOMB_UNPROTECTED, 1) ADD_GAME_STATE (TAALO_UNPROTECTED, 1) ADD_GAME_STATE (TALKING_PET_VISITS, 3) ADD_GAME_STATE (TALKING_PET_HOME_VISITS, 3) ADD_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES, 1) /* The Umgah have come under the influence of the Talking Pet */ ADD_GAME_STATE (KNOW_UMGAH_ZOMBIES, 1) /* The Captain is aware that something is up with the Umgah */ ADD_GAME_STATE (ARILOU_VISITS, 3) ADD_GAME_STATE (ARILOU_HOME_VISITS, 3) ADD_GAME_STATE (KNOW_ARILOU_WANT_WRECK, 1) ADD_GAME_STATE (ARILOU_CHECKED_UMGAH, 2) ADD_GAME_STATE (PORTAL_SPAWNER, 1) ADD_GAME_STATE (PORTAL_SPAWNER_ON_SHIP, 1) ADD_GAME_STATE (UMGAH_VISITS, 3) ADD_GAME_STATE (UMGAH_HOME_VISITS, 3) ADD_GAME_STATE (MET_NORMAL_UMGAH, 1) ADD_GAME_STATE (SYREEN_HOME_VISITS, 3) ADD_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP, 1) ADD_GAME_STATE (KNOW_SYREEN_VAULT, 1) ADD_GAME_STATE (EGG_CASE0_ON_SHIP, 1) ADD_GAME_STATE (SUN_DEVICE_UNGUARDED, 1) ADD_GAME_STATE (ROSY_SPHERE_ON_SHIP, 1) ADD_GAME_STATE (CHMMR_HOME_VISITS, 3) ADD_GAME_STATE (CHMMR_EMERGING, 1) ADD_GAME_STATE (CHMMR_UNLEASHED, 1) ADD_GAME_STATE (CHMMR_BOMB_STATE, 2) ADD_GAME_STATE (DRUUGE_DISCLAIMER, 1) ADD_GAME_STATE (YEHAT_VISITS, 3) ADD_GAME_STATE (YEHAT_REBEL_VISITS, 3) ADD_GAME_STATE (YEHAT_HOME_VISITS, 3) ADD_GAME_STATE (YEHAT_CIVIL_WAR, 1) ADD_GAME_STATE (YEHAT_ABSORBED_PKUNK, 1) ADD_GAME_STATE (YEHAT_SHIP_MONTH, 4) ADD_GAME_STATE (YEHAT_SHIP_DAY, 5) ADD_GAME_STATE (YEHAT_SHIP_YEAR, 5) ADD_GAME_STATE (CLEAR_SPINDLE, 1) ADD_GAME_STATE (PKUNK_VISITS, 3) ADD_GAME_STATE (PKUNK_HOME_VISITS, 3) ADD_GAME_STATE (PKUNK_SHIP_MONTH, 4) /* The month in PKUNK_SHIP_YEAR that new ships are available * from the Pkunk. */ ADD_GAME_STATE (PKUNK_SHIP_DAY, 5) /* The day of the month in PKUNK_SHIP_MONTH in PKUNK_SHIP_YEAR * that new ships are available. */ ADD_GAME_STATE (PKUNK_SHIP_YEAR, 5) /* The year that new ships are available from the Pkunk * (stored as an offset from the year the game starts). */ ADD_GAME_STATE (PKUNK_MISSION, 3) ADD_GAME_STATE (SUPOX_VISITS, 3) ADD_GAME_STATE (SUPOX_HOME_VISITS, 3) ADD_GAME_STATE (THRADD_VISITS, 3) ADD_GAME_STATE (THRADD_HOME_VISITS, 3) ADD_GAME_STATE (HELIX_VISITS, 3) ADD_GAME_STATE (HELIX_UNPROTECTED, 1) ADD_GAME_STATE (THRADD_CULTURE, 2) ADD_GAME_STATE (THRADD_MISSION, 3) /* 0 if the Thraddash fleet hasn't left the Thraddash home world. * 1 if the Thraddash are heading towards Kohr-Ah territory. * 2 if the Thraddash are fighting the Kohr-Ah. * 3 if the Thraddash are returning from Kohr-Ah territory. * 4 if the Thraddash fleet is back at the Thraddash home world. */ ADD_GAME_STATE (DRUUGE_VISITS, 3) ADD_GAME_STATE (DRUUGE_HOME_VISITS, 3) ADD_GAME_STATE (ROSY_SPHERE, 1) ADD_GAME_STATE (SCANNED_MAIDENS, 1) ADD_GAME_STATE (SCANNED_FRAGMENTS, 1) ADD_GAME_STATE (SCANNED_CASTER, 1) ADD_GAME_STATE (SCANNED_SPAWNER, 1) ADD_GAME_STATE (SCANNED_ULTRON, 1) ADD_GAME_STATE (ZOQFOT_INFO, 2) ADD_GAME_STATE (ZOQFOT_HOSTILE, 1) ADD_GAME_STATE (ZOQFOT_HOME_VISITS, 3) ADD_GAME_STATE (MET_ZOQFOT, 1) ADD_GAME_STATE (ZOQFOT_DISTRESS, 2) /* 0 if the Zoq-Fot-Pik aren't in distress * 1 if the Zoq-Fot-Pik are under attack by the Kohr-Ah * 2 if the Zoq-Fot-Pik have been destroyed because of this * attack (not by the Kohr-Ah final victory cleansing) */ ADD_GAME_STATE (EGG_CASE1_ON_SHIP, 1) ADD_GAME_STATE (EGG_CASE2_ON_SHIP, 1) ADD_GAME_STATE (MYCON_SUN_VISITS, 3) ADD_GAME_STATE (ORZ_HOME_VISITS, 3) ADD_GAME_STATE (MELNORME_FUEL_PROCEDURE, 1) ADD_GAME_STATE (MELNORME_TECH_PROCEDURE, 1) ADD_GAME_STATE (MELNORME_INFO_PROCEDURE, 1) ADD_GAME_STATE (MELNORME_TECH_STACK, 4) ADD_GAME_STATE (MELNORME_EVENTS_INFO_STACK, 5) ADD_GAME_STATE (MELNORME_ALIEN_INFO_STACK, 5) ADD_GAME_STATE (MELNORME_HISTORY_INFO_STACK, 5) ADD_GAME_STATE (RAINBOW_WORLD0, 8) /* Low byte of a bit array, one bit per rainbow world. * Each bit is set if the rainbow world has been visited. * The lowest bit is for the first star in the star_array * with RAINBOW_DEFINED, and so on. */ ADD_GAME_STATE (RAINBOW_WORLD1, 2) /* High 2 bits of the bit array of which RAINBOW_WORLD0 * is the low byte. */ ADD_GAME_STATE (MELNORME_RAINBOW_COUNT, 4) /* The number of rainbow world locations sold to the Melnorme. */ ADD_GAME_STATE (USED_BROADCASTER, 1) ADD_GAME_STATE (BROADCASTER_RESPONSE, 1) ADD_GAME_STATE (IMPROVED_LANDER_SPEED, 1) ADD_GAME_STATE (IMPROVED_LANDER_CARGO, 1) ADD_GAME_STATE (IMPROVED_LANDER_SHOT, 1) ADD_GAME_STATE (MET_ORZ_BEFORE, 1) ADD_GAME_STATE (YEHAT_REBEL_TOLD_PKUNK, 1) ADD_GAME_STATE (PLAYER_HAD_SEX, 1) ADD_GAME_STATE (UMGAH_BROADCASTERS_ON_SHIP, 1) ADD_GAME_STATE (LIGHT_MINERAL_LOAD, 3) ADD_GAME_STATE (MEDIUM_MINERAL_LOAD, 3) ADD_GAME_STATE (HEAVY_MINERAL_LOAD, 3) ADD_GAME_STATE (STARBASE_BULLETS0, 8) ADD_GAME_STATE (STARBASE_BULLETS1, 8) ADD_GAME_STATE (STARBASE_BULLETS2, 8) ADD_GAME_STATE (STARBASE_BULLETS3, 8) ADD_GAME_STATE (STARBASE_MONTH, 4) ADD_GAME_STATE (STARBASE_DAY, 5) ADD_GAME_STATE (CREW_SOLD_TO_DRUUGE0, 8) ADD_GAME_STATE (CREW_PURCHASED0, 8) ADD_GAME_STATE (CREW_PURCHASED1, 8) ADD_GAME_STATE (URQUAN_PROTECTING_SAMATRA, 1) ADD_GAME_STATE (COLONY_GRPOFFS0, 8) ADD_GAME_STATE (COLONY_GRPOFFS1, 8) ADD_GAME_STATE (COLONY_GRPOFFS2, 8) ADD_GAME_STATE (COLONY_GRPOFFS3, 8) #define THRADDASH_BODY_THRESHOLD 25 ADD_GAME_STATE (THRADDASH_BODY_COUNT, 5) ADD_GAME_STATE (UTWIG_SUPOX_MISSION, 3) /* 0 if the Utwig and Supox fleet haven't left their home world. * 1 if the U&S are on their way towards the Kohr-Ah * 2 if the U&S are fighting the Kohr-Ah (first 80 days) * 3 does not occur * 4 if the U&S are fighting the Kohr-Ah (second 80 days) * 5 if the U&S are returning home. * 6 if the U&S are back at their home world. */ ADD_GAME_STATE (SPATHI_INFO, 3) ADD_GAME_STATE (ILWRATH_INFO, 2) ADD_GAME_STATE (ILWRATH_GODS_SPOKEN, 4) ADD_GAME_STATE (ILWRATH_WORSHIP, 2) ADD_GAME_STATE (ILWRATH_FIGHT_THRADDASH, 1) ADD_GAME_STATE (SAMATRA_GRPOFFS0, 8) ADD_GAME_STATE (SAMATRA_GRPOFFS1, 8) ADD_GAME_STATE (SAMATRA_GRPOFFS2, 8) ADD_GAME_STATE (SAMATRA_GRPOFFS3, 8) ADD_GAME_STATE (READY_TO_CONFUSE_URQUAN, 1) ADD_GAME_STATE (URQUAN_HYPNO_VISITS, 1) ADD_GAME_STATE (MENTIONED_PET_COMPULSION, 1) ADD_GAME_STATE (URQUAN_INFO, 2) ADD_GAME_STATE (KNOW_URQUAN_STORY, 2) ADD_GAME_STATE (MYCON_INFO, 4) ADD_GAME_STATE (MYCON_RAMBLE, 5) ADD_GAME_STATE (KNOW_ABOUT_SHATTERED, 2) /* 0 if the player doesn't known about shattered worlds * 1 if the player has encountered a shattered world * 2 if the player knows that shatterred worlds are caused * by Mycon deep children. * 3 if the player has told the Syreen that Mycon Deep Children * cause shattered worlds. Proof doesn't have to be presented * yet at this time. */ ADD_GAME_STATE (MYCON_INSULTS, 3) ADD_GAME_STATE (MYCON_KNOW_AMBUSH, 1) /* Set to 1 when the Mycon have been butchered at Organon, * just before the remaining Mycon head back home. */ ADD_GAME_STATE (SYREEN_INFO, 2) ADD_GAME_STATE (KNOW_SYREEN_WORLD_SHATTERED, 1) ADD_GAME_STATE (SYREEN_KNOW_ABOUT_MYCON, 1) ADD_GAME_STATE (TALKING_PET_INFO, 3) ADD_GAME_STATE (TALKING_PET_SUGGESTIONS, 3) ADD_GAME_STATE (LEARNED_TALKING_PET, 1) ADD_GAME_STATE (DNYARRI_LIED, 1) /* Set when the Talking Pet tells you his version of their * race's history with the Ur-Quan. * Cleared once you confront him about this lie. */ ADD_GAME_STATE (SHIP_TO_COMPEL, 1) ADD_GAME_STATE (ORZ_GENERAL_INFO, 2) ADD_GAME_STATE (ORZ_PERSONAL_INFO, 3) ADD_GAME_STATE (ORZ_ANDRO_STATE, 2) ADD_GAME_STATE (REFUSED_ORZ_ALLIANCE, 1) ADD_GAME_STATE (PKUNK_MANNER, 2) /* 0 not met the Pkunk * 1 fought the Pkunk, but relations are still salvagable. * 2 hostile relations with the Pkunk, no way back. * 3 friendly relations with the Pkunk */ ADD_GAME_STATE (PKUNK_ON_THE_MOVE, 1) ADD_GAME_STATE (PKUNK_FLEET, 2) ADD_GAME_STATE (PKUNK_MIGRATE, 2) ADD_GAME_STATE (PKUNK_RETURN, 1) ADD_GAME_STATE (PKUNK_WORRY, 2) ADD_GAME_STATE (PKUNK_INFO, 3) ADD_GAME_STATE (PKUNK_WAR, 2) ADD_GAME_STATE (PKUNK_FORTUNE, 3) ADD_GAME_STATE (PKUNK_MIGRATE_VISITS, 3) ADD_GAME_STATE (PKUNK_REASONS, 4) ADD_GAME_STATE (PKUNK_SWITCH, 1) ADD_GAME_STATE (PKUNK_SENSE_VICTOR, 1) ADD_GAME_STATE (KOHR_AH_REASONS, 2) ADD_GAME_STATE (KOHR_AH_PLEAD, 2) ADD_GAME_STATE (KOHR_AH_INFO, 2) ADD_GAME_STATE (KNOW_KOHR_AH_STORY, 2) ADD_GAME_STATE (KOHR_AH_SENSES_EVIL, 1) ADD_GAME_STATE (URQUAN_SENSES_EVIL, 1) ADD_GAME_STATE (SLYLANDRO_PROBE_VISITS, 3) ADD_GAME_STATE (SLYLANDRO_PROBE_THREAT, 2) ADD_GAME_STATE (SLYLANDRO_PROBE_WRONG, 2) ADD_GAME_STATE (SLYLANDRO_PROBE_ID, 2) ADD_GAME_STATE (SLYLANDRO_PROBE_INFO, 2) ADD_GAME_STATE (SLYLANDRO_PROBE_EXIT, 2) ADD_GAME_STATE (UMGAH_HOSTILE, 1) ADD_GAME_STATE (UMGAH_EVIL_BLOBBIES, 1) ADD_GAME_STATE (UMGAH_MENTIONED_TRICKS, 2) ADD_GAME_STATE (BOMB_CARRIER, 1) /* 0 when the flagship is not in battle, or it doesn't have the * enhanced precursor bomb installed. * 1 when the flagship is in battle and the bomb is installed. * This determines whether you can flee (if the warp escape unit * is installed at all), and whether taking the ship into the * Sa-Matra defense structure will trigger the end of the game. */ ADD_GAME_STATE (THRADD_MANNER, 1) ADD_GAME_STATE (THRADD_INTRO, 2) ADD_GAME_STATE (THRADD_DEMEANOR, 3) ADD_GAME_STATE (THRADD_INFO, 2) ADD_GAME_STATE (THRADD_BODY_LEVEL, 2) ADD_GAME_STATE (THRADD_MISSION_VISITS, 1) ADD_GAME_STATE (THRADD_STACK_1, 3) ADD_GAME_STATE (THRADD_HOSTILE_STACK_2, 1) ADD_GAME_STATE (THRADD_HOSTILE_STACK_3, 1) ADD_GAME_STATE (THRADD_HOSTILE_STACK_4, 1) ADD_GAME_STATE (THRADD_HOSTILE_STACK_5, 1) ADD_GAME_STATE (CHMMR_STACK, 2) ADD_GAME_STATE (ARILOU_MANNER, 2) ADD_GAME_STATE (NO_PORTAL_VISITS, 1) ADD_GAME_STATE (ARILOU_STACK_1, 2) ADD_GAME_STATE (ARILOU_STACK_2, 1) ADD_GAME_STATE (ARILOU_STACK_3, 2) ADD_GAME_STATE (ARILOU_STACK_4, 1) ADD_GAME_STATE (ARILOU_STACK_5, 2) ADD_GAME_STATE (ARILOU_INFO, 2) ADD_GAME_STATE (ARILOU_HINTS, 2) ADD_GAME_STATE (DRUUGE_MANNER, 1) ADD_GAME_STATE (DRUUGE_SPACE_INFO, 2) ADD_GAME_STATE (DRUUGE_HOME_INFO, 2) ADD_GAME_STATE (DRUUGE_SALVAGE, 1) ADD_GAME_STATE (KNOW_DRUUGE_SLAVERS, 2) ADD_GAME_STATE (FRAGMENTS_BOUGHT, 2) ADD_GAME_STATE (ZEX_STACK_1, 2) ADD_GAME_STATE (ZEX_STACK_2, 2) ADD_GAME_STATE (ZEX_STACK_3, 2) ADD_GAME_STATE (VUX_INFO, 2) ADD_GAME_STATE (VUX_STACK_1, 4) ADD_GAME_STATE (VUX_STACK_2, 2) ADD_GAME_STATE (VUX_STACK_3, 2) ADD_GAME_STATE (VUX_STACK_4, 2) ADD_GAME_STATE (SHOFIXTI_STACK4, 2) ADD_GAME_STATE (YEHAT_REBEL_INFO, 3) ADD_GAME_STATE (YEHAT_ROYALIST_INFO, 1) ADD_GAME_STATE (YEHAT_ROYALIST_TOLD_PKUNK, 1) ADD_GAME_STATE (NO_YEHAT_ALLY_HOME, 1) ADD_GAME_STATE (NO_YEHAT_HELP_HOME, 1) ADD_GAME_STATE (NO_YEHAT_INFO, 1) ADD_GAME_STATE (NO_YEHAT_ALLY_SPACE, 2) ADD_GAME_STATE (NO_YEHAT_HELP_SPACE, 2) ADD_GAME_STATE (ZOQFOT_KNOW_MASK, 4) ADD_GAME_STATE (SUPOX_HOSTILE, 1) ADD_GAME_STATE (SUPOX_INFO, 1) ADD_GAME_STATE (SUPOX_WAR_NEWS, 2) ADD_GAME_STATE (SUPOX_ULTRON_HELP, 1) ADD_GAME_STATE (SUPOX_STACK1, 3) ADD_GAME_STATE (SUPOX_STACK2, 2) ADD_GAME_STATE (UTWIG_HOSTILE, 1) ADD_GAME_STATE (UTWIG_INFO, 1) ADD_GAME_STATE (UTWIG_WAR_NEWS, 2) ADD_GAME_STATE (UTWIG_STACK1, 3) ADD_GAME_STATE (UTWIG_STACK2, 2) ADD_GAME_STATE (BOMB_INFO, 1) ADD_GAME_STATE (BOMB_STACK1, 2) ADD_GAME_STATE (BOMB_STACK2, 2) ADD_GAME_STATE (SLYLANDRO_KNOW_BROKEN, 1) ADD_GAME_STATE (PLAYER_KNOWS_PROBE, 1) ADD_GAME_STATE (PLAYER_KNOWS_PROGRAM, 1) ADD_GAME_STATE (PLAYER_KNOWS_EFFECTS, 1) ADD_GAME_STATE (PLAYER_KNOWS_PRIORITY, 1) ADD_GAME_STATE (SLYLANDRO_STACK1, 3) ADD_GAME_STATE (SLYLANDRO_STACK2, 1) ADD_GAME_STATE (SLYLANDRO_STACK3, 2) ADD_GAME_STATE (SLYLANDRO_STACK4, 2) ADD_GAME_STATE (SLYLANDRO_STACK5, 1) ADD_GAME_STATE (SLYLANDRO_STACK6, 1) ADD_GAME_STATE (SLYLANDRO_STACK7, 2) ADD_GAME_STATE (SLYLANDRO_STACK8, 2) ADD_GAME_STATE (SLYLANDRO_STACK9, 2) ADD_GAME_STATE (SLYLANDRO_KNOW_EARTH, 1) ADD_GAME_STATE (SLYLANDRO_KNOW_EXPLORE, 1) ADD_GAME_STATE (SLYLANDRO_KNOW_GATHER, 1) ADD_GAME_STATE (SLYLANDRO_KNOW_URQUAN, 2) ADD_GAME_STATE (RECALL_VISITS, 2) ADD_GAME_STATE (SLYLANDRO_MULTIPLIER, 3) ADD_GAME_STATE (KNOW_SPATHI_QUEST, 1) ADD_GAME_STATE (KNOW_SPATHI_EVIL, 1) ADD_GAME_STATE (BATTLE_PLANET, 8) ADD_GAME_STATE (ESCAPE_COUNTER, 8) ADD_GAME_STATE (CREW_SOLD_TO_DRUUGE1, 8) ADD_GAME_STATE (PKUNK_DONE_WAR, 1) ADD_GAME_STATE (SYREEN_STACK0, 2) ADD_GAME_STATE (SYREEN_STACK1, 2) ADD_GAME_STATE (SYREEN_STACK2, 2) ADD_GAME_STATE (REFUSED_ULTRON_AT_BOMB, 1) ADD_GAME_STATE (NO_TRICK_AT_SUN, 1) ADD_GAME_STATE (SPATHI_STACK0, 2) ADD_GAME_STATE (SPATHI_STACK1, 1) ADD_GAME_STATE (SPATHI_STACK2, 1) ADD_GAME_STATE (ORZ_STACK0, 1) ADD_GAME_STATE (ORZ_STACK1, 1) END_GAME_STATE #define READ_SPEED_MASK ((1 << 3) - 1) #define NUM_READ_SPEEDS 5 #define COMBAT_SPEED_SHIFT 6 #define COMBAT_SPEED_MASK (((1 << 2) - 1) << COMBAT_SPEED_SHIFT) #define NUM_COMBAT_SPEEDS 4 #define MUSIC_DISABLED (1 << 3) #define SOUND_DISABLED (1 << 4) #define CYBORG_ENABLED (1 << 5) enum { SUPER_MELEE = 0, /* Is also used while in the main menu */ IN_LAST_BATTLE, IN_ENCOUNTER, IN_HYPERSPACE /* in Hyperspace or Quasispace */, IN_INTERPLANETARY, WON_LAST_BATTLE, /* The following three are only used when displaying save game * summaries */ IN_QUASISPACE, IN_PLANET_ORBIT, IN_STARBASE, CHECK_PAUSE = MAKE_WORD (0, (1 << 0)), IN_BATTLE = MAKE_WORD (0, (1 << 1)), START_ENCOUNTER = MAKE_WORD (0, (1 << 2)), START_INTERPLANETARY = MAKE_WORD (0, (1 << 3)), CHECK_LOAD = MAKE_WORD (0, (1 << 4)), CHECK_RESTART = MAKE_WORD (0, (1 << 5)), CHECK_ABORT = MAKE_WORD (0, (1 << 6)), }; typedef UWORD ACTIVITY; typedef struct { // XXX: cur_state is obsolete now and was replaced by process.c:zoom_out BYTE cur_state, glob_flags; BYTE CrewCost, FuelCost; BYTE ModuleCost[NUM_MODULES]; BYTE ElementWorth[NUM_ELEMENT_CATEGORIES]; PPRIMITIVE DisplayArray; ACTIVITY CurrentActivity; CLOCK_STATE GameClock; POINT autopilot; POINT ip_location; STAMP ShipStamp; VELOCITY_DESC velocity; DWORD BattleGroupRef; QUEUE avail_race_q; QUEUE npc_built_ship_q; // Non-player-character list of ships (during encounter) // or list of groups present in solarsys (during IP) QUEUE encounter_q; QUEUE built_ship_q; /* Queue of SIS escort ships */ BYTE GameState[(NUM_GAME_STATE_BITS + 7) >> 3]; } GAME_STATE; typedef GAME_STATE *PGAME_STATE; typedef struct { SIS_STATE SIS_state; GAME_STATE Game_state; } GLOBDATA; typedef GLOBDATA *PGLOBDATA; extern GLOBDATA GlobData; #define GLOBAL(f) GlobData.Game_state.f #define GLOBAL_SIS(f) GlobData.SIS_state.f #define GLOBDATAPTR PGLOBDATA //#define STATE_DEBUG extern BYTE getGameState (int startBit, int endBit); extern void setGameState (int startBit, int endBit, BYTE val #ifdef STATE_DEBUG , const char *name #endif ); #define GET_GAME_STATE(SName) getGameState ((SName), (END_##SName)) #ifdef STATE_DEBUG # define SET_GAME_STATE(SName, val) \ setGameState ((SName), (END_##SName), (val), #SName) #else # define SET_GAME_STATE(SName, val) \ setGameState ((SName), (END_##SName), (val)) #endif extern DWORD getGameState32 (int startBit); extern void setGameState32 (int startBit, DWORD val #ifdef STATE_DEBUG , const char *name #endif ); #define GET_GAME_STATE_32(SName) getGameState32 ((SName)) #ifdef STATE_DEBUG # define SET_GAME_STATE_32(SName, val) \ setGameState32 ((SName), (val), #SName) #else # define SET_GAME_STATE_32(SName, val) \ setGameState32 ((SName), (val)) #endif extern CONTEXT RadarContext; extern void DiscardStarMap (PVOID CodeRef); extern void RetrieveStarMap (void); extern void FreeSC2Data (void); extern BOOLEAN LoadSC2Data (void); void InitGlobData (void); #endif /* _GLOBDATA_H */ uqm-0.6.2/sc2/src/sc2code/init.c0000600000175000017500000001433210543202100014704 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "colors.h" #include "element.h" #include "globdata.h" #include "init.h" #include "port.h" #include "resinst.h" #include "nameref.h" #include "setup.h" #include "units.h" FRAME stars_in_space; FRAME asteroid[NUM_VIEWS]; FRAME blast[NUM_VIEWS]; FRAME explosion[NUM_VIEWS]; BOOLEAN load_animation (PFRAME pixarray, DWORD big_res, DWORD med_res, DWORD sml_res) { DRAWABLE d; if ((d = LoadGraphic (big_res)) == (DRAWABLE)NULL_PTR) return (FALSE); pixarray[0] = CaptureDrawable (d); if (med_res != 0L && (d = LoadGraphic (med_res)) == (DRAWABLE)NULL_PTR) return (FALSE); pixarray[1] = CaptureDrawable (d); if (sml_res != 0L && (d = LoadGraphic (sml_res)) == (DRAWABLE)NULL_PTR) return (FALSE); pixarray[2] = CaptureDrawable (d); return (TRUE); } BOOLEAN free_image (PFRAME pixarray) { BOOLEAN retval; COUNT i; retval = TRUE; for (i = 0; i < NUM_VIEWS; ++i) { if (pixarray[i] != (FRAME)NULL_PTR) { if (!DestroyDrawable (ReleaseDrawable (pixarray[i]))) retval = FALSE; pixarray[i] = (FRAME)NULL_PTR; } } return (retval); } static BYTE space_ini_cnt; BOOLEAN InitSpace (void) { if (space_ini_cnt++ == 0 && LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER) { stars_in_space = CaptureDrawable ( LoadGraphic (STAR_MASK_PMAP_ANIM)); if (stars_in_space == NULL) return FALSE; if (!load_animation (explosion, BOOM_BIG_MASK_PMAP_ANIM, BOOM_MED_MASK_PMAP_ANIM, BOOM_SML_MASK_PMAP_ANIM)) return FALSE; if (!load_animation (blast, BLAST_BIG_MASK_PMAP_ANIM, BLAST_MED_MASK_PMAP_ANIM, BLAST_SML_MASK_PMAP_ANIM)) return FALSE; if (!load_animation (asteroid, ASTEROID_BIG_MASK_PMAP_ANIM, ASTEROID_MED_MASK_PMAP_ANIM, ASTEROID_SML_MASK_PMAP_ANIM)) return FALSE; } return TRUE; } void UninitSpace (void) { if (space_ini_cnt && --space_ini_cnt == 0) { free_image (blast); free_image (explosion); free_image (asteroid); DestroyDrawable (ReleaseDrawable (stars_in_space)); stars_in_space = 0; } } SIZE InitShips (void) { SIZE num_ships; InitSpace (); SetContext (StatusContext); SetContext (SpaceContext); InitDisplayList (); InitGalaxy (); num_ships = NUM_SIDES; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { ReinitQueue (&race_q[0]); ReinitQueue (&race_q[1]); Build (&race_q[0], SIS_RES_INDEX, GOOD_GUY, 0); LoadHyperspace (); --num_ships; } else { COUNT i; RECT r; SetContextFGFrame (Screen); r.corner.x = SAFE_X; r.corner.y = SAFE_Y; r.extent.width = SPACE_WIDTH; r.extent.height = SPACE_HEIGHT; SetContextClipRect (&r); SetContextBackGroundColor (BLACK_COLOR); { CONTEXT OldContext; OldContext = SetContext (ScreenContext); SetContextBackGroundColor (BLACK_COLOR); ClearDrawable (); SetContext (OldContext); } if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) free_gravity_well (); else { #define NUM_ASTEROIDS 5 for (i = 0; i < NUM_ASTEROIDS; ++i) spawn_asteroid (NULL_PTR); #define NUM_PLANETS 1 for (i = 0; i < NUM_PLANETS; ++i) spawn_planet (); } } // FlushInput (); return (num_ships); } void UninitShips (void) { BYTE crew_retrieved; SIZE i; HELEMENT hElement, hNextElement; STARSHIPPTR SPtr[NUM_PLAYERS]; StopSound (); UninitSpace (); for (i = 0; i < NUM_PLAYERS; ++i) SPtr[i] = 0; // Count the crew floating in space. crew_retrieved = 0; for (hElement = GetHeadElement (); hElement != 0; hElement = hNextElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); hNextElement = GetSuccElement (ElementPtr); if (ElementPtr->state_flags & CREW_OBJECT) ++crew_retrieved; UnlockElement (hElement); } for (hElement = GetHeadElement (); hElement != 0; hElement = hNextElement) { ELEMENTPTR ElementPtr; extern void new_ship (PELEMENT ElementPtr); LockElement (hElement, &ElementPtr); hNextElement = GetSuccElement (ElementPtr); if ((ElementPtr->state_flags & PLAYER_SHIP) || ElementPtr->death_func == new_ship) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); // There should only be one ship left in battle. // He gets the crew still floating in space. if (StarShipPtr->RaceDescPtr->ship_info.crew_level) { if (crew_retrieved >= StarShipPtr->RaceDescPtr->ship_info.max_crew - StarShipPtr->RaceDescPtr->ship_info.crew_level) StarShipPtr->RaceDescPtr->ship_info.crew_level = StarShipPtr->RaceDescPtr->ship_info.max_crew; else StarShipPtr->RaceDescPtr->ship_info.crew_level += crew_retrieved; } if (StarShipPtr->RaceDescPtr->uninit_func != NULL) (*StarShipPtr->RaceDescPtr->uninit_func) ( StarShipPtr->RaceDescPtr); StarShipPtr->ShipFacing = StarShipPtr->RaceDescPtr->ship_info.var2; StarShipPtr->special_counter = StarShipPtr->RaceDescPtr->ship_info.crew_level; SPtr[WHICH_SIDE (ElementPtr->state_flags)] = StarShipPtr; free_ship (StarShipPtr, TRUE); } UnlockElement (hElement); } GLOBAL (CurrentActivity) &= ~IN_BATTLE; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) { } else if (LOBYTE (GLOBAL (CurrentActivity)) <= IN_ENCOUNTER && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) { for (i = NUM_PLAYERS - 1; i >= 0; --i) { if (SPtr[i]) GetEncounterStarShip (SPtr[i], i); } } if (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER) { ReinitQueue (&race_q[0]); ReinitQueue (&race_q[1]); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) FreeHyperspace (); } } uqm-0.6.2/sc2/src/sc2code/pickmele.c0000600000175000017500000003407310543202103015541 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pickmele.h" #include "build.h" #include "controls.h" #include "intel.h" #include "melee.h" #ifdef NETPLAY # include "netplay/netmelee.h" # include "netplay/netmisc.h" # include "netplay/notify.h" #endif #include "races.h" #include "settings.h" #include "setup.h" #include "sounds.h" #include "libs/inplib.h" #include "libs/mathlib.h" #define NUM_MELEE_COLS_ORIG NUM_MELEE_COLUMNS #define PICK_X_OFFS 57 #define PICK_Y_OFFS 24 #define PICK_SIDE_OFFS 100 struct getmelee_struct { BOOLEAN (*InputFunc) (struct getmelee_struct *pInputState); COUNT MenuRepeatDelay; BOOLEAN Initialized; HSTARSHIP hBattleShip; COUNT row, col, ships_left, which_player; COUNT randomIndex; #ifdef NETPLAY BOOLEAN remoteSelected; #endif RECT flash_rect; }; #ifdef NETPLAY static void reportShipSelected (GETMELEE_STATE *gms, COUNT index); #endif // Returns the th ship in the queue, or 0 if it is not available. // For all the ships in the queue, the ShipFacing field contains the // index in the queue. static HSTARSHIP MeleeShipByQueueIndex (const QUEUE *queue, COUNT index) { HSTARSHIP hShip; HSTARSHIP hNextShip; for (hShip = GetHeadLink (queue); hShip != 0; hShip = hNextShip) { STARSHIPPTR StarShipPtr = LockStarShip (queue, hShip); if (StarShipPtr->ShipFacing == index) { hNextShip = hShip; if (StarShipPtr->RaceResIndex == 0) hShip = 0; UnlockStarShip (queue, hNextShip); break; } hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (queue, ship); } return hShip; } // Returns the th available ship in the queue. static HSTARSHIP MeleeShipByUsedIndex (const QUEUE *queue, COUNT index) { HSTARSHIP hShip; HSTARSHIP hNextShip; for (hShip = GetHeadLink (queue); hShip != 0; hShip = hNextShip) { STARSHIPPTR StarShipPtr = LockStarShip (queue, hShip); if (StarShipPtr->RaceResIndex && index-- == 0) { UnlockStarShip (queue, hShip); break; } hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (queue, hShip); } return hShip; } #if 0 static COUNT queueIndexFromShip (HSTARSHIP hShip) { COUNT result; STARSHIPPTR StarShipPtr = LockStarShip (queue, hShip); result = StarShipPtr->ShipFacing; UnlockStarShip (queue, hShip); } #endif static void PickMelee_ChangedSelection (GETMELEE_STATE *gms) { LockMutex (GraphicsLock); gms->flash_rect.corner.x = PICK_X_OFFS + ((ICON_WIDTH + 2) * gms->col); gms->flash_rect.corner.y = PICK_Y_OFFS + ((ICON_HEIGHT + 2) * gms->row) + ((1 - gms->which_player) * PICK_SIDE_OFFS); SetFlashRect (&gms->flash_rect, (FRAME)0); UnlockMutex (GraphicsLock); } // Select a new ship from the fleet for battle. // Returns 'TRUE' if no choice has been made yet; this function is to be // called again later. // Returns 'FALSE' if a choice has been made. gms->hStarShip is set // to the chosen (or randomly selected) ship, or to 0 if 'exit' has // been chosen. /* TODO: Include player timeouts */ static BOOLEAN DoGetMelee (GETMELEE_STATE *gms) { BOOLEAN left, right, up, down, select; COUNT which_player = gms->which_player; BOOLEAN done = FALSE; SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); if (!gms->Initialized) { gms->Initialized = TRUE; gms->row = 0; gms->col = NUM_MELEE_COLS_ORIG; #ifdef NETPLAY gms->remoteSelected = FALSE; #endif // We determine in advance which ship would be chosen if the player // wants a random ship, to keep it simple to keep network parties // synchronised. gms->randomIndex = (COUNT)TFB_Random () % gms->ships_left; PickMelee_ChangedSelection (gms); return TRUE; } SleepThread (ONE_SECOND / 120); #ifdef NETPLAY netInput (); if (!allConnected()) goto aborted; #endif if (GLOBAL (CurrentActivity) & CHECK_ABORT) goto aborted; if (PlayerInput[which_player] == ComputerInput) { /* TODO: Make this a frame-by-frame thing. This code is currently * copied from intel.c's computer_intelligence */ SleepThread (ONE_SECOND >> 1); left = right = up = down = FALSE; select = TRUE; } #ifdef NETPLAY else if (PlayerInput[which_player] == NetworkInput) { flushPacketQueues (); if (gms->remoteSelected) return FALSE; return TRUE; } #endif else { CONTROL_TEMPLATE template; if (which_player == 0) template = PlayerOne; else template = PlayerTwo; left = PulsedInputState.key[template][KEY_LEFT]; right = PulsedInputState.key[template][KEY_RIGHT]; up = PulsedInputState.key[template][KEY_UP]; down = PulsedInputState.key[template][KEY_DOWN]; select = PulsedInputState.key[template][KEY_WEAPON]; } if (select) { if (gms->col == NUM_MELEE_COLS_ORIG) { if (gms->row == 0) { // Random ship gms->hBattleShip = MeleeShipByUsedIndex ( &race_q[which_player], gms->randomIndex); #ifdef NETPLAY reportShipSelected (gms, (COUNT)~0); #endif done = TRUE; } else { // Selected exit if (ConfirmExit ()) goto aborted; } } else { COUNT ship_index; ship_index = (gms->row * NUM_MELEE_COLS_ORIG) + gms->col; gms->hBattleShip = MeleeShipByQueueIndex ( &race_q[which_player], ship_index); if (gms->hBattleShip != 0) { // Selection contains a ship. #ifdef NETPLAY reportShipSelected (gms, ship_index); #endif done = TRUE; } } } else { // Process motion commands. COUNT new_row, new_col; new_row = gms->row; new_col = gms->col; if (left) { if (new_col-- == 0) new_col = NUM_MELEE_COLS_ORIG; } else if (right) { if (new_col++ == NUM_MELEE_COLS_ORIG) new_col = 0; } if (up) { if (new_row-- == 0) new_row = NUM_MELEE_ROWS - 1; } else if (down) { if (++new_row == NUM_MELEE_ROWS) new_row = 0; } if (new_row != gms->row || new_col != gms->col) { gms->row = new_row; gms->col = new_col; PlayMenuSound (MENU_SOUND_MOVE); PickMelee_ChangedSelection (gms); } } #ifdef NETPLAY flushPacketQueues (); #endif return !done; aborted: #ifdef NETPLAY flushPacketQueues (); #endif gms->hBattleShip = 0; GLOBAL (CurrentActivity) &= ~CHECK_ABORT; return FALSE; } #ifdef NETPLAY static void endMeleeCallback (NetConnection *conn, void *arg) { NetMelee_reenterState_inSetup (conn); (void) arg; } #endif HSTARSHIP GetMeleeStarShip (STARSHIPPTR LastStarShipPtr, COUNT which_player) { COUNT ships_left; TEXT t; UNICODE buf[40]; STAMP s; CONTEXT OldContext; GETMELEE_STATE gmstate; STARSHIPPTR StarShipPtr; BOOLEAN firstTime; if (!(GLOBAL (CurrentActivity) & IN_BATTLE)) return (0); #ifdef NETPLAY { NetConnection *conn = netConnections[which_player]; if (conn != NULL) { BattleStateData *battleStateData; battleStateData = (BattleStateData *) NetConnection_getStateData(conn); battleStateData->getMeleeState = &gmstate; } } #endif s.frame = SetAbsFrameIndex (PickMeleeFrame, which_player); OldContext = SetContext (OffScreenContext); SetContextFGFrame (s.frame); if (LastStarShipPtr == 0 || LastStarShipPtr->special_counter == 0) { COUNT cur_bucks; HSTARSHIP hBattleShip, hNextShip; cur_bucks = 0; for (hBattleShip = GetHeadLink (&race_q[which_player]); hBattleShip != 0; hBattleShip = hNextShip) { StarShipPtr = LockStarShip (&race_q[which_player], hBattleShip); if (StarShipPtr == LastStarShipPtr) { LastStarShipPtr->RaceResIndex = 0; gmstate.col = LastStarShipPtr->ShipFacing; s.origin.x = 3 + ((ICON_WIDTH + 2) * (gmstate.col % NUM_MELEE_COLS_ORIG)); s.origin.y = 9 + ((ICON_HEIGHT + 2) * (gmstate.col / NUM_MELEE_COLS_ORIG)); s.frame = SetAbsFrameIndex (StatusFrame, 3); DrawStamp (&s); s.frame = SetAbsFrameIndex (PickMeleeFrame, which_player); } else if (StarShipPtr->RaceResIndex) { cur_bucks += StarShipPtr->special_counter; } hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (&race_q[which_player], hBattleShip); } GetFrameRect (s.frame, &gmstate.flash_rect); gmstate.flash_rect.extent.width -= 4; t.baseline.x = gmstate.flash_rect.extent.width; gmstate.flash_rect.corner.x = gmstate.flash_rect.extent.width - (6 * 3); gmstate.flash_rect.corner.y = 2; gmstate.flash_rect.extent.width = (6 * 3); gmstate.flash_rect.extent.height = 7 - 2; SetContextForeGroundColor (PICK_BG_COLOR); DrawFilledRectangle (&gmstate.flash_rect); sprintf (buf, "%d", cur_bucks); t.baseline.y = 7; t.align = ALIGN_RIGHT; t.pStr = buf; t.CharCount = (COUNT)~0; SetContextFont (TinyFont); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C)); font_DrawText (&t); } SetContext (SpaceContext); s.origin.x = PICK_X_OFFS - 3; s.origin.y = PICK_Y_OFFS - 9 + ((1 - which_player) * PICK_SIDE_OFFS); DrawStamp (&s); if (LOBYTE (battle_counter) == 0 || HIBYTE (battle_counter) == 0) { // One side is out of ships. Game over. DWORD TimeOut; BOOLEAN PressState, ButtonState; s.origin.y = PICK_Y_OFFS - 9 + (which_player * PICK_SIDE_OFFS); s.frame = SetAbsFrameIndex (PickMeleeFrame, (COUNT) (1 - which_player)); DrawStamp (&s); TimeOut = GetTimeCounter () + (ONE_SECOND * 4); SetContext (OldContext); UnlockMutex (GraphicsLock); PressState = PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_CANCEL]; do { UpdateInputState (); ButtonState = PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_CANCEL]; if (PressState) { PressState = ButtonState; ButtonState = FALSE; } TaskSwitch (); } while (!(GLOBAL (CurrentActivity) & CHECK_ABORT) && (!ButtonState && (!(PlayerControl[0] & PlayerControl[1] & PSYTRON_CONTROL) || GetTimeCounter () < TimeOut))); #ifdef NETPLAY setStateConnections (NetState_endMelee); localReadyConnections (endMeleeCallback, NULL, true); #endif LockMutex (GraphicsLock); return (0); } // Fade in if we're not already faded in. #ifdef NETPLAY // Hack. If one side is network controlled, the top player does not have // to be the first player to get a chance to select his ship, // As what is top locally doesn't have to be the same as what it is // remotely. // This check is not so nice as it replicates the code used to decide // which party is first in selectAllShips. firstTime = (LastStarShipPtr == 0) && ((which_player == 0) == (((PlayerControl[0] & NETWORK_CONTROL) && !NetConnection_getDiscriminant(netConnections[0])) || ((PlayerControl[1] & NETWORK_CONTROL) && NetConnection_getDiscriminant(netConnections[1])))); #else firstTime = LastStarShipPtr == 0 && which_player == 1; #endif if (firstTime) { BYTE fade_buf[] = {FadeAllToColor}; SleepThreadUntil (XFormColorMap ((COLORMAPPTR) fade_buf, ONE_SECOND / 2) + ONE_SECOND / 60); FlushColorXForms (); } if (which_player == 0) ships_left = LOBYTE (battle_counter); else ships_left = HIBYTE (battle_counter); gmstate.flash_rect.extent.width = (ICON_WIDTH + 2); gmstate.flash_rect.extent.height = (ICON_HEIGHT + 2); #ifdef NETPLAY { bool allOk = negotiateReadyConnections (true, NetState_selectShip); if (!allOk) { // Some network connection has been reset. gmstate.hBattleShip = 0; } } #endif gmstate.InputFunc = DoGetMelee; SetDefaultMenuRepeatDelay (); gmstate.Initialized = FALSE; gmstate.ships_left = ships_left; gmstate.which_player = which_player; UnlockMutex (GraphicsLock); ResetKeyRepeat (); DoInput ((PVOID)&gmstate, FALSE); LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); if (gmstate.hBattleShip == 0) { // Aborting. GLOBAL (CurrentActivity) &= ~IN_BATTLE; } else { StarShipPtr = LockStarShip (&race_q[which_player], gmstate.hBattleShip); OwnStarShip (StarShipPtr, 1 << which_player, StarShipPtr->captains_name_index); StarShipPtr->captains_name_index = 0; UnlockStarShip (&race_q[which_player], gmstate.hBattleShip); PlayMenuSound (MENU_SOUND_SUCCESS); WaitForSoundEnd (0); } #ifdef NETPLAY { NetConnection *conn = netConnections[which_player]; if (conn != NULL && NetConnection_isConnected(conn)) { BattleStateData *battleStateData; battleStateData = (BattleStateData *) NetConnection_getStateData(conn); battleStateData->getMeleeState = NULL; } } #endif return (gmstate.hBattleShip); } #ifdef NETPLAY // Called when a ship selection has arrived from a remote player. bool updateMeleeSelection (GETMELEE_STATE *gms, COUNT player, COUNT ship) { if (gms == NULL) { // This happens when we get an update message from a connection // for who we are not selecting a ship (yet?). fprintf (stderr, "Unexpected ship selection packet received.\n"); return false; } if (ship == (COUNT) ~0) { // Random selection. gms->hBattleShip = MeleeShipByUsedIndex (&race_q[player], gms->randomIndex); gms->remoteSelected = TRUE; NetConnection_setState (netConnections[player], NetState_interBattle); return true; } gms->hBattleShip = MeleeShipByQueueIndex (&race_q[player], ship); if (gms->hBattleShip == 0) { fprintf (stderr, "Invalid ship selection received from remote " "party.\n"); return false; } gms->remoteSelected = TRUE; NetConnection_setState (netConnections[player], NetState_interBattle); return true; } static void reportShipSelected (GETMELEE_STATE *gms, COUNT index) { size_t playerI; for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { NetConnection *conn = netConnections[playerI]; if (conn == NULL) continue; if (!NetConnection_isConnected (conn)) continue; Netplay_selectShip (conn, index); NetConnection_setState (conn, NetState_interBattle); } (void) gms; } #endif uqm-0.6.2/sc2/src/sc2code/mouse_err.c0000600000175000017500000000153610543202103015746 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "controls.h" #include "gamestr.h" void MouseError (void) { DoPopupWindow (GAME_STRING (MAINMENU_STRING_BASE + 56)); } uqm-0.6.2/sc2/src/sc2code/sounds.c0000600000175000017500000001002310543202101015246 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "settings.h" #include "sounds.h" #include "units.h" SOUND MenuSounds; SOUND GameSounds; #define MAX_SOUNDS 8 static BYTE num_sounds = 0; static SOUND sound_buf[MAX_SOUNDS]; static ELEMENTPTR sound_posobj[MAX_SOUNDS]; void PlaySound (SOUND S, SoundPosition Pos, ELEMENTPTR PositionalObject, BYTE Priority) { BYTE chan, c; static BYTE lru_channel[NUM_FX_CHANNELS] = {0, 1, 2, 3}; static SOUND channel[NUM_FX_CHANNELS] = {0, 0, 0, 0}; if (S == 0) return; for (chan = 0; chan < NUM_FX_CHANNELS; ++chan) { if (S == channel[chan]) break; } if (chan == NUM_FX_CHANNELS) { for (chan = 0; chan < NUM_FX_CHANNELS; ++chan) { if (!ChannelPlaying (chan + MIN_FX_CHANNEL)) break; } if (chan == NUM_FX_CHANNELS) chan = lru_channel[0]; } channel[chan] = S; for (c = 0; c < NUM_FX_CHANNELS - 1; ++c) { if (lru_channel[c] == chan) { memmove ((PBYTE)&lru_channel[c], (PBYTE)&lru_channel[c + 1], (NUM_FX_CHANNELS - 1) - c); break; } } lru_channel[NUM_FX_CHANNELS - 1] = chan; PlaySoundEffect (S, chan + MIN_FX_CHANNEL, Pos, PositionalObject, Priority); } void PlayMenuSound (MENU_SOUND_EFFECT S) { PlaySoundEffect (SetAbsSoundIndex (MenuSounds, S), 0, NotPositional (), NULL, GAME_SOUND_PRIORITY); } void ProcessSound (SOUND Sound, ELEMENTPTR PositionalObject) { if (Sound == (SOUND)~0) { memset (sound_buf, 0, sizeof (sound_buf)); memset (sound_posobj, 0, sizeof (sound_posobj)); num_sounds = MAX_SOUNDS; } else if (num_sounds < MAX_SOUNDS) { sound_buf[num_sounds] = Sound; sound_posobj[num_sounds++] = PositionalObject; } } SoundPosition CalcSoundPosition (ELEMENTPTR ElementPtr) { SoundPosition pos; if (ElementPtr == NULL) { pos.x = pos.y = 0; pos.positional = FALSE; } else { GRAPHICS_PRIM objtype; objtype = GetPrimType (&DisplayArray[ElementPtr->PrimIndex]); if (objtype == LINE_PRIM) { pos.x = DisplayArray[ElementPtr->PrimIndex].Object.Line.first.x; pos.y = DisplayArray[ElementPtr->PrimIndex].Object.Line.first.y; } else { pos.x = DisplayArray[ElementPtr->PrimIndex].Object.Point.x; pos.y = DisplayArray[ElementPtr->PrimIndex].Object.Point.y; } pos.x -= (SPACE_WIDTH >> 1); pos.y -= (SPACE_HEIGHT >> 1); pos.positional = TRUE; } return pos; } SoundPosition NotPositional (void) { return CalcSoundPosition (NULL); } /* Updates positional sound effects */ void UpdateSoundPositions (void) { COUNT i; for (i = FIRST_SFX_CHANNEL; i <= LAST_SFX_CHANNEL; ++i) { ELEMENTPTR posobj; if (!ChannelPlaying(i)) continue; posobj = GetPositionalObject (i); if (posobj != NULL) { SoundPosition pos; pos = CalcSoundPosition (posobj); if (pos.positional) UpdateSoundPosition (i, pos); } } } void FlushSounds (void) { if (num_sounds > 0) { SOUND *pSound; ELEMENTPTR *pSoundPosObj; pSound = sound_buf; pSoundPosObj = sound_posobj; do { SoundPosition pos = CalcSoundPosition (*pSoundPosObj); PlaySound (*pSound++, pos, *pSoundPosObj++, GAME_SOUND_PRIORITY); } while (--num_sounds); } } void RemoveSoundsForObject (ELEMENTPTR PosObj) { int i; for (i = FIRST_SFX_CHANNEL; i <= LAST_SFX_CHANNEL; ++i) { if (GetPositionalObject (i) == PosObj) SetPositionalObject (i, NULL); } for (i = 0; i < num_sounds; ++i) { if (sound_posobj[i] == PosObj) sound_posobj[i] = NULL; } } uqm-0.6.2/sc2/src/sc2code/util.c0000644000175000017500000001363310552135701014745 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "commglue.h" #include "comm.h" #include "controls.h" #include "util.h" #include "setup.h" #include "libs/inplib.h" #include "libs/sound/trackplayer.h" #include "libs/mathlib.h" void DrawStarConBox (PRECT pRect, SIZE BorderWidth, COLOR TopLeftColor, COLOR BottomRightColor, BOOLEAN FillInterior, COLOR InteriorColor) { RECT locRect; if (BorderWidth == 0) BorderWidth = 2; else { SetContextForeGroundColor (TopLeftColor); locRect.corner = pRect->corner; locRect.extent.width = pRect->extent.width; locRect.extent.height = 1; DrawFilledRectangle (&locRect); if (BorderWidth == 2) { ++locRect.corner.x; ++locRect.corner.y; locRect.extent.width -= 2; DrawFilledRectangle (&locRect); } locRect.corner = pRect->corner; locRect.extent.width = 1; locRect.extent.height = pRect->extent.height; DrawFilledRectangle (&locRect); if (BorderWidth == 2) { ++locRect.corner.x; ++locRect.corner.y; locRect.extent.height -= 2; DrawFilledRectangle (&locRect); } SetContextForeGroundColor (BottomRightColor); locRect.corner.x = pRect->corner.x + pRect->extent.width - 1; locRect.corner.y = pRect->corner.y + 1; locRect.extent.height = pRect->extent.height - 1; DrawFilledRectangle (&locRect); if (BorderWidth == 2) { --locRect.corner.x; ++locRect.corner.y; locRect.extent.height -= 2; DrawFilledRectangle (&locRect); } locRect.corner.x = pRect->corner.x; locRect.extent.width = pRect->extent.width; locRect.corner.y = pRect->corner.y + pRect->extent.height - 1; locRect.extent.height = 1; DrawFilledRectangle (&locRect); if (BorderWidth == 2) { ++locRect.corner.x; --locRect.corner.y; locRect.extent.width -= 2; DrawFilledRectangle (&locRect); } } if (FillInterior) { SetContextForeGroundColor (InteriorColor); locRect.corner.x = pRect->corner.x + BorderWidth; locRect.corner.y = pRect->corner.y + BorderWidth; locRect.extent.width = pRect->extent.width - (BorderWidth << 1); locRect.extent.height = pRect->extent.height - (BorderWidth << 1); DrawFilledRectangle (&locRect); } } DWORD SeedRandomNumbers (void) { DWORD cur_time; cur_time = GetTimeCounter (); TFB_SeedRandom (cur_time); return (cur_time); } void WaitForNoInput (SIZE Duration) { BOOLEAN PressState; PressState = AnyButtonPress (FALSE); if (Duration < 0) { if (PressState) return; Duration = -Duration; } else if (!PressState) return; { DWORD TimeOut; BOOLEAN ButtonState; TimeOut = GetTimeCounter () + Duration; do { ButtonState = AnyButtonPress (FALSE); if (PressState) { PressState = ButtonState; ButtonState = 0; } } while (!ButtonState && (TaskSwitch (), GetTimeCounter ()) <= TimeOut); } } BOOLEAN PauseGame (void) { RECT r; STAMP s; CONTEXT OldContext; FRAME F; HOT_SPOT OldHot; RECT OldRect; if (ActivityFrame == 0 || (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_PAUSE)) || (LastActivity & (CHECK_LOAD | CHECK_RESTART))) return (FALSE); GLOBAL (CurrentActivity) |= CHECK_PAUSE; if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) SuspendGameClock (); if (CommData.ConversationPhrases && PlayingTrack ()) PauseTrack (); LockMutex (GraphicsLock); OldContext = SetContext (ScreenContext); OldHot = SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); GetContextClipRect (&OldRect); SetContextClipRect (NULL_PTR); GetFrameRect (ActivityFrame, &r); r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; s.origin = r.corner; s.frame = ActivityFrame; F = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); SetSystemRect (&r); DrawStamp (&s); // Releasing the lock lets the rotate_planet_task // draw a frame. PauseRotate can still allow one more frame // to be drawn, so it is safer to just not release the lock //UnlockMutex (GraphicsLock); FlushGraphics (); //LockMutex (GraphicsLock); while (ImmediateInputState.menu[KEY_PAUSE]) TaskSwitch (); while (!ImmediateInputState.menu[KEY_PAUSE]) TaskSwitch (); while (ImmediateInputState.menu[KEY_PAUSE]) TaskSwitch (); GamePaused = FALSE; s.frame = F; DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); ClearSystemRect (); SetContextClipRect (&OldRect); SetFrameHot (Screen, OldHot); SetContext (OldContext); WaitForNoInput (ONE_SECOND / 4); FlushInput (); if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) ResumeGameClock (); if (CommData.ConversationPhrases && PlayingTrack ()) { ResumeTrack (); if (CommData.AlienTransitionDesc.AnimFlags & TALK_DONE) do_subtitles ((void *)~0); } UnlockMutex (GraphicsLock); TaskSwitch (); GLOBAL (CurrentActivity) &= ~CHECK_PAUSE; return (TRUE); } // Waits for a new button to be pressed // and returns TRUE if Quit was selected BOOLEAN WaitAnyButtonOrQuit (BOOLEAN CheckSpecial) { while (AnyButtonPress (TRUE)) TaskSwitch (); while (!AnyButtonPress (TRUE) && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) TaskSwitch (); /* Satisfy unused parameter */ (void) CheckSpecial; return (GLOBAL (CurrentActivity) & CHECK_ABORT) != 0; } uqm-0.6.2/sc2/src/sc2code/battle.h0000600000175000017500000000236010543202103015222 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _BATTLE_H #define _BATTLE_H #include "libs/compiler.h" #include "displist.h" typedef struct battlestate_struct { BOOLEAN (*InputFunc) (struct battlestate_struct *pInputState); COUNT MenuRepeatDelay; BOOLEAN first_time; DWORD NextTime; } BATTLE_STATE; extern QUEUE disp_q; extern SIZE battle_counter; extern BOOLEAN instantVictory; #ifdef NETPLAY typedef DWORD BattleFrameCounter; extern BattleFrameCounter battleFrameCount; extern COUNT currentDeadSide; #endif extern BOOLEAN Battle (void); #endif /* _BATTLE_H */ uqm-0.6.2/sc2/src/sc2code/isndres.h0000600000175000017500000000014410543202102015413 0ustar joeyjoey#define MENU_SOUNDS 0x04000005L #define GAME_SOUNDS 0x04200105L #define LANDER_SOUNDS 0x05400205L uqm-0.6.2/sc2/src/sc2code/oscill.c0000600000175000017500000001007210543202101015224 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "oscill.h" #include "sis.h" #include "libs/graphics/gfx_common.h" #include "libs/graphics/drawable.h" #include "libs/sound/trackplayer.h" static FRAMEPTR scope_frame; static int scope_init = 0; static TFB_Image *scope_bg = NULL; static TFB_Image *scope_surf = NULL; static UBYTE scope_data[RADAR_WIDTH - 2]; BOOLEAN oscillDisabled = FALSE; void InitOscilloscope (DWORD x, DWORD y, DWORD width, DWORD height, FRAME f) { scope_frame = f; if (!scope_init) { TFB_Canvas scope_bg_canvas, scope_surf_canvas; if (TFB_DrawCanvas_IsPaletted (scope_frame->image->NormalImg)) { scope_bg_canvas = TFB_DrawCanvas_New_Paletted (width, height, scope_frame->image->Palette, -1); scope_surf_canvas = TFB_DrawCanvas_New_Paletted (width, height, scope_frame->image->Palette, -1); } else { scope_bg_canvas = TFB_DrawCanvas_New_ForScreen (width, height, FALSE); scope_surf_canvas = TFB_DrawCanvas_New_ForScreen (width, height, FALSE); } scope_bg = TFB_DrawImage_New (scope_bg_canvas); scope_surf = TFB_DrawImage_New (scope_surf_canvas); TFB_DrawImage_Image (scope_frame->image, 0, 0, 0, NULL, scope_bg); scope_init = 1; } /* remove compiler warnings */ (void) x; (void) y; } void UninitOscilloscope (void) { // XXX: Is never called (BUG?) if (scope_bg) { TFB_DrawImage_Delete (scope_bg); scope_bg = NULL; } if (scope_surf) { TFB_DrawImage_Delete (scope_surf); scope_surf = NULL; } scope_init = 0; } // draws the oscilloscope void Oscilloscope (DWORD grab_data) { STAMP s; if (oscillDisabled) return; if (!grab_data) return; TFB_DrawImage_Image (scope_bg, 0, 0, 0, NULL, scope_surf); if (GetSoundData (scope_data)) { int i, r, g, b; TFB_DrawCanvas_GetPixel (scope_bg->NormalImg, scope_bg->extent.width / 2, scope_bg->extent.height / 2, &r, &g, &b); for (i = 0; i < RADAR_WIDTH - 3; ++i) TFB_DrawImage_Line (i + 1, scope_data[i], i + 2, scope_data[i + 1], r, g, b, scope_surf); } TFB_DrawImage_Image (scope_surf, 0, 0, 0, NULL, scope_frame->image); s.frame = scope_frame; s.origin.x = s.origin.y = 0; DrawStamp (&s); } static STAMP sliderStamp; static STAMP buttonStamp; static BOOLEAN sliderChanged = FALSE; int sliderSpace; // slider width - button width BOOLEAN sliderDisabled = FALSE; /* * Initialise the communication progress bar * x - x location of slider * y - y location of slider * width - width of slider * height - height of slider * bwidth - width of button indicating current progress * bheight - height of button indicating progress * f - image for the slider */ void InitSlider (int x, int y, int width, int height, int bwidth, int bheight, FRAME f) { sliderStamp.origin.x = x; sliderStamp.origin.y = y; sliderStamp.frame = f; buttonStamp.origin.x = x; buttonStamp.origin.y = y - ((bheight - height) >> 1); sliderSpace = width - bwidth; } void SetSliderImage (FRAME f) { sliderChanged = TRUE; buttonStamp.frame = f; } void Slider (void) { int offs; static int last_offs = -1; if (sliderDisabled) return; offs = GetSoundInfo (sliderSpace); if (offs != last_offs || sliderChanged) { sliderChanged = FALSE; last_offs = offs; buttonStamp.origin.x = sliderStamp.origin.x + offs; BatchGraphics (); DrawStamp (&sliderStamp); DrawStamp (&buttonStamp); UnbatchGraphics (); } } uqm-0.6.2/sc2/src/sc2code/comm.c0000600000175000017500000012311410543202101014674 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define COMM_INTERNAL #include "comm.h" #include "build.h" #include "commanim.h" #include "commglue.h" #include "controls.h" #include "colors.h" #include "encount.h" #include "endian_uqm.h" #include "gamestr.h" #include "options.h" #include "load.h" #include "oscill.h" #include "settings.h" #include "setup.h" #include "sounds.h" #include "nameref.h" #include "uqmdebug.h" #include "libs/graphics/gfx_common.h" #include "libs/inplib.h" #include "libs/sound/sound.h" #include "libs/sound/trackint.h" #include "libs/log.h" #include #define MAX_RESPONSES 8 #define BACKGROUND_VOL \ (speechVolumeScale == 0.0f ? NORMAL_VOLUME : (NORMAL_VOLUME >> 1)) #define FOREGROUND_VOL NORMAL_VOLUME LOCDATA CommData; int cur_comm; UNICODE shared_phrase_buf[2048]; typedef struct response_entry { RESPONSE_REF response_ref; TEXT response_text; RESPONSE_FUNC response_func; } RESPONSE_ENTRY; typedef RESPONSE_ENTRY *PRESPONSE_ENTRY; typedef struct encounter_state { BOOLEAN (*InputFunc) (struct encounter_state *pES); COUNT MenuRepeatDelay; COUNT Initialized; BYTE num_responses, cur_response, top_response; RESPONSE_ENTRY response_list[MAX_RESPONSES]; Task AnimTask; COUNT phrase_buf_index; UNICODE phrase_buf[512]; } ENCOUNTER_STATE; typedef ENCOUNTER_STATE *PENCOUNTER_STATE; static PENCOUNTER_STATE pCurInputState; static SUBTITLE_STATE subtitle_state = DONE_SUBTITLE; static Mutex subtitle_mutex; TEXT SubtitleText; static const UNICODE * volatile last_subtitle; CONTEXT TextCacheContext; FRAME TextCacheFrame; RECT CommWndRect = { // default values; actually inited by HailAlien() {SIS_ORG_X, SIS_ORG_Y}, {0, 0} }; /* _count_lines - sees how many lines a given input string would take to * display given the line wrapping information */ static int _count_lines (PTEXT pText) { SIZE text_width; const unsigned char *pStr; int numLines = 0; BOOLEAN eol; text_width = CommData.AlienTextWidth; SetContextFont (CommData.AlienFont); pStr = pText->pStr; do { ++numLines; pText->pStr = pStr; eol = getLineWithinWidth (pText, &pStr, text_width, (COUNT)~0); } while (!eol); pText->pStr = pStr; return numLines; } // status == -1: draw highlighted player dialog option // status == -2: draw non-highlighted player dialog option // status == -4: use current context, and baseline from pTextIn // status == 1: draw alien speech; subtitle cache is used static COORD add_text (int status, PTEXT pTextIn) { COUNT maxchars, numchars; TEXT locText; PTEXT pText; SIZE leading; const unsigned char *pStr; SIZE text_width; int num_lines = 0; static COORD last_baseline; BOOLEAN eol; CONTEXT OldContext; BatchGraphics (); maxchars = (COUNT)~0; if (status == 1) { if (last_subtitle == pTextIn->pStr) { // draws cached subtitle STAMP s; s.origin.x = 0; s.origin.y = 0; s.frame = TextCacheFrame; DrawStamp (&s); UnbatchGraphics (); return last_baseline; } else { // draw to subtitle cache; prepare first OldContext = SetContext (TextCacheContext); ClearDrawable (); last_subtitle = pTextIn->pStr; } text_width = CommData.AlienTextWidth; SetContextFont (CommData.AlienFont); GetContextFontLeading (&leading); pText = pTextIn; } else if (GetContextFontLeading (&leading), status <= -4) { text_width = (SIZE) (SIS_SCREEN_WIDTH - 8 - (TEXT_X_OFFS << 2)); pText = pTextIn; } else { text_width = (SIZE) (SIS_SCREEN_WIDTH - 8 - (TEXT_X_OFFS << 2)); switch (status) { case -3: // Unknown. Never reached; color matches the background color. SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); break; case -2: // Not highlighted dialog options. SetContextForeGroundColor (COMM_PLAYER_TEXT_NORMAL_COLOR); break; case -1: // Currently highlighted dialog option. SetContextForeGroundColor (COMM_PLAYER_TEXT_HIGHLIGHT_COLOR); break; } maxchars = pTextIn->CharCount; locText = *pTextIn; locText.baseline.x -= 8; locText.CharCount = (COUNT)~0; locText.pStr = "*"; font_DrawText (&locText); locText = *pTextIn; pText = &locText; pText->baseline.y -= leading; } numchars = 0; pStr = pText->pStr; if (status > 0 && (CommData.AlienTextValign & (VALIGN_MIDDLE | VALIGN_BOTTOM))) { num_lines = _count_lines(pText); if (CommData.AlienTextValign == VALIGN_BOTTOM) pText->baseline.y -= (leading * num_lines); else if (CommData.AlienTextValign == VALIGN_MIDDLE) pText->baseline.y -= ((leading * num_lines) / 2); if (pText->baseline.y < 0) pText->baseline.y = 0; } do { pText->pStr = pStr; pText->baseline.y += leading; eol = getLineWithinWidth (pText, &pStr, text_width, maxchars); maxchars -= pText->CharCount; if (maxchars != 0) --maxchars; numchars += pText->CharCount; if (status <= 0) { // Player dialog option or (status == -4) other non-alien // text. if (pText->baseline.y < SIS_SCREEN_HEIGHT) font_DrawText (pText); if (status < -4 && pText->baseline.y >= -status - 10) { // Never actually reached. Status is never <-4. ++pStr; break; } } else { // Alien speech // Draw the background by drawing the same text in the // background color one pixel shifted to all 4 directions. SetContextForeGroundColor (CommData.AlienTextBColor); --pText->baseline.x; font_DrawText (pText); ++pText->baseline.x; --pText->baseline.y; font_DrawText (pText); ++pText->baseline.x; ++pText->baseline.y; font_DrawText (pText); --pText->baseline.x; ++pText->baseline.y; font_DrawText (pText); SetContextForeGroundColor (CommData.AlienTextFColor); --pText->baseline.y; font_DrawText (pText); } } while (!eol && maxchars); pText->pStr = pStr; if (status == 1) { STAMP s; // We were drawing to cache -- flush to screen SetContext (OldContext); s.origin.x = s.origin.y = 0; s.frame = TextCacheFrame; DrawStamp (&s); last_baseline = pText->baseline.y; } UnbatchGraphics (); return (pText->baseline.y); } // This function calculates how much of a string can be fitted within // a specific width, up to a newline or terminating \0. // pText is the text to be fitted. pText->CharCount will be set to the // number of characters that fitted. // startNext will be filled with the start of the first word that // doesn't fit in one line, or if an entire line fits, to the character // past the newline, or if the entire string fits, to the end of the // string. // maxWidth is the maximum number of pixels that a line may be wide // ASSUMPTION: there are no words in the text wider than maxWidth // maxChars is the maximum number of characters (not bytes) that are to // be fitted. // TRUE is returned if a complete line fitted // FALSE otherwise BOOLEAN getLineWithinWidth(TEXT *pText, const unsigned char **startNext, SIZE maxWidth, COUNT maxChars) { BOOLEAN eol; // The end of the line of text has been reached. BOOLEAN done; // We cannot add any more words. RECT rect; COUNT oldCount; const unsigned char *ptr; const unsigned char *wordStart; wchar_t ch; COUNT charCount; //GetContextClipRect (&rect); eol = FALSE; done = FALSE; oldCount = 1; charCount = 0; ch = '\0'; ptr = pText->pStr; for (;;) { wordStart = ptr; // Scan one word. for (;;) { if (*ptr == '\0') { eol = TRUE; done = TRUE; break; } ch = getCharFromString (&ptr); eol = ch == '\0' || ch == '\n' || ch == '\r'; done = eol || charCount >= maxChars; if (done || ch == ' ') break; charCount++; } oldCount = pText->CharCount; pText->CharCount = charCount; TextRect (pText, &rect, NULL_PTR); if (rect.extent.width >= maxWidth) { pText->CharCount = oldCount; *startNext = wordStart; return FALSE; } if (done) { *startNext = ptr; return eol; } charCount++; // For the space in between words. } } static void DrawSISComWindow (void) { CONTEXT OldContext; if (LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) { RECT r; OldContext = SetContext (SpaceContext); r.corner.x = 0; r.corner.y = SLIDER_Y + SLIDER_HEIGHT; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT - r.corner.y; SetContextForeGroundColor (COMM_PLAYER_BACKGROUND_COLOR); DrawFilledRectangle (&r); SetContext (OldContext); } #ifdef NEVER else { #define NUM_CREDITS 5 BYTE j; TEXT t; STRING OldStrings; extern STRING CreditStrings; t.baseline.x = SCREEN_WIDTH >> 1; t.baseline.y = RADAR_Y - 5; t.align = ALIGN_CENTER; OldContext = SetContext (ScreenContext); OldStrings = SetRelStringTableIndex (CreditStrings, -NUM_CREDITS); SetContextFont (MicroFont); BatchGraphics (); for (j = 0; j < NUM_CREDITS; ++j) { SetContextForeGroundColor (BLACK_COLOR); t.pStr = (UNICODE *)GetStringAddress (OldStrings); t.CharCount = GetStringLength (OldStrings); OldStrings = SetRelStringTableIndex (OldStrings, 1); font_DrawText (&t); SetContextForeGroundColor (WHITE_COLOR); t.pStr = (PBYTE)GetStringAddress (CreditStrings); t.CharCount = GetStringLength (CreditStrings); CreditStrings = SetRelStringTableIndex (CreditStrings, 1); font_DrawText (&t); if (j) t.baseline.y += 12; else { t.baseline.y += 16; SetContextFont (StarConFont); } } UnbatchGraphics (); SetContext (OldContext); } #endif /* NEVER */ } void DrawAlienFrame (FRAME aframe, PSEQUENCE pSeq) { COUNT i; STAMP s; ANIMATION_DESCPTR ADPtr; s.origin.x = -SAFE_X; s.origin.y = 0; s.frame = CommData.AlienFrame; if (s.frame == 0) s.frame = aframe; BatchGraphics (); DrawStamp (&s); i = CommData.NumAnimations; ADPtr = &CommData.AlienAmbientArray[i]; while (i--) { --ADPtr; if (!(ADPtr->AnimFlags & ANIM_MASK)) { s.frame = SetAbsFrameIndex (s.frame, ADPtr->StartIndex); DrawStamp (&s); ADPtr->AnimFlags |= ANIM_DISABLED; } else if (pSeq) { if (pSeq->AnimType == PICTURE_ANIM) { s.frame = pSeq->AnimObj.CurFrame; DrawStamp (&s); } --pSeq; } } if (aframe && CommData.AlienFrame && aframe != CommData.AlienFrame) { s.frame = aframe; DrawStamp (&s); } UnbatchGraphics (); } void init_communication (void) { subtitle_mutex = CreateMutex ("Subtitle Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); } void uninit_communication (void) { DestroyMutex (subtitle_mutex); } volatile BOOLEAN ClearSummary; static volatile BOOLEAN ClearSubtitle; static void RefreshResponses (PENCOUNTER_STATE pES) { COORD y; BYTE response; SIZE leading; STAMP s; SetContext (SpaceContext); GetContextFontLeading (&leading); BatchGraphics (); DrawSISComWindow (); y = SLIDER_Y + SLIDER_HEIGHT + 1; for (response = pES->top_response; response < pES->num_responses; ++response) { pES->response_list[response].response_text.baseline.x = TEXT_X_OFFS + 8; pES->response_list[response].response_text.baseline.y = y + leading; pES->response_list[response].response_text.align = ALIGN_LEFT; if (response == pES->cur_response) y = add_text (-1, &pES->response_list[response].response_text); else y = add_text (-2, &pES->response_list[response].response_text); } if (pES->top_response) { s.origin.y = SLIDER_Y + SLIDER_HEIGHT + 1; s.frame = SetAbsFrameIndex (ActivityFrame, 6); } else if (y > SIS_SCREEN_HEIGHT) { s.origin.y = SIS_SCREEN_HEIGHT - 2; s.frame = SetAbsFrameIndex (ActivityFrame, 7); } else s.frame = 0; if (s.frame) { RECT r; GetFrameRect (s.frame, &r); s.origin.x = SIS_SCREEN_WIDTH - r.extent.width - 1; DrawStamp (&s); } UnbatchGraphics (); } static void FeedbackPlayerPhrase (UNICODE *pStr) { last_subtitle = NULL; SetContext (SpaceContext); BatchGraphics (); DrawSISComWindow (); if (pStr[0]) { TEXT ct; ct.baseline.x = SIS_SCREEN_WIDTH >> 1; ct.baseline.y = SLIDER_Y + SLIDER_HEIGHT + 13; ct.align = ALIGN_CENTER; ct.CharCount = (COUNT)~0; ct.pStr = GAME_STRING (FEEDBACK_STRING_BASE); // "(In response to your statement)" SetContextForeGroundColor (COMM_RESPONSE_INTRO_TEXT_COLOR); font_DrawText (&ct); ct.baseline.y += 16; SetContextForeGroundColor (COMM_FEEDBACK_TEXT_COLOR); ct.pStr = pStr; add_text (-4, &ct); } UnbatchGraphics (); } void UpdateSpeechGraphics (BOOLEAN Initialize) { CONTEXT OldContext; if (Initialize) { RECT r, sr; FRAME f; InitOscilloscope (0, 0, RADAR_WIDTH, RADAR_HEIGHT, SetAbsFrameIndex (ActivityFrame, 9)); f = SetAbsFrameIndex (ActivityFrame, 2); GetFrameRect (f, &r); SetSliderImage (f); f = SetAbsFrameIndex (ActivityFrame, 5); GetFrameRect (f, &sr); InitSlider (0, SLIDER_Y, SIS_SCREEN_WIDTH, sr.extent.height, r.extent.width, r.extent.height, f); } OldContext = SetContext (RadarContext); Oscilloscope (!Initialize); SetContext (SpaceContext); Slider (); SetContext (OldContext); } static BOOLEAN SpewPhrases (COUNT wait_track) { BOOLEAN ContinuityBreak; DWORD TimeIn; COUNT which_track; FRAME F; BOOLEAN passed = TRUE; TimeIn = GetTimeCounter (); ContinuityBreak = FALSE; F = CommData.AlienFrame; if (wait_track == 0) { wait_track = (COUNT)~0; which_track = (COUNT)~0; goto Rewind; } which_track = PlayingTrack (); if (which_track == 0) { // initial start of player if (wait_track == 1 || wait_track == (COUNT)~0) { ResumeTrack (); UnlockMutex (GraphicsLock); do { TaskSwitch (); LockMutex (GraphicsLock); which_track = PlayingTrack (); UnlockMutex (GraphicsLock); } while (!which_track); LockMutex (GraphicsLock); } } else if (which_track <= wait_track) ResumeTrack (); do { if (GLOBAL (CurrentActivity) & CHECK_ABORT) break; UnlockMutex (GraphicsLock); /* FIXME: is this a remnant of 128-tick clock? * with 120-tick clock this will sleep for 1 tick -- * for 1/120th of a second; if ONE_SECOND is upgraded * it will probably sleep for 2/120th of a second. * Might need to be fixed. */ SleepThreadUntil (TimeIn + (ONE_SECOND / 64)); TimeIn = GetTimeCounter (); #if DEMO_MODE || CREATE_JOURNAL InputState = 0; #else /* !(DEMO_MODE || CREATE_JOURNAL) */ UpdateInputState (); #endif LockMutex (GraphicsLock); if (PulsedInputState.menu[KEY_MENU_CANCEL]) { SetSliderImage (SetAbsFrameIndex (ActivityFrame, 8)); JumpTrack (); CommData.AlienFrame = F; do_subtitles ((void *)~0); return (FALSE); } if (which_track) { BOOLEAN left = FALSE; BOOLEAN right = FALSE; if (optSmoothScroll == OPT_PC) { left = PulsedInputState.menu[KEY_MENU_LEFT]; right = PulsedInputState.menu[KEY_MENU_RIGHT]; } else if (optSmoothScroll == OPT_3DO) { left = ImmediateInputState.menu[KEY_MENU_LEFT]; right = ImmediateInputState.menu[KEY_MENU_RIGHT]; } if (right) { SetSliderImage (SetAbsFrameIndex (ActivityFrame, 3)); if (optSmoothScroll == OPT_PC && !FastForward_Page ()) { SetSliderImage (SetAbsFrameIndex (ActivityFrame, 8)); JumpTrack (); CommData.AlienFrame = F; do_subtitles ((void *)~0); return (FALSE); } else if (optSmoothScroll == OPT_3DO) FastForward_Smooth (); ContinuityBreak = TRUE; CommData.AlienFrame = 0; } else if (left) { Rewind: SetSliderImage (SetAbsFrameIndex (ActivityFrame, 4)); if (optSmoothScroll == OPT_PC) FastReverse_Page (); else if (optSmoothScroll == OPT_3DO) FastReverse_Smooth (); ContinuityBreak = TRUE; CommData.AlienFrame = 0; } else if (ContinuityBreak) { SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2)); which_track = PlayingTrack (); if (which_track && which_track <= wait_track) { if (optSmoothScroll == OPT_3DO) ResumeTrack (); } else { ContinuityBreak = FALSE; passed = (which_track != 0); break; } ContinuityBreak = FALSE; } else if (which_track == wait_track || wait_track == (COUNT)~0) CommData.AlienFrame = F; } } while (ContinuityBreak || ((which_track = PlayingTrack ()) && which_track <= wait_track)); CommData.AlienFrame = F; do_subtitles ((void *)~0); if (!which_track || wait_track == (COUNT)~0) { // reached the end SetSliderImage (SetAbsFrameIndex (ActivityFrame, 8)); return (FALSE); } return (passed); } static BOOLEAN DoTalkSegue (COUNT wait_track) { BOOLEAN done; // Transition animation to talking state, if necessary if (CommData.AlienTalkDesc.NumFrames) { if (!(CommData.AlienTransitionDesc.AnimFlags & TALK_INTRO)) { CommData.AlienTransitionDesc.AnimFlags |= TALK_INTRO; if (CommData.AlienTransitionDesc.NumFrames) CommData.AlienTalkDesc.AnimFlags |= TALK_INTRO; } CommData.AlienTransitionDesc.AnimFlags &= ~PAUSE_TALKING; if (CommData.AlienTalkDesc.NumFrames) CommData.AlienTalkDesc.AnimFlags |= WAIT_TALKING; while (CommData.AlienTalkDesc.AnimFlags & TALK_INTRO) { // wait until the transition finishes UnlockMutex (GraphicsLock); TaskSwitch (); LockMutex (GraphicsLock); } } done = !SpewPhrases (wait_track); // transition back to silent, if necessary if (CommData.AlienTalkDesc.NumFrames) { // must set the TALK_DONE flag so that the animation task // releases WAIT_TALKING from AlienTalkDesc CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE; if ((CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING)) CommData.AlienTalkDesc.AnimFlags |= PAUSE_TALKING; } return done; } static void FlushTalkSegue (void) { FlushInput (); while (AnyButtonPress (TRUE)) TaskSwitch (); do TaskSwitch (); while (CommData.AlienTalkDesc.AnimFlags & PAUSE_TALKING); } void AlienTalkSegue (COUNT wait_track) { BOOLEAN done; // this skips any talk segues that follow an aborted one if ((GLOBAL (CurrentActivity) & CHECK_ABORT) || (CommData.AlienTransitionDesc.AnimFlags & TALK_DONE)) return; LockMutex (GraphicsLock); if (!pCurInputState->Initialized) { SetColorMap (GetColorMapAddress (CommData.AlienColorMap)); DrawAlienFrame (CommData.AlienFrame, NULL_PTR); UpdateSpeechGraphics (TRUE); if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE || (!GET_GAME_STATE (PLAYER_HYPNOTIZED) && !GET_GAME_STATE (CHMMR_EMERGING) && GET_GAME_STATE (CHMMR_BOMB_STATE) != 2 && (pMenuState == 0 || !GET_GAME_STATE (MOONBASE_ON_SHIP) || GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER)))) { RECT r; if (pMenuState == 0 && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) { r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT; ScreenTransition (3, &r); } else { ScreenTransition (3, &CommWndRect); } UnbatchGraphics (); } else { BYTE clut_buf[] = {FadeAllToColor}; UnbatchGraphics (); if (GET_GAME_STATE (MOONBASE_ON_SHIP) || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND * 2); else if (GET_GAME_STATE (CHMMR_EMERGING)) XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND * 2); else XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND * 5); } pCurInputState->Initialized = TRUE; PlayMusic ((MUSIC_REF)CommData.AlienSong, TRUE, 1); SetMusicVolume (BACKGROUND_VOL); { DWORD TimeOut; TimeOut = GetTimeCounter () + (ONE_SECOND >> 1); /* if (CommData.NumAnimations) */ pCurInputState->AnimTask = StartCommAnimTask (); UnlockMutex (GraphicsLock); SleepThreadUntil (TimeOut); LockMutex (GraphicsLock); } LastActivity &= ~CHECK_LOAD; } done = DoTalkSegue (wait_track); if (done || wait_track == (COUNT)~0) FadeMusic (FOREGROUND_VOL, ONE_SECOND); UnlockMutex (GraphicsLock); FlushTalkSegue (); if (done || wait_track == (COUNT)~0) { // all done talking here CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE; } else { // there is more to come CommData.AlienTransitionDesc.AnimFlags &= ~TALK_DONE; // allow a transition to talking state again later CommData.AlienTransitionDesc.AnimFlags &= ~TALK_INTRO; } } typedef struct summary_state { // standard state required by DoInput BOOLEAN (*InputFunc) (struct summary_state *pSS); COUNT MenuRepeatDelay; // extended state BOOLEAN Initialized; BOOLEAN PrintNext; const TFB_SoundChain *NextSub; const UNICODE *LeftOver; } SUMMARY_STATE; typedef SUMMARY_STATE *PSUMMARY_STATE; static BOOLEAN DoConvSummary (PSUMMARY_STATE pSS) { #define DELTA_Y_SUMMARY 8 #define MAX_SUMM_ROWS ((SIS_SCREEN_HEIGHT - SLIDER_Y - SLIDER_HEIGHT) \ / DELTA_Y_SUMMARY) - 1 if (!pSS->Initialized) { pSS->PrintNext = TRUE; pSS->NextSub = first_chain; pSS->LeftOver = NULL; pSS->MenuRepeatDelay = 0; pSS->InputFunc = DoConvSummary; pSS->Initialized = TRUE; DoInput (pSS, FALSE); } else if (GLOBAL (CurrentActivity) & CHECK_ABORT) { return FALSE; // bail out } else if (PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_CANCEL] || PulsedInputState.menu[KEY_MENU_RIGHT]) { if (pSS->NextSub) { // we want the next page pSS->PrintNext = TRUE; } else { // no more, we are done return FALSE; } } else if (pSS->PrintNext) { // print the next page RECT r; TEXT t; int row; FONT oldFont; r.corner.x = 0; r.corner.y = 0; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT - SLIDER_Y - SLIDER_HEIGHT + 2; LockMutex (GraphicsLock); SetContextForeGroundColor (COMM_HISTORY_BACKGROUND_COLOR); DrawFilledRectangle (&r); SetContextForeGroundColor (COMM_HISTORY_TEXT_COLOR); r.extent.width -= 2 + 2; t.baseline.x = 2; t.align = ALIGN_LEFT; t.baseline.y = DELTA_Y_SUMMARY; oldFont = SetContextFont (TinyFont); for (row = 0; row < MAX_SUMM_ROWS && pSS->NextSub; ++row, pSS->NextSub = pSS->NextSub->next) { const unsigned char *next; if (pSS->LeftOver) { // some text left from last subtitle t.pStr = pSS->LeftOver; pSS->LeftOver = NULL; } else { t.pStr = pSS->NextSub->text; if (!t.pStr) continue; } t.CharCount = (COUNT)~0; for ( ; row < MAX_SUMM_ROWS && !getLineWithinWidth (&t, &next, r.extent.width, (COUNT)~0); ++row) { font_DrawText (&t); t.baseline.y += DELTA_Y_SUMMARY; t.pStr = next; t.CharCount = (COUNT)~0; } if (row >= MAX_SUMM_ROWS) { // no more space on screen, but some text left over // from the current subtitle pSS->LeftOver = next; break; } // this subtitle fit completely font_DrawText (&t); t.baseline.y += DELTA_Y_SUMMARY; } if (row >= MAX_SUMM_ROWS && (pSS->NextSub || pSS->LeftOver)) { // draw *MORE* TEXT mt; UNICODE buffer[80]; mt.baseline.x = SIS_SCREEN_WIDTH >> 1; mt.baseline.y = t.baseline.y; mt.align = ALIGN_CENTER; snprintf (buffer, sizeof (buffer), "%s%s%s", // "MORE" STR_MIDDLE_DOT, GAME_STRING (FEEDBACK_STRING_BASE + 1), STR_MIDDLE_DOT); mt.pStr = buffer; SetContextForeGroundColor (COMM_MORE_TEXT_COLOR); font_DrawText (&mt); } SetContextFont (oldFont); UnlockMutex (GraphicsLock); pSS->PrintNext = FALSE; } else { SleepThread (ONE_SECOND / 20); } return TRUE; // keep going } // Called when the player presses the select button on a response. static void SelectResponse (PENCOUNTER_STATE pES) { const unsigned char *end; PTEXT response_text = &pES->response_list[pES->cur_response].response_text; end = skipUTF8Chars(response_text->pStr, response_text->CharCount); pES->phrase_buf_index = end - response_text->pStr; memcpy(pES->phrase_buf, response_text->pStr, pES->phrase_buf_index); pES->phrase_buf[pES->phrase_buf_index++] = '\0'; LockMutex (GraphicsLock); FeedbackPlayerPhrase (pES->phrase_buf); StopTrack (); SetSliderImage (SetAbsFrameIndex (ActivityFrame, 2)); UnlockMutex (GraphicsLock); FadeMusic (BACKGROUND_VOL, ONE_SECOND); CommData.AlienTransitionDesc.AnimFlags &= ~(TALK_INTRO | TALK_DONE); pES->num_responses = 0; (*pES->response_list[pES->cur_response].response_func) (pES->response_list[pES->cur_response].response_ref); } // Called when the player presses the cancel button in comm. static void SelectConversationSummary (PENCOUNTER_STATE pES) { SUMMARY_STATE SummaryState; LockMutex (GraphicsLock); FeedbackPlayerPhrase (pES->phrase_buf); PauseAnimTask = TRUE; UnlockMutex (GraphicsLock); // wait for ambient anim task to pause SleepThread (ONE_SECOND / 30); SummaryState.Initialized = FALSE; DoConvSummary (&SummaryState); LockMutex (GraphicsLock); RefreshResponses (pES); ClearSummary = TRUE; PauseAnimTask = FALSE; UnlockMutex (GraphicsLock); } static void PlayerResponseInput (PENCOUNTER_STATE pES) { BYTE response; if (pES->top_response == (BYTE)~0) { pES->top_response = 0; LockMutex (GraphicsLock); RefreshResponses (pES); UnlockMutex (GraphicsLock); } if (PulsedInputState.menu[KEY_MENU_SELECT]) { SelectResponse (pES); } else if (PulsedInputState.menu[KEY_MENU_CANCEL] && LOBYTE (GLOBAL (CurrentActivity)) != WON_LAST_BATTLE) { SelectConversationSummary (pES); } else { response = pES->cur_response; if (PulsedInputState.menu[KEY_MENU_LEFT]) { FadeMusic (BACKGROUND_VOL, ONE_SECOND); LockMutex (GraphicsLock); FeedbackPlayerPhrase (pES->phrase_buf); // reset transition state CommData.AlienTransitionDesc.AnimFlags &= ~(TALK_INTRO | TALK_DONE); DoTalkSegue (0); if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) { RefreshResponses (pES); FadeMusic (FOREGROUND_VOL, ONE_SECOND); } UnlockMutex (GraphicsLock); FlushTalkSegue (); // done one way or the other CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE; } else if (PulsedInputState.menu[KEY_MENU_UP]) response = (BYTE)((response + (BYTE)(pES->num_responses - 1)) % pES->num_responses); else if (PulsedInputState.menu[KEY_MENU_DOWN]) response = (BYTE)((BYTE)(response + 1) % pES->num_responses); if (response != pES->cur_response) { COORD y; LockMutex (GraphicsLock); BatchGraphics (); add_text (-2, &pES->response_list[pES->cur_response].response_text); pES->cur_response = response; y = add_text (-1, &pES->response_list[pES->cur_response].response_text); if (response < pES->top_response) { pES->top_response = 0; RefreshResponses (pES); } else if (y > SIS_SCREEN_HEIGHT) { pES->top_response = response; RefreshResponses (pES); } UnbatchGraphics (); UnlockMutex (GraphicsLock); } } } static BOOLEAN DoCommunication (PENCOUNTER_STATE pES) { SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT); if (!(CommData.AlienTransitionDesc.AnimFlags & TALK_DONE)) AlienTalkSegue ((COUNT)~0); if (GLOBAL (CurrentActivity) & CHECK_ABORT) ; else if (pES->num_responses == 0) { // The player doesn't get a chance to say anything. DWORD TimeIn, TimeOut; TimeOut = FadeMusic (0, ONE_SECOND * 3) + ONE_SECOND / 60; TimeIn = GetTimeCounter (); do { SleepThreadUntil (TimeIn + ONE_SECOND / 120); TimeIn = GetTimeCounter (); // Warning! This used to re-gather input data to check for rewind. UpdateInputState (); if (PulsedInputState.menu[KEY_MENU_LEFT]) { FadeMusic (BACKGROUND_VOL, ONE_SECOND); LockMutex (GraphicsLock); // reset transition state CommData.AlienTransitionDesc.AnimFlags &= ~(TALK_INTRO | TALK_DONE); DoTalkSegue (0); UnlockMutex (GraphicsLock); FlushTalkSegue (); // done one way or the other CommData.AlienTransitionDesc.AnimFlags |= TALK_DONE; if (GLOBAL (CurrentActivity) & CHECK_ABORT) break; TimeOut = FadeMusic (0, ONE_SECOND * 2) + ONE_SECOND / 60; TimeIn = GetTimeCounter (); } } while (TimeIn <= TimeOut); } else { PlayerResponseInput (pES); return (TRUE); } LockMutex (GraphicsLock); if (pES->AnimTask) { UnlockMutex (GraphicsLock); ConcludeTask (pES->AnimTask); LockMutex (GraphicsLock); pES->AnimTask = 0; } CommData.AlienTransitionDesc.AnimFlags &= ~(TALK_INTRO | TALK_DONE); SetContext (SpaceContext); DestroyContext (ReleaseContext (TaskContext)); TaskContext = 0; UnlockMutex (GraphicsLock); FlushColorXForms (); ClearSubtitle = FALSE; StopMusic (); StopSound (); StopTrack (); SleepThreadUntil (FadeMusic (NORMAL_VOLUME, 0) + ONE_SECOND / 60); return (FALSE); } void DoResponsePhrase (RESPONSE_REF R, RESPONSE_FUNC response_func, UNICODE *ConstructStr) { PENCOUNTER_STATE pES = pCurInputState; PRESPONSE_ENTRY pEntry; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return; if (pES->num_responses == 0) { pES->cur_response = 0; pES->top_response = (BYTE)~0; } pEntry = &pES->response_list[pES->num_responses]; pEntry->response_ref = R; pEntry->response_text.pStr = ConstructStr; if (pEntry->response_text.pStr) pEntry->response_text.CharCount = (COUNT)~0; else { STRING locString; locString = SetAbsStringTableIndex (CommData.ConversationPhrases, (COUNT) (R - 1)); pEntry->response_text.pStr = (UNICODE *) GetStringAddress (locString); pEntry->response_text.CharCount = GetStringLength (locString); //#define BVT_PROBLEM #ifdef BVT_PROBLEM if (pEntry->response_text.pStr[pEntry->response_text.CharCount - 1] == '\0') --pEntry->response_text.CharCount; #endif /* BVT_PROBLEM */ } pEntry->response_func = response_func; ++pES->num_responses; } static void HailAlien (void) { MEM_HANDLE hOldIndex; ENCOUNTER_STATE ES; FONT PlayerFont, OldFont; MUSIC_REF SongRef = 0; COLOR TextBack; pCurInputState = &ES; memset (pCurInputState, 0, sizeof (*pCurInputState)); ES.InputFunc = DoCommunication; hOldIndex = SetResourceIndex (hResIndex); PlayerFont = CaptureFont ((FONT_REF)LoadFont (PLAYER_FONT)); SetResourceIndex (hOldIndex); CommData.AlienFrame = CaptureDrawable ( LoadGraphic ((RESOURCE)CommData.AlienFrame)); CommData.AlienFont = CaptureFont ((FONT_REF) LoadFont ((RESOURCE)CommData.AlienFont)); CommData.AlienColorMap = CaptureColorMap ( LoadColorMap ((RESOURCE)CommData.AlienColorMap)); if ((CommData.AlienSongFlags & LDASF_USE_ALTERNATE) && CommData.AlienAltSong) SongRef = LoadMusic ((RESOURCE)CommData.AlienAltSong); if (SongRef) CommData.AlienSong = SongRef; else CommData.AlienSong = LoadMusic ((RESOURCE)CommData.AlienSong); CommData.ConversationPhrases = CaptureStringTable ( LoadStringTable ((RESOURCE)CommData.ConversationPhrases)); SubtitleText.baseline = CommData.AlienTextBaseline; SubtitleText.align = CommData.AlienTextAlign; // init subtitle cache context TextCacheContext = CaptureContext (CreateContext ()); TextCacheFrame = CaptureDrawable ( CreateDrawable (WANT_PIXMAP, SIS_SCREEN_WIDTH, SIS_SCREEN_HEIGHT - SLIDER_Y - SLIDER_HEIGHT + 2, 1)); SetContext (TextCacheContext); SetContextFGFrame (TextCacheFrame); TextBack = BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x10), 0x00); // Color key for the background. SetContextBackGroundColor (TextBack); ClearDrawable (); SetFrameTransparentColor (TextCacheFrame, TextBack); ES.phrase_buf_index = 1; ES.phrase_buf[0] = '\0'; SetContext (SpaceContext); OldFont = SetContextFont (PlayerFont); { RECT r; TaskContext = CaptureContext (CreateContext ()); SetContext (TaskContext); SetContextFGFrame (Screen); GetFrameRect (CommData.AlienFrame, &r); r.extent.width = SIS_SCREEN_WIDTH; CommWndRect.extent = r.extent; SetTransitionSource (NULL); BatchGraphics (); if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { r.corner = CommWndRect.corner; SetContextClipRect (&r); } else { r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; SetContextClipRect (&r); CommWndRect.corner = r.corner; if (pMenuState == 0) { RepairSISBorder (); UnlockMutex (GraphicsLock); DrawMenuStateStrings ((BYTE)~0, 1); LockMutex (GraphicsLock); } else /* in starbase */ { DrawSISFrame (); if (GET_GAME_STATE (STARBASE_AVAILABLE)) { DrawSISMessage (GAME_STRING (STARBASE_STRING_BASE + 1)); // "Starbase Commander" DrawSISTitle (GAME_STRING (STARBASE_STRING_BASE + 0)); // "Starbase" } else { DrawSISMessage (NULL_PTR); DrawSISTitle (GLOBAL_SIS (PlanetName)); } } } DrawSISComWindow (); } UnlockMutex (GraphicsLock); LastActivity |= CHECK_LOAD; /* prevent spurious input */ (*CommData.init_encounter_func) (); DoInput ((PVOID)&ES, FALSE); if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) (*CommData.post_encounter_func) (); (*CommData.uninit_encounter_func) (); LockMutex (GraphicsLock); DestroyStringTable (ReleaseStringTable (CommData.ConversationPhrases)); DestroyMusic ((MUSIC_REF)CommData.AlienSong); DestroyColorMap (ReleaseColorMap (CommData.AlienColorMap)); DestroyFont (ReleaseFont (CommData.AlienFont)); DestroyDrawable (ReleaseDrawable (CommData.AlienFrame)); DestroyContext (ReleaseContext (TextCacheContext)); DestroyDrawable (ReleaseDrawable (TextCacheFrame)); SetContext (SpaceContext); SetContextFont (OldFont); DestroyFont (ReleaseFont (PlayerFont)); CommData.ConversationPhrases = 0; pCurInputState = 0; } COUNT InitCommunication (RESOURCE which_comm) { COUNT status; MEM_HANDLE hOldIndex, hIndex; LOCDATAPTR LocDataPtr; #ifdef DEBUG if (disableInteractivity) return 0; #endif last_subtitle = NULL; LockMutex (GraphicsLock); if (LastActivity & CHECK_LOAD) { LastActivity &= ~CHECK_LOAD; if (which_comm != COMMANDER_CONVERSATION) { if (LOBYTE (LastActivity) == 0) { DrawSISFrame (); } else { ClearSISRect (DRAW_SIS_DISPLAY); RepairSISBorder (); } DrawSISMessage (NULL_PTR); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) DrawHyperCoords (GLOBAL (ShipStamp.origin)); else if (HIWORD (GLOBAL (ShipStamp.frame)) == 0) DrawHyperCoords (CurStarDescPtr->star_pt); else DrawSISTitle (GLOBAL_SIS (PlanetName)); } } if (which_comm == 0) { status = URQUAN_PROBE_SHIP; which_comm = URQUAN_CONVERSATION; } else { if (which_comm == (RESOURCE) YEHAT_REBEL_CONVERSATION) { status = YEHAT_REBEL_SHIP; which_comm = YEHAT_CONVERSATION; } else { status = GET_PACKAGE (which_comm) - GET_PACKAGE (ARILOU_CONVERSATION) + ARILOU_SHIP; if (status >= YEHAT_REBEL_SHIP) { /* conversation exception, set to self */ status = HUMAN_SHIP; } } ActivateStarShip (status, SPHERE_TRACKING); if (which_comm == ORZ_CONVERSATION || (which_comm == TALKING_PET_CONVERSATION && (!GET_GAME_STATE (TALKING_PET_ON_SHIP) || LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE)) || (which_comm != CHMMR_CONVERSATION && which_comm != SYREEN_CONVERSATION ))//&& (ActivateStarShip (status, CHECK_ALLIANCE) & BAD_GUY))) BuildBattle (1); } hOldIndex = SetResourceIndex (hResIndex); hIndex = OpenResourceIndexInstance (which_comm); if (hIndex == 0) { SET_GAME_STATE (BATTLE_SEGUE, 1); LocDataPtr = 0; } else { SetResourceIndex (hIndex); LocDataPtr = (LOCDATAPTR)init_race ( status != YEHAT_REBEL_SHIP ? which_comm : (RESOURCE)YEHAT_REBEL_CONVERSATION); if (LocDataPtr) CommData = *LocDataPtr; } UnlockMutex (GraphicsLock); if (GET_GAME_STATE (BATTLE_SEGUE) == 0) { // Not offered the chance to attack. status = HAIL; } else if ((status = InitEncounter ()) == HAIL && LocDataPtr) { // The player chose to talk. SET_GAME_STATE (BATTLE_SEGUE, 0); } else { // The player chose to attack. status = ATTACK; SET_GAME_STATE (BATTLE_SEGUE, 1); } LockMutex (GraphicsLock); if (status == HAIL) { cur_comm = which_comm; HailAlien (); cur_comm = 0; } else if (LocDataPtr) { // only when comm initied successfully if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) (*CommData.post_encounter_func) (); // process states (*CommData.uninit_encounter_func) (); // cleanup } SetResourceIndex (hOldIndex); CloseResourceIndex (hIndex); UnlockMutex (GraphicsLock); status = 0; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE && (GLOBAL (glob_flags) & CYBORG_ENABLED)) ReinitQueue (&GLOBAL (npc_built_ship_q)); SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 0); status = (GET_GAME_STATE (BATTLE_SEGUE) && GetHeadLink (&GLOBAL (npc_built_ship_q))); if (status) { // Start combat BuildBattle (0); EncounterBattle (); } else { SET_GAME_STATE (BATTLE_SEGUE, 0); } } UninitEncounter (); return (status); } void RaceCommunication (void) { COUNT i, status; HSTARSHIP hStarShip; SHIP_FRAGMENTPTR FragPtr; RESOURCE RaceComm[] = { RACE_COMMUNICATION }; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) { /* Going into talking pet conversation */ ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (SAMATRA_SHIP, &GLOBAL (npc_built_ship_q), 0); InitCommunication (TALKING_PET_CONVERSATION); if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) { GLOBAL (CurrentActivity) = WON_LAST_BATTLE; } return; } else if (NextActivity & CHECK_LOAD) { BYTE ec; ec = GET_GAME_STATE (ESCAPE_COUNTER); if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) InitCommunication (SPATHI_CONVERSATION); else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) == 0) InitCommunication (TALKING_PET_CONVERSATION); else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & ((1 << 4) | (1 << 5))) // Communicate with the Ilwrath using a Hyperwave Broadcaster. InitCommunication (ILWRATH_CONVERSATION); else InitCommunication (CHMMR_CONVERSATION); if (GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) { NextActivity = GLOBAL (CurrentActivity) & ~START_ENCOUNTER; if (LOBYTE (NextActivity) == IN_INTERPLANETARY) NextActivity |= START_INTERPLANETARY; GLOBAL (CurrentActivity) |= CHECK_LOAD; /* fake a load game */ } SET_GAME_STATE (ESCAPE_COUNTER, ec); return; } else if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { ReinitQueue (&GLOBAL (npc_built_ship_q)); if (GET_GAME_STATE (ARILOU_SPACE_SIDE) >= 2) { InitCommunication (ARILOU_CONVERSATION); return; } else { COUNT NumShips; HENCOUNTER hEncounter; ENCOUNTERPTR EncounterPtr; hEncounter = GetHeadEncounter (); LockEncounter (hEncounter, &EncounterPtr); NumShips = LONIBBLE (EncounterPtr->SD.Index); for (i = 0; i < NumShips; ++i) { CloneShipFragment (EncounterPtr->SD.Type, &GLOBAL (npc_built_ship_q), 0); } CurStarDescPtr = (STAR_DESCPTR)&EncounterPtr->SD; UnlockEncounter (hEncounter); } } hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); i = GET_RACE_ID (FragPtr); UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); status = InitCommunication (RaceComm[i]); if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) return; if (i == CHMMR_SHIP) ReinitQueue (&GLOBAL (npc_built_ship_q)); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY) { /* if used destruct code in interplanetary */ if (i == SLYLANDRO_SHIP && status == 0) ReinitQueue (&GLOBAL (npc_built_ship_q)); } else { PEXTENDED_STAR_DESC pESD; pESD = (PEXTENDED_STAR_DESC)CurStarDescPtr; if (pESD) { BYTE i, NumShips; NumShips = (BYTE)CountLinks (&GLOBAL (npc_built_ship_q)); pESD->Index = MAKE_BYTE (NumShips, HINIBBLE (pESD->Index)); pESD->Index |= ENCOUNTER_REFORMING; if (status == 0) pESD->Index |= ONE_SHOT_ENCOUNTER; for (i = 0; i < NumShips; ++i) { HSTARSHIP hStarShip; SHIP_FRAGMENTPTR TemplatePtr; hStarShip = GetStarShipFromIndex ( &GLOBAL (npc_built_ship_q), i); TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); pESD->ShipList[i] = TemplatePtr->ShipInfo; pESD->ShipList[i].var1 = GET_RACE_ID (TemplatePtr); UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } ReinitQueue (&GLOBAL (npc_built_ship_q)); CurStarDescPtr = 0; } } } SUBTITLE_STATE do_subtitles (UNICODE *pStr) { static UNICODE *last_page = NULL; LockMutex (subtitle_mutex); if (pStr == 0) { subtitle_state = DONE_SUBTITLE; UnlockMutex (subtitle_mutex); return (subtitle_state); } else if (pStr == (void *)~0) { subtitle_state = WAIT_SUBTITLE; } else { if (last_page == pStr) { UnlockMutex (subtitle_mutex); return (subtitle_state); } subtitle_state = READ_SUBTITLE; ClearSubtitle = TRUE; } last_page = pStr; switch (subtitle_state) { case READ_SUBTITLE: { /* Baseline may be updated by the ZFP */ SubtitleText.baseline = CommData.AlienTextBaseline; SubtitleText.align = CommData.AlienTextAlign; SubtitleText.pStr = pStr; SubtitleText.CharCount = (COUNT)~0; subtitle_state = WAIT_SUBTITLE; break; } case WAIT_SUBTITLE: { subtitle_state = DONE_SUBTITLE; ClearSubtitle = TRUE; } case DONE_SUBTITLE: break; default: // Should not happen assert(false); break; } UnlockMutex (subtitle_mutex); return (subtitle_state); } void RedrawSubtitles (void) { TEXT t; if (!optSubtitles) return; t = SubtitleText; add_text (1, &t); } // Sets ClearSubtitle, returning the old value. The current subtitle state // is also returned, through sub_state BOOLEAN SetClearSubtitle (BOOLEAN flag, SUBTITLE_STATE *sub_state) { BOOLEAN oldClearSubtitle; LockMutex (subtitle_mutex); oldClearSubtitle = ClearSubtitle; *sub_state = subtitle_state; ClearSubtitle = flag; UnlockMutex (subtitle_mutex); return oldClearSubtitle; } uqm-0.6.2/sc2/src/sc2code/settings.h0000600000175000017500000000224310543202103015607 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SETTINGS_H #define _SETTINGS_H #include "libs/sndlib.h" extern void ToggleMusic (void); extern void StopMusic (void); extern void ResumeMusic (void); extern void PauseMusic (void); extern void ToggleSoundEffect (void); extern void PlayMusic (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority); extern void PlaySoundEffect (SOUND S, COUNT Channel, SoundPosition Pos, void *PositionalObject, BYTE Priority); #endif /* _SETTINGS_H */ uqm-0.6.2/sc2/src/sc2code/save.h0000600000175000017500000000165210543202103014710 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SAVE_H #define _SAVE_H #include "sis.h" #include "libs/compiler.h" extern void SaveProblem (void); extern BOOLEAN SaveGame (COUNT which_game, SUMMARY_DESC *summary_desc); #endif /* _SAVE_H */ uqm-0.6.2/sc2/src/sc2code/master.h0000600000175000017500000000171310543202101015241 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _MASTER_H #define _MASTER_H #include "races.h" #include "libs/compiler.h" extern void LoadMasterShipList (void); extern void FreeMasterShipList (void); extern HSTARSHIP FindMasterShip (DWORD ship_ref); #endif /* _MASTER_H */ uqm-0.6.2/sc2/src/sc2code/save.c0000600000175000017500000004760110543202103014707 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "save.h" #include "build.h" #include "declib.h" #include "controls.h" #include "encount.h" #include "file.h" #include "gamestr.h" #include "globdata.h" #include "options.h" #include "races.h" #include "shipcont.h" #include "setup.h" #include "state.h" #include "util.h" #include "libs/inplib.h" #include "libs/log.h" // XXX: these should handle endian conversions later static inline COUNT cwrite_8 (DECODE_REF fh, BYTE v) { return cwrite (&v, 1, 1, fh); } static inline COUNT cwrite_16 (DECODE_REF fh, UWORD v) { return cwrite (&v, 2, 1, fh); } static inline COUNT cwrite_32 (DECODE_REF fh, DWORD v) { return cwrite (&v, 4, 1, fh); } static inline COUNT cwrite_ptr (DECODE_REF fh) { return cwrite_32 (fh, 0); /* ptrs are useless in saves */ } static inline COUNT cwrite_a8 (DECODE_REF fh, PBYTE ar, COUNT count) { return cwrite (ar, 1, count, fh) == count; } static inline COUNT write_8 (PVOID fp, BYTE v) { return WriteResFile (&v, 1, 1, fp); } static inline COUNT write_16 (PVOID fp, UWORD v) { return WriteResFile (&v, 2, 1, fp); } static inline COUNT write_32 (PVOID fp, DWORD v) { return WriteResFile (&v, 4, 1, fp); } static inline COUNT write_ptr (PVOID fp) { return write_32 (fp, 0); /* ptrs are useless in saves */ } static inline COUNT write_a8 (PVOID fp, PBYTE ar, COUNT count) { return WriteResFile (ar, 1, count, fp) == count; } static inline COUNT write_a16 (PVOID fp, PUWORD ar, COUNT count) { for ( ; count > 0; --count, ++ar) { if (write_16 (fp, *ar) != 1) return 0; } return 1; } static void SaveShipQueue (DECODE_REF fh, PQUEUE pQueue) { COUNT num_links; HSTARSHIP hStarShip; // Write the number of entries in the queue. num_links = CountLinks (pQueue); cwrite_16 (fh, num_links); hStarShip = GetHeadLink (pQueue); while (num_links--) { HSTARSHIP hNextShip; SHIP_FRAGMENTPTR FragPtr; COUNT Index; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); hNextShip = _GetSuccLink (FragPtr); if (pQueue == &GLOBAL (avail_race_q)) Index = GetIndexFromStarShip (pQueue, hStarShip); // The index is the position in the queue. else Index = GET_RACE_ID (FragPtr); // Write the number identifying this ship type. // See races.h; look for the enum containing NUM_AVAILABLE_RACES. cwrite_16 (fh, Index); if (pQueue != &GLOBAL (avail_race_q)) { // queues other than avail_race_q save SHIP_FRAGMENT elements // Write SHIP_FRAGMENT elements cwrite_16 (fh, FragPtr->s.Player); cwrite_8 (fh, FragPtr->s.Captain); cwrite_8 (fh, 0); /* padding */ } // Write SHIP_INFO elements cwrite_16 (fh, FragPtr->ShipInfo.ship_flags); cwrite_8 (fh, FragPtr->ShipInfo.var1); cwrite_8 (fh, FragPtr->ShipInfo.var2); cwrite_8 (fh, FragPtr->ShipInfo.crew_level); cwrite_8 (fh, FragPtr->ShipInfo.max_crew); cwrite_8 (fh, FragPtr->ShipInfo.energy_level); cwrite_8 (fh, FragPtr->ShipInfo.max_energy); cwrite_16 (fh, FragPtr->ShipInfo.loc.x); cwrite_16 (fh, FragPtr->ShipInfo.loc.y); if (pQueue == &GLOBAL (avail_race_q)) { // avail_race_q contains information not about specific ships, // but about a race. EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr = (EXTENDED_SHIP_FRAGMENTPTR) FragPtr; cwrite_16 (fh, ExtFragPtr->ShipInfo.actual_strength); cwrite_16 (fh, ExtFragPtr->ShipInfo.known_strength); cwrite_16 (fh, ExtFragPtr->ShipInfo.known_loc.x); cwrite_16 (fh, ExtFragPtr->ShipInfo.known_loc.y); cwrite_8 (fh, ExtFragPtr->ShipInfo.growth_err_term); cwrite_8 (fh, ExtFragPtr->ShipInfo.func_index); cwrite_16 (fh, ExtFragPtr->ShipInfo.dest_loc.x); cwrite_16 (fh, ExtFragPtr->ShipInfo.dest_loc.y); cwrite_16 (fh, 0); /* alignment padding */ } UnlockStarShip (pQueue, hStarShip); hStarShip = hNextShip; } } static void SaveEncounter (ENCOUNTERPTR EncounterPtr, DECODE_REF fh) { COUNT i; cwrite_ptr (fh); /* useless ptr; HENCOUNTER pred */ cwrite_ptr (fh); /* useless ptr; HENCOUNTER succ */ cwrite_ptr (fh); /* useless ptr; HELEMENT hElement */ cwrite_16 (fh, EncounterPtr->transition_state); cwrite_16 (fh, EncounterPtr->origin.x); cwrite_16 (fh, EncounterPtr->origin.y); cwrite_16 (fh, EncounterPtr->radius); // EXTENDED_STAR_DESC fields cwrite_16 (fh, EncounterPtr->SD.star_pt.x); cwrite_16 (fh, EncounterPtr->SD.star_pt.y); cwrite_8 (fh, EncounterPtr->SD.Type); cwrite_8 (fh, EncounterPtr->SD.Index); cwrite_16 (fh, 0); /* alignment padding */ // Save each entry in the SHIP_INFO array: for (i = 0; i < MAX_HYPER_SHIPS; i++) { SHIP_INFOPTR ShipInfo = &EncounterPtr->SD.ShipList[i]; cwrite_16 (fh, ShipInfo->ship_flags); cwrite_8 (fh, ShipInfo->var1); cwrite_8 (fh, ShipInfo->var2); cwrite_8 (fh, ShipInfo->crew_level); cwrite_8 (fh, ShipInfo->max_crew); cwrite_8 (fh, ShipInfo->energy_level); cwrite_8 (fh, ShipInfo->max_energy); cwrite_16 (fh, ShipInfo->loc.x); cwrite_16 (fh, ShipInfo->loc.y); cwrite_32 (fh, 0); /* useless val; STRING race_strings */ cwrite_ptr (fh); /* useless ptr; FRAME icons */ cwrite_ptr (fh); /* useless ptr; FRAME melee_icon */ } // Save the stuff after the SHIP_INFO array: cwrite_32 (fh, EncounterPtr->log_x); cwrite_32 (fh, EncounterPtr->log_y); } static void SaveEvent (EVENTPTR EventPtr, DECODE_REF fh) { cwrite_ptr (fh); /* useless ptr; HEVENT pred */ cwrite_ptr (fh); /* useless ptr; HEVENT succ */ cwrite_8 (fh, EventPtr->day_index); cwrite_8 (fh, EventPtr->month_index); cwrite_16 (fh, EventPtr->year_index); cwrite_8 (fh, EventPtr->func_index); cwrite_8 (fh, 0); /* padding */ cwrite_16 (fh, 0); /* padding */ } static void DummySaveQueue (PQUEUE QueuePtr, DECODE_REF fh) { /* QUEUE should never actually be saved since it contains * purely internal representation and the lists * involved are actually saved separately */ (void)QueuePtr; /* silence compiler */ /* QUEUE format with QUEUE_TABLE defined -- UQM default */ cwrite_ptr (fh); /* HLINK head */ cwrite_ptr (fh); /* HLINK tail */ cwrite_ptr (fh); /* PBYTE pq_tab */ cwrite_ptr (fh); /* HLINK free_list */ cwrite_16 (fh, 0); /* MEM_HANDLE hq_tab */ cwrite_16 (fh, 0); /* COUNT object_size */ cwrite_8 (fh, 0); /* BYTE num_objects */ cwrite_8 (fh, 0); /* padding */ cwrite_16 (fh, 0); /* padding */ } static void SaveClockState (PCLOCK_STATE ClockPtr, DECODE_REF fh) { cwrite_8 (fh, ClockPtr->day_index); cwrite_8 (fh, ClockPtr->month_index); cwrite_16 (fh, ClockPtr->year_index); cwrite_16 (fh, ClockPtr->tick_count); cwrite_16 (fh, ClockPtr->day_in_ticks); cwrite_ptr (fh); /* useless ptr; Semaphore clock_sem */ cwrite_ptr (fh); /* useless ptr; Task clock_task */ cwrite_32 (fh, ClockPtr->TimeCounter); /* theoretically useless */ DummySaveQueue (&ClockPtr->event_q, fh); } static void SaveGameState (PGAME_STATE GSPtr, DECODE_REF fh) { cwrite_8 (fh, 0); /* obsolete; BYTE cur_state */ cwrite_8 (fh, GSPtr->glob_flags); cwrite_8 (fh, GSPtr->CrewCost); cwrite_8 (fh, GSPtr->FuelCost); cwrite_a8 (fh, GSPtr->ModuleCost, NUM_MODULES); cwrite_a8 (fh, GSPtr->ElementWorth, NUM_ELEMENT_CATEGORIES); cwrite_ptr (fh); /* useless ptr; PPRIMITIVE DisplayArray */ cwrite_16 (fh, GSPtr->CurrentActivity); cwrite_16 (fh, 0); /* CLOCK_STATE alignment padding */ SaveClockState (&GSPtr->GameClock, fh); cwrite_16 (fh, GSPtr->autopilot.x); cwrite_16 (fh, GSPtr->autopilot.y); cwrite_16 (fh, GSPtr->ip_location.x); cwrite_16 (fh, GSPtr->ip_location.y); /* STAMP ShipStamp */ cwrite_16 (fh, GSPtr->ShipStamp.origin.x); cwrite_16 (fh, GSPtr->ShipStamp.origin.y); cwrite_32 (fh, (DWORD)GSPtr->ShipStamp.frame); /* abused ptr to store DWORD */ /* VELOCITY_DESC velocity */ cwrite_16 (fh, GSPtr->velocity.TravelAngle); cwrite_16 (fh, GSPtr->velocity.vector.width); cwrite_16 (fh, GSPtr->velocity.vector.height); cwrite_16 (fh, GSPtr->velocity.fract.width); cwrite_16 (fh, GSPtr->velocity.fract.height); cwrite_16 (fh, GSPtr->velocity.error.width); cwrite_16 (fh, GSPtr->velocity.error.height); cwrite_16 (fh, GSPtr->velocity.incr.width); cwrite_16 (fh, GSPtr->velocity.incr.height); cwrite_16 (fh, 0); /* VELOCITY_DESC padding */ cwrite_32 (fh, GSPtr->BattleGroupRef); DummySaveQueue (&GSPtr->avail_race_q, fh); DummySaveQueue (&GSPtr->npc_built_ship_q, fh); DummySaveQueue (&GSPtr->encounter_q, fh); DummySaveQueue (&GSPtr->built_ship_q, fh); cwrite_a8 (fh, GSPtr->GameState, sizeof (GSPtr->GameState)); assert (sizeof (GSPtr->GameState) % 4 == 3); cwrite_8 (fh, 0); /* GAME_STATE alignment padding */ } static BOOLEAN SaveSisState (PSIS_STATE SSPtr, PVOID fp) { if ( write_32 (fp, SSPtr->log_x) != 1 || write_32 (fp, SSPtr->log_y) != 1 || write_32 (fp, SSPtr->ResUnits) != 1 || write_32 (fp, SSPtr->FuelOnBoard) != 1 || write_16 (fp, SSPtr->CrewEnlisted) != 1 || write_16 (fp, SSPtr->TotalElementMass) != 1 || write_16 (fp, SSPtr->TotalBioMass) != 1 || write_a8 (fp, SSPtr->ModuleSlots, NUM_MODULE_SLOTS) != 1 || write_a8 (fp, SSPtr->DriveSlots, NUM_DRIVE_SLOTS) != 1 || write_a8 (fp, SSPtr->JetSlots, NUM_JET_SLOTS) != 1 || write_8 (fp, SSPtr->NumLanders) != 1 || write_a16 (fp, SSPtr->ElementAmounts, NUM_ELEMENT_CATEGORIES) != 1 || write_a8 (fp, SSPtr->ShipName, SIS_NAME_SIZE) != 1 || write_a8 (fp, SSPtr->CommanderName, SIS_NAME_SIZE) != 1 || write_a8 (fp, SSPtr->PlanetName, SIS_NAME_SIZE) != 1 || write_16 (fp, 0) != 1 /* padding */ ) return FALSE; else return TRUE; } static BOOLEAN SaveSummary (SUMMARY_DESC *SummPtr, PVOID fp) { if (!SaveSisState (&SummPtr->SS, fp)) return FALSE; if ( write_8 (fp, SummPtr->Activity) != 1 || write_8 (fp, SummPtr->Flags) != 1 || write_8 (fp, SummPtr->day_index) != 1 || write_8 (fp, SummPtr->month_index) != 1 || write_16 (fp, SummPtr->year_index) != 1 || write_8 (fp, SummPtr->MCreditLo) != 1 || write_8 (fp, SummPtr->MCreditHi) != 1 || write_8 (fp, SummPtr->NumShips) != 1 || write_8 (fp, SummPtr->NumDevices) != 1 || write_a8 (fp, SummPtr->ShipList, MAX_BUILT_SHIPS) != 1 || write_a8 (fp, SummPtr->DeviceList, MAX_EXCLUSIVE_DEVICES) != 1 || write_16 (fp, 0) != 1 /* padding */ ) return FALSE; else return TRUE; } static void SaveStarDesc (STAR_DESCPTR SDPtr, DECODE_REF fh) { cwrite_16 (fh, SDPtr->star_pt.x); cwrite_16 (fh, SDPtr->star_pt.y); cwrite_8 (fh, SDPtr->Type); cwrite_8 (fh, SDPtr->Index); cwrite_8 (fh, SDPtr->Prefix); cwrite_8 (fh, SDPtr->Postfix); } static void PrepareSummary (SUMMARY_DESC *SummPtr) { SummPtr->SS = GlobData.SIS_state; switch (SummPtr->Activity = LOBYTE (GLOBAL (CurrentActivity))) { case IN_HYPERSPACE: if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1) SummPtr->Activity = IN_QUASISPACE; break; case IN_INTERPLANETARY: if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) == (BYTE)~0) SummPtr->Activity = IN_STARBASE; else if (pSolarSysState && pSolarSysState->MenuState.Initialized >= 3) SummPtr->Activity = IN_PLANET_ORBIT; break; } SummPtr->MCreditLo = GET_GAME_STATE (MELNORME_CREDIT0); SummPtr->MCreditHi = GET_GAME_STATE (MELNORME_CREDIT1); { HSTARSHIP hStarShip, hNextShip; for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), SummPtr->NumShips = 0; hStarShip; hStarShip = hNextShip, ++SummPtr->NumShips) { SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip ); hNextShip = _GetSuccLink (StarShipPtr); SummPtr->ShipList[SummPtr->NumShips] = GET_RACE_ID (StarShipPtr); UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); } } SummPtr->NumDevices = InventoryDevices (SummPtr->DeviceList); SummPtr->Flags = GET_GAME_STATE (LANDER_SHIELDS) | (GET_GAME_STATE (IMPROVED_LANDER_SPEED) << (4 + 0)) | (GET_GAME_STATE (IMPROVED_LANDER_CARGO) << (4 + 1)) | (GET_GAME_STATE (IMPROVED_LANDER_SHOT) << (4 + 2)) | ((GET_GAME_STATE (CHMMR_BOMB_STATE) < 2 ? 0 : 1) << (4 + 3)); SummPtr->day_index = GLOBAL (GameClock.day_index); SummPtr->month_index = GLOBAL (GameClock.month_index); SummPtr->year_index = GLOBAL (GameClock.year_index); } static void SaveProblemMessage (PSTAMP MsgStamp) { #define MAX_MSG_LINES 1 RECT r; COUNT i; TEXT t; UNICODE *ppStr[MAX_MSG_LINES]; ppStr[0] = GAME_STRING (SAVEGAME_STRING_BASE + 2); SetContextFont (StarConFont); t.baseline.x = t.baseline.y = 0; t.align = ALIGN_CENTER; for (i = 0; i < MAX_MSG_LINES; ++i) { RECT tr; t.pStr = ppStr[i]; if (*t.pStr == '\0') break; t.CharCount = (COUNT)~0; TextRect (&t, &tr, NULL_PTR); if (i == 0) r = tr; else BoxUnion (&tr, &r, &r); t.baseline.y += 11; } t.baseline.x = ((SIS_SCREEN_WIDTH >> 1) - (r.extent.width >> 1)) - r.corner.x; t.baseline.y = ((SIS_SCREEN_HEIGHT >> 1) - (r.extent.height >> 1)) - r.corner.y; r.corner.x += t.baseline.x - 4; r.corner.y += t.baseline.y - 4; r.extent.width += 8; r.extent.height += 8; { RECT clip_r; GetContextClipRect (&clip_r); MsgStamp->origin = r.corner; r.corner.x += clip_r.corner.x; r.corner.y += clip_r.corner.y; MsgStamp->frame = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); r.corner.x -= clip_r.corner.x; r.corner.y -= clip_r.corner.y; } BatchGraphics (); DrawStarConBox (&r, 2, BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F), TRUE, BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x0F)); for (i = 0; i < MAX_MSG_LINES; ++i) { t.pStr = ppStr[i]; if (*t.pStr == '\0') break; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += 11; } UnbatchGraphics (); } void SaveProblem (void) { STAMP s; CONTEXT OldContext; LockMutex (GraphicsLock); OldContext = SetContext (SpaceContext); SaveProblemMessage (&s); FlushGraphics (); UnlockMutex (GraphicsLock); while (AnyButtonPress (FALSE)); do { TaskSwitch (); UpdateInputState (); } while (!(PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_SPECIAL] || (GLOBAL (CurrentActivity) & CHECK_ABORT))); LockMutex (GraphicsLock); BatchGraphics (); DrawStamp (&s); UnbatchGraphics (); SetContext (OldContext); DestroyDrawable (ReleaseDrawable (s.frame)); UnlockMutex (GraphicsLock); return; } // This function first writes to a memory file, and then writes the whole // lot to the actual save file at once. BOOLEAN SaveGame (COUNT which_game, SUMMARY_DESC *SummPtr) { BOOLEAN success, made_room; PVOID out_fp; MEM_HANDLE h; DECODE_REF fh; success = TRUE; made_room = FALSE; RetrySave: h = mem_request (10 * 1024); out_fp = mem_lock (h); if (out_fp == 0 || (fh = copen (out_fp, MEMORY_STREAM, STREAM_WRITE)) == 0) { if (success) { success = FALSE; made_room = TRUE; mem_unlock (h); mem_release (h); FreeSC2Data (); log_add (log_Debug, "Insufficient room for save buffers" " -- RETRYING"); goto RetrySave; } else log_add (log_Debug, "Insufficient room for save buffers" " -- GIVING UP!"); } else { GAME_STATE_FILE *fp; DWORD flen; COUNT num_links; FRAME frame; POINT pt; STAR_DESC SD; char buf[256], file[PATH_MAX]; success = TRUE; if (CurStarDescPtr) SD = *CurStarDescPtr; else memset (&SD, 0, sizeof (SD)); // XXX: Backup: ShipStamp.frame is abused to store DWORD info // SaveFlagshipState() overwrites it with a DWORD value frame = GLOBAL (ShipStamp.frame); pt = GLOBAL (ip_location); SaveFlagshipState (); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && !(GLOBAL (CurrentActivity) & (START_ENCOUNTER | START_INTERPLANETARY))) PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); SaveGameState (&GlobData.Game_state, fh); GLOBAL (ip_location) = pt; // XXX: Restore: ShipStamp.frame is abused to store DWORD info GLOBAL (ShipStamp.frame) = frame; SaveShipQueue (fh, &GLOBAL (avail_race_q)); if (!(GLOBAL (CurrentActivity) & START_INTERPLANETARY)) SaveShipQueue (fh, &GLOBAL (npc_built_ship_q)); SaveShipQueue (fh, &GLOBAL (built_ship_q)); // Save the number of game events (compressed). num_links = CountLinks (&GLOBAL (GameClock.event_q)); cwrite_16 (fh, num_links); // Save the game events themselves (compressed): { HEVENT hEvent; hEvent = GetHeadLink (&GLOBAL (GameClock.event_q)); while (num_links--) { HEVENT hNextEvent; EVENTPTR EventPtr; LockEvent (hEvent, &EventPtr); hNextEvent = GetSuccEvent (EventPtr); SaveEvent (EventPtr, fh); UnlockEvent (hEvent); hEvent = hNextEvent; } } // Save the number of encounters (black globes in HS/QS (compressed)) num_links = CountLinks (&GLOBAL (encounter_q)); // Save the encounters themselves (compressed): cwrite_16 (fh, num_links); { HENCOUNTER hEncounter; hEncounter = GetHeadLink (&GLOBAL (encounter_q)); while (num_links--) { HENCOUNTER hNextEncounter; ENCOUNTERPTR EncounterPtr; LockEncounter (hEncounter, &EncounterPtr); hNextEncounter = GetSuccEncounter (EncounterPtr); SaveEncounter (EncounterPtr, fh); UnlockEncounter (hEncounter); hEncounter = hNextEncounter; } } // Copy the star info file to the memory file (compressed). fp = OpenStateFile (STARINFO_FILE, "rb"); if (fp) { flen = LengthStateFile (fp); // Write the uncompressed size. cwrite_32 (fh, flen); while (flen) { COUNT num_bytes; num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; ReadStateFile (buf, num_bytes, 1, fp); cwrite (buf, num_bytes, 1, fh); flen -= num_bytes; } CloseStateFile (fp); } // Copy the defined groupinfo file into the memory file (compressed) fp = OpenStateFile (DEFGRPINFO_FILE, "rb"); if (fp) { flen = LengthStateFile (fp); // Write the uncompressed size. cwrite_32 (fh, flen); while (flen) { COUNT num_bytes; num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; ReadStateFile (buf, num_bytes, 1, fp); cwrite (buf, num_bytes, 1, fh); flen -= num_bytes; } CloseStateFile (fp); } // Copy the random groupinfo file into the memory file (compressed) fp = OpenStateFile (RANDGRPINFO_FILE, "rb"); if (fp) { flen = LengthStateFile (fp); // Write the uncompressed size. cwrite_32 (fh, flen); while (flen) { COUNT num_bytes; num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; ReadStateFile (buf, num_bytes, 1, fp); cwrite (buf, num_bytes, 1, fh); flen -= num_bytes; } CloseStateFile (fp); } // Write the current star desc into the memory file (compressed). SaveStarDesc (&SD, fh); flen = cclose (fh); // Write the memory file to the actual savegame file. sprintf (file, "starcon2.%02u", which_game); log_add (log_Debug, "'%s' is %u bytes long", file, flen + sizeof (*SummPtr)); if (flen && (out_fp = res_OpenResFile (saveDir, file, "wb"))) { PrepareSummary (SummPtr); success = SaveSummary (SummPtr, out_fp); // Then write the rest of the data. if (success && WriteResFile (mem_lock (h), (COUNT)flen, 1, out_fp) == 0) success = FALSE; mem_unlock (h); if (res_CloseResFile ((uio_Stream *)out_fp) == 0) success = FALSE; } else success = FALSE; if (!success) DeleteResFile (saveDir, file); } mem_unlock (h); mem_release (h); if (made_room) LoadSC2Data (); return (success); } uqm-0.6.2/sc2/src/sc2code/intel.h0000600000175000017500000000521210543202103015061 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _INTEL_H #define _INTEL_H #include "controls.h" #include "element.h" #include "races.h" typedef enum { PURSUE = 0, AVOID, ENTICE, NO_MOVEMENT } MOVEMENT_STATE; typedef struct { PELEMENT ObjectPtr; COUNT facing, which_turn; MOVEMENT_STATE MoveState; } EVALUATE_DESC; typedef EVALUATE_DESC *PEVALUATE_DESC; #define EVALUATE_DESCPTR PEVALUATE_DESC #define MANEUVERABILITY(pi) ((pi)->ManeuverabilityIndex) #define WEAPON_RANGE(pi) ((pi)->WeaponRange) #define WORLD_TO_TURN(d) ((d)>>6) #define CLOSE_RANGE_WEAPON DISPLAY_TO_WORLD (50) #define LONG_RANGE_WEAPON DISPLAY_TO_WORLD (1000) #define FAST_SHIP 150 #define MEDIUM_SHIP 45 #define SLOW_SHIP 25 enum { ENEMY_SHIP_INDEX = 0, CREW_OBJECT_INDEX, ENEMY_WEAPON_INDEX, GRAVITY_MASS_INDEX, FIRST_EMPTY_INDEX }; extern STARSHIPPTR CyborgDescPtr; extern SIZE cur_player; extern BATTLE_INPUT_STATE computer_intelligence (COUNT player, STARSHIPPTR StarShipPtr); extern BATTLE_INPUT_STATE tactical_intelligence (COUNT player, STARSHIPPTR StarShipPtr); extern void ship_intelligence (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR ObjectsOfConcern, COUNT ConcernCounter); extern BOOLEAN ship_weapons (ELEMENTPTR ShipPtr, ELEMENTPTR OtherPtr, COUNT margin_of_error); extern void Pursue (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr); extern void Entice (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr); extern void Avoid (ELEMENTPTR ShipPtr, EVALUATE_DESCPTR EvalDescPtr); extern BOOLEAN TurnShip (ELEMENTPTR ShipPtr, COUNT angle); extern BOOLEAN ThrustShip (ELEMENTPTR ShipPtr, COUNT angle); #define HUMAN_CONTROL (BYTE)(1 << 0) #define CYBORG_CONTROL (BYTE)(1 << 1) #define PSYTRON_CONTROL (BYTE)(1 << 2) #define NETWORK_CONTROL (BYTE)(1 << 3) #define COMPUTER_CONTROL (CYBORG_CONTROL | PSYTRON_CONTROL) #define STANDARD_RATING (BYTE)(1 << 4) #define GOOD_RATING (BYTE)(1 << 5) #define AWESOME_RATING (BYTE)(1 << 6) #endif /* _INTEL_H */ uqm-0.6.2/sc2/src/sc2code/starcon.h0000600000175000017500000000155210543202101015420 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _STARCON_H #define _STARCON_H extern int Starcon2Main (void *threadArg); extern void FreeGameData (void); #endif /* _STARCON_H */ uqm-0.6.2/sc2/src/sc2code/outfit.c0000600000175000017500000004722010543202103015260 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "options.h" #include "colors.h" #include "controls.h" #include "gameopt.h" #include "gamestr.h" #include "resinst.h" #include "nameref.h" #include "settings.h" #include "starbase.h" #include "setup.h" #include "sis.h" #include "sounds.h" #include "libs/graphics/gfx_common.h" enum { OUTFIT_FUEL, OUTFIT_MODULES, OUTFIT_SAVELOAD, OUTFIT_EXIT, OUTFIT_DOFUEL }; static void DrawModuleStrings (PMENU_STATE pMS, BYTE NewModule) { RECT r; STAMP s; CONTEXT OldContext; OldContext = SetContext (StatusContext); GetContextClipRect (&r); s.origin.x = RADAR_X - r.corner.x; s.origin.y = RADAR_Y - r.corner.y; r.corner.x = s.origin.x - 1; r.corner.y = s.origin.y - 11; r.extent.width = RADAR_WIDTH + 2; r.extent.height = 11; BatchGraphics (); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); DrawFilledRectangle (&r); if (NewModule >= EMPTY_SLOT) { r.corner = s.origin; r.extent.width = RADAR_WIDTH; r.extent.height = RADAR_HEIGHT; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); DrawFilledRectangle (&r); } else if (pMS->CurFrame) { TEXT t; UNICODE buf[40]; s.frame = SetAbsFrameIndex (pMS->CurFrame, NewModule); DrawStamp (&s); t.baseline.x = s.origin.x + RADAR_WIDTH - 2; t.baseline.y = s.origin.y + RADAR_HEIGHT - 2; t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; t.pStr = buf; sprintf (buf, "%u", GLOBAL (ModuleCost[NewModule]) * MODULE_COST_SCALE); SetContextFont (TinyFont); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x1F, 0x00), 0x02)); font_DrawText (&t); } UnbatchGraphics (); SetContext (OldContext); } static void RedistributeFuel (void) { COUNT m; DWORD FuelVolume; RECT r; if ((FuelVolume = GLOBAL_SIS (FuelOnBoard)) <= FUEL_RESERVE) return; GLOBAL_SIS (FuelOnBoard) = 0; m = FUEL_VOLUME_PER_ROW; r.extent.width = 3; r.extent.height = 1; while (FuelVolume -= m) { GLOBAL_SIS (FuelOnBoard) += FUEL_VOLUME_PER_ROW; GetFTankCapacity (&r.corner); DrawPoint (&r.corner); r.corner.x += r.extent.width + 1; DrawPoint (&r.corner); r.corner.x -= r.extent.width; SetContextForeGroundColor (SetContextBackGroundColor (BLACK_COLOR)); DrawFilledRectangle (&r); if (FuelVolume < FUEL_VOLUME_PER_ROW) m = (COUNT)FuelVolume; } FuelVolume = GLOBAL_SIS (FuelOnBoard) + m; r.extent.width = 5; while ((GLOBAL_SIS (FuelOnBoard) += FUEL_VOLUME_PER_ROW) < GetFTankCapacity (&r.corner)) { SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0B, 0x00, 0x00), 0x2E)); DrawFilledRectangle (&r); } GLOBAL_SIS (FuelOnBoard) = FuelVolume; } #define LANDER_X 24 #define LANDER_Y 67 #define LANDER_WIDTH 15 static void DisplayLanders (PMENU_STATE pMS) { STAMP s; s.frame = pMS->ModuleFrame; if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 3) { s.origin.x = s.origin.y = 0; s.frame = DecFrameIndex (s.frame); DrawStamp (&s); } else { COUNT i; s.origin.x = LANDER_X; s.origin.y = LANDER_Y; for (i = 0; i < GLOBAL_SIS (NumLanders); ++i) { DrawStamp (&s); s.origin.x += LANDER_WIDTH; } SetContextForeGroundColor (BLACK_COLOR); for (; i < MAX_LANDERS; ++i) { DrawFilledStamp (&s); s.origin.x += LANDER_WIDTH; } } } static BOOLEAN DoInstallModule (PMENU_STATE pMS) { BYTE NewState, new_slot_piece, old_slot_piece; SIZE FirstItem, LastItem; BOOLEAN select, cancel, motion; if (GLOBAL (CurrentActivity) & CHECK_ABORT) { pMS->InputFunc = DoOutfit; return (TRUE); } select = PulsedInputState.menu[KEY_MENU_SELECT]; cancel = PulsedInputState.menu[KEY_MENU_CANCEL]; motion = PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_RIGHT] || PulsedInputState.menu[KEY_MENU_UP] || PulsedInputState.menu[KEY_MENU_DOWN]; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); FirstItem = 0; NewState = pMS->CurState; switch (NewState) { case PLANET_LANDER: case EMPTY_SLOT + 3: old_slot_piece = pMS->delta_item < GLOBAL_SIS (NumLanders) ? PLANET_LANDER : (EMPTY_SLOT + 3); LastItem = MAX_LANDERS - 1; break; case FUSION_THRUSTER: case EMPTY_SLOT + 0: old_slot_piece = GLOBAL_SIS (DriveSlots[pMS->delta_item]); LastItem = NUM_DRIVE_SLOTS - 1; break; case TURNING_JETS: case EMPTY_SLOT + 1: old_slot_piece = GLOBAL_SIS (JetSlots[pMS->delta_item]); LastItem = NUM_JET_SLOTS - 1; break; default: old_slot_piece = GLOBAL_SIS (ModuleSlots[pMS->delta_item]); if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 3) FirstItem = NUM_BOMB_MODULES; LastItem = NUM_MODULE_SLOTS - 1; break; } if (NewState < CREW_POD) FirstItem = LastItem = NewState; else if (NewState < EMPTY_SLOT) FirstItem = CREW_POD, LastItem = NUM_PURCHASE_MODULES - 1; if (!pMS->Initialized) { new_slot_piece = old_slot_piece; pMS->Initialized = TRUE; pMS->InputFunc = DoInstallModule; LockMutex (GraphicsLock); SetContext (SpaceContext); ClearSISRect (CLEAR_SIS_RADAR); SetFlashRect (NULL_PTR, (FRAME)0); goto InitFlash; } else if (select || cancel) { new_slot_piece = pMS->CurState; if (select) { if (new_slot_piece < EMPTY_SLOT) { if (GLOBAL_SIS (ResUnits) < (DWORD)(GLOBAL (ModuleCost[new_slot_piece]) * MODULE_COST_SCALE)) { // not enough RUs to build PlayMenuSound (MENU_SOUND_FAILURE); return (TRUE); } } else if (new_slot_piece == EMPTY_SLOT + 2) { if (old_slot_piece == CREW_POD) { if (GLOBAL_SIS (CrewEnlisted) > CREW_POD_CAPACITY * (CountSISPieces (CREW_POD) - 1)) { // crew pod still needed for crew recruited PlayMenuSound (MENU_SOUND_FAILURE); return (TRUE); } } else if (old_slot_piece == FUEL_TANK || old_slot_piece == HIGHEFF_FUELSYS) { DWORD volume; volume = (DWORD)CountSISPieces (FUEL_TANK) * FUEL_TANK_CAPACITY + (DWORD)CountSISPieces (HIGHEFF_FUELSYS) * HEFUEL_TANK_CAPACITY; volume -= (old_slot_piece == FUEL_TANK ? FUEL_TANK_CAPACITY : HEFUEL_TANK_CAPACITY); if (GLOBAL_SIS (FuelOnBoard) > volume + FUEL_RESERVE) { // fuel tank still needed for the fuel on board PlayMenuSound (MENU_SOUND_FAILURE); return (TRUE); } } else if (old_slot_piece == STORAGE_BAY) { if (GLOBAL_SIS (TotalElementMass) > STORAGE_BAY_CAPACITY * (CountSISPieces (STORAGE_BAY) - 1)) { // storage bay still needed for the cargo PlayMenuSound (MENU_SOUND_FAILURE); return (TRUE); } } } } LockMutex (GraphicsLock); SetContext (SpaceContext); SetFlashRect (NULL_PTR, (FRAME)0); if (select) { if (new_slot_piece >= EMPTY_SLOT && old_slot_piece >= EMPTY_SLOT) { new_slot_piece -= EMPTY_SLOT - 1; if (new_slot_piece > CREW_POD) new_slot_piece = PLANET_LANDER; } else { switch (pMS->CurState) { case PLANET_LANDER: ++GLOBAL_SIS (NumLanders); break; case EMPTY_SLOT + 3: --GLOBAL_SIS (NumLanders); break; case FUSION_THRUSTER: case EMPTY_SLOT + 0: GLOBAL_SIS (DriveSlots[pMS->delta_item]) = new_slot_piece; break; case TURNING_JETS: case EMPTY_SLOT + 1: GLOBAL_SIS (JetSlots[pMS->delta_item]) = new_slot_piece; break; default: GLOBAL_SIS (ModuleSlots[pMS->delta_item]) = new_slot_piece; break; } if (new_slot_piece < EMPTY_SLOT) DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, -(GLOBAL (ModuleCost[new_slot_piece]) * MODULE_COST_SCALE)); else /* if (old_slot_piece < EMPTY_SLOT) */ DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, GLOBAL (ModuleCost[old_slot_piece]) * MODULE_COST_SCALE); if (pMS->CurState == PLANET_LANDER || pMS->CurState == EMPTY_SLOT + 3) DisplayLanders (pMS); else { DrawShipPiece (pMS, new_slot_piece, pMS->delta_item, FALSE); if (new_slot_piece > TURNING_JETS && old_slot_piece > TURNING_JETS) RedistributeFuel (); if (optWhichFonts == OPT_PC) DrawFlagshipStats (); } } cancel = FALSE; } if (pMS->CurState < EMPTY_SLOT) { pMS->CurState += EMPTY_SLOT - 1; if (pMS->CurState < EMPTY_SLOT) pMS->CurState = EMPTY_SLOT + 3; else if (pMS->CurState > EMPTY_SLOT + 2) pMS->CurState = EMPTY_SLOT + 2; if (cancel) new_slot_piece = pMS->CurState; goto InitFlash; } else if (!cancel) { pMS->CurState = new_slot_piece; goto InitFlash; } else { SetContext (StatusContext); UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_FUEL, pMS->CurState = OUTFIT_MODULES); LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); pMS->InputFunc = DoOutfit; ClearSISRect (DRAW_SIS_DISPLAY); } UnlockMutex (GraphicsLock); } else if (motion) { SIZE NewItem; NewItem = NewState < EMPTY_SLOT ? pMS->CurState : pMS->delta_item; do { if (NewState >= EMPTY_SLOT && (PulsedInputState.menu[KEY_MENU_UP] || PulsedInputState.menu[KEY_MENU_DOWN])) { if (PulsedInputState.menu[KEY_MENU_UP]) { if (NewState-- == EMPTY_SLOT) NewState = EMPTY_SLOT + 3; } else { if (NewState++ == EMPTY_SLOT + 3) NewState = EMPTY_SLOT; } NewItem = 0; if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 3) { if (NewState == EMPTY_SLOT + 3) NewState = PulsedInputState.menu[KEY_MENU_UP] ? EMPTY_SLOT + 2 : EMPTY_SLOT; if (NewState == EMPTY_SLOT + 2) NewItem = NUM_BOMB_MODULES; } pMS->delta_item = NewItem; } else if (PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_UP]) { if (NewItem-- == FirstItem) NewItem = LastItem; } else if (PulsedInputState.menu[KEY_MENU_RIGHT] || PulsedInputState.menu[KEY_MENU_DOWN]) { if (NewItem++ == LastItem) NewItem = FirstItem; } } while (NewState < EMPTY_SLOT && (GLOBAL (ModuleCost[NewItem]) == 0 || (NewItem >= GUN_WEAPON && NewItem <= CANNON_WEAPON && pMS->delta_item > 0 && pMS->delta_item < 13))); LockMutex (GraphicsLock); if (NewState < EMPTY_SLOT) { if (NewItem != pMS->CurState) { pMS->CurState = NewItem; DrawModuleStrings (pMS, NewItem); // flash with PC menus too SetFlashRect (SFR_MENU_ANY, (FRAME)0); } } else if (NewItem != pMS->delta_item || NewState != pMS->CurState) { SIZE w; switch (NewState) { case PLANET_LANDER: case EMPTY_SLOT + 3: new_slot_piece = NewItem < GLOBAL_SIS (NumLanders) ? PLANET_LANDER : (EMPTY_SLOT + 3); break; case FUSION_THRUSTER: case EMPTY_SLOT + 0: new_slot_piece = GLOBAL_SIS (DriveSlots[NewItem]); break; case TURNING_JETS: case EMPTY_SLOT + 1: new_slot_piece = GLOBAL_SIS (JetSlots[NewItem]); break; default: new_slot_piece = GLOBAL_SIS (ModuleSlots[NewItem]); break; } SetContext (SpaceContext); if (NewState == pMS->CurState) { if (NewState == PLANET_LANDER || NewState == EMPTY_SLOT + 3) w = LANDER_WIDTH; else w = SHIP_PIECE_OFFSET; w *= (NewItem - pMS->delta_item); pMS->flash_rect0.corner.x += w; pMS->delta_item = NewItem; } else { pMS->CurState = NewState; InitFlash: w = SHIP_PIECE_OFFSET; switch (pMS->CurState) { case PLANET_LANDER: case EMPTY_SLOT + 3: pMS->flash_rect0.corner.x = LANDER_X - 1; pMS->flash_rect0.corner.y = LANDER_Y - 1; pMS->flash_rect0.extent.width = 11 + 2; pMS->flash_rect0.extent.height = 13 + 2; w = LANDER_WIDTH; break; case FUSION_THRUSTER: case EMPTY_SLOT + 0: pMS->flash_rect0.corner.x = DRIVE_TOP_X - 1; pMS->flash_rect0.corner.y = DRIVE_TOP_Y - 1; pMS->flash_rect0.extent.width = 8; pMS->flash_rect0.extent.height = 6; break; case TURNING_JETS: case EMPTY_SLOT + 1: pMS->flash_rect0.corner.x = JET_TOP_X - 1; pMS->flash_rect0.corner.y = JET_TOP_Y - 1; pMS->flash_rect0.extent.width = 9; pMS->flash_rect0.extent.height = 10; break; default: pMS->flash_rect0.corner.x = MODULE_TOP_X - 1; pMS->flash_rect0.corner.y = MODULE_TOP_Y - 1; pMS->flash_rect0.extent.width = SHIP_PIECE_OFFSET + 2; pMS->flash_rect0.extent.height = 34; break; } w *= pMS->delta_item; pMS->flash_rect0.corner.x += w; } DrawModuleStrings (pMS, new_slot_piece); if (pMS->CurState < EMPTY_SLOT) // flash with PC menus too SetFlashRect (SFR_MENU_ANY, (FRAME)0); else SetFlashRect (&pMS->flash_rect0, (FRAME)0); } UnlockMutex (GraphicsLock); } return (TRUE); } static void ChangeFuelQuantity (void) { RECT r; r.extent.height = 1; if (PulsedInputState.menu[KEY_MENU_UP]) { LockMutex (GraphicsLock); SetContext (SpaceContext); if (GetFTankCapacity (&r.corner) > GLOBAL_SIS (FuelOnBoard) && GLOBAL_SIS (ResUnits) >= (DWORD)GLOBAL (FuelCost)) { if (GLOBAL_SIS (FuelOnBoard) >= FUEL_RESERVE - FUEL_TANK_SCALE) { r.extent.width = 3; DrawPoint (&r.corner); r.corner.x += r.extent.width + 1; DrawPoint (&r.corner); r.corner.x -= r.extent.width; SetContextForeGroundColor (SetContextBackGroundColor (BLACK_COLOR)); DrawFilledRectangle (&r); } DeltaSISGauges (0, FUEL_TANK_SCALE, -GLOBAL (FuelCost)); SetContext (StatusContext); GetGaugeRect (&r, FALSE); SetFlashRect (&r, (FRAME)0); } else { // no more room for fuel or not enough RUs PlayMenuSound (MENU_SOUND_FAILURE); } UnlockMutex (GraphicsLock); } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { LockMutex (GraphicsLock); SetContext (SpaceContext); if (GLOBAL_SIS (FuelOnBoard)) { DeltaSISGauges (0, -FUEL_TANK_SCALE, GLOBAL (FuelCost)); if (GLOBAL_SIS (FuelOnBoard) % FUEL_VOLUME_PER_ROW == 0) { GetFTankCapacity (&r.corner); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0B, 0x00, 0x00), 0x2E)); r.extent.width = 5; DrawFilledRectangle (&r); } } else { // no fuel left to drain PlayMenuSound (MENU_SOUND_FAILURE); } SetContext (StatusContext); GetGaugeRect (&r, FALSE); SetFlashRect (&r, (FRAME)0); UnlockMutex (GraphicsLock); } } BOOLEAN DoOutfit (PMENU_STATE pMS) { if (GLOBAL (CurrentActivity) & CHECK_ABORT) goto ExitOutfit; if (!pMS->Initialized) { pMS->InputFunc = DoOutfit; pMS->Initialized = TRUE; { COUNT num_frames; STAMP s; pMS->CurFrame = CaptureDrawable ( LoadGraphic (MODULES_PMAP_ANIM)); pMS->hMusic = LoadMusic (OUTFIT_MUSIC); pMS->CurState = OUTFIT_FUEL; pMS->ModuleFrame = CaptureDrawable ( LoadGraphic (SISMODS_MASK_PMAP_ANIM)); s.origin.x = s.origin.y = 0; s.frame = CaptureDrawable ( LoadGraphic (OUTFIT_PMAP_ANIM)); LockMutex (GraphicsLock); SetTransitionSource (NULL); BatchGraphics (); DrawSISFrame (); DrawSISMessage (GAME_STRING (STARBASE_STRING_BASE + 2)); DrawSISTitle (GAME_STRING (STARBASE_STRING_BASE)); SetContext (SpaceContext); DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); for (num_frames = 0; num_frames < NUM_DRIVE_SLOTS; ++num_frames) { BYTE which_piece; which_piece = GLOBAL_SIS (DriveSlots[num_frames]); if (which_piece < EMPTY_SLOT) DrawShipPiece (pMS, which_piece, num_frames, FALSE); } for (num_frames = 0; num_frames < NUM_JET_SLOTS; ++num_frames) { BYTE which_piece; which_piece = GLOBAL_SIS (JetSlots[num_frames]); if (which_piece < EMPTY_SLOT) DrawShipPiece (pMS, which_piece, num_frames, FALSE); } for (num_frames = 0; num_frames < NUM_MODULE_SLOTS; ++num_frames) { BYTE which_piece; which_piece = GLOBAL_SIS (ModuleSlots[num_frames]); if (which_piece < EMPTY_SLOT) DrawShipPiece (pMS, which_piece, num_frames, FALSE); } RedistributeFuel (); DisplayLanders (pMS); if (GET_GAME_STATE (CHMMR_BOMB_STATE) < 3) { BYTE ShieldFlags; ShieldFlags = GET_GAME_STATE (LANDER_SHIELDS); s.frame = SetAbsFrameIndex (pMS->ModuleFrame, GetFrameCount (pMS->ModuleFrame) - 5); if (ShieldFlags & (1 << EARTHQUAKE_DISASTER)) DrawStamp ((PSTAMP)&s); s.frame = IncFrameIndex (s.frame); if (ShieldFlags & (1 << BIOLOGICAL_DISASTER)) DrawStamp ((PSTAMP)&s); s.frame = IncFrameIndex (s.frame); if (ShieldFlags & (1 << LIGHTNING_DISASTER)) DrawStamp ((PSTAMP)&s); s.frame = IncFrameIndex (s.frame); if (ShieldFlags & (1 << LAVASPOT_DISASTER)) DrawStamp ((PSTAMP)&s); } UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_FUEL, pMS->CurState); LockMutex (GraphicsLock); DrawFlagshipName (FALSE); if (optWhichFonts == OPT_PC) DrawFlagshipStats (); UnlockMutex (GraphicsLock); { RECT r; r.corner.x = 0; r.corner.y = 0; r.extent.width = SCREEN_WIDTH; r.extent.height = SCREEN_HEIGHT; ScreenTransition (3, &r); } PlayMusic (pMS->hMusic, TRUE, 1); UnbatchGraphics (); LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); GLOBAL_SIS (FuelOnBoard) = (GLOBAL_SIS (FuelOnBoard) + (FUEL_TANK_SCALE >> 1)) / FUEL_TANK_SCALE; GLOBAL_SIS (FuelOnBoard) *= FUEL_TANK_SCALE; } SetContext (StatusContext); } else if (PulsedInputState.menu[KEY_MENU_CANCEL] || (PulsedInputState.menu[KEY_MENU_SELECT] && pMS->CurState == OUTFIT_EXIT)) { if (pMS->CurState == OUTFIT_DOFUEL) { pMS->CurState = OUTFIT_FUEL; LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); } else { ExitOutfit: DestroyDrawable (ReleaseDrawable (pMS->CurFrame)); pMS->CurFrame = 0; DestroyDrawable (ReleaseDrawable (pMS->ModuleFrame)); pMS->ModuleFrame = 0; return (FALSE); } } else if (PulsedInputState.menu[KEY_MENU_SELECT]) { switch (pMS->CurState) { case OUTFIT_FUEL: { RECT r; pMS->CurState = OUTFIT_DOFUEL; LockMutex (GraphicsLock); SetContext (StatusContext); GetGaugeRect (&r, FALSE); SetFlashRect (&r, (FRAME)0); UnlockMutex (GraphicsLock); break; } case OUTFIT_DOFUEL: pMS->CurState = OUTFIT_FUEL; LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); break; case OUTFIT_MODULES: pMS->CurState = EMPTY_SLOT + 2; if (GET_GAME_STATE (CHMMR_BOMB_STATE) != 3) pMS->delta_item = 0; else pMS->delta_item = NUM_BOMB_MODULES; pMS->first_item.y = 0; pMS->Initialized = 0; DoInstallModule (pMS); break; case OUTFIT_SAVELOAD: if (GameOptions () == 0) goto ExitOutfit; DrawMenuStateStrings (PM_FUEL, pMS->CurState); LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); break; } } else { switch (pMS->CurState) { case OUTFIT_DOFUEL: SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT | MENU_SOUND_CANCEL); break; default: SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); break; } if (pMS->CurState == OUTFIT_DOFUEL) ChangeFuelQuantity (); else DoMenuChooser (pMS, PM_FUEL); } return (TRUE); } uqm-0.6.2/sc2/src/sc2code/sounds.h0000600000175000017500000000515110543202101015261 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SOUNDS_H #define _SOUNDS_H #include "element.h" #include "libs/compiler.h" #include "libs/sndlib.h" typedef enum { GRAB_CREW = 0, SHIP_EXPLODES, TARGET_DAMAGED_FOR_1_PT, TARGET_DAMAGED_FOR_2_3_PT, TARGET_DAMAGED_FOR_4_5_PT, TARGET_DAMAGED_FOR_6_PLUS_PT } SOUND_EFFECTS; typedef enum { MENU_SOUND_MOVE = 0, MENU_SOUND_SUCCESS, MENU_SOUND_FAILURE, MENU_SOUND_INVOKED, } MENU_SOUND_EFFECT; extern SOUND MenuSounds; extern SOUND GameSounds; /* Constants for DoInput */ typedef UWORD MENU_SOUND_FLAGS; #define MENU_SOUND_UP ((MENU_SOUND_FLAGS)(1 << 0)) #define MENU_SOUND_DOWN ((MENU_SOUND_FLAGS)(1 << 1)) #define MENU_SOUND_LEFT ((MENU_SOUND_FLAGS)(1 << 2)) #define MENU_SOUND_RIGHT ((MENU_SOUND_FLAGS)(1 << 3)) #define MENU_SOUND_SELECT ((MENU_SOUND_FLAGS)(1 << 4)) #define MENU_SOUND_CANCEL ((MENU_SOUND_FLAGS)(1 << 5)) #define MENU_SOUND_SPECIAL ((MENU_SOUND_FLAGS)(1 << 6)) #define MENU_SOUND_PAGEUP ((MENU_SOUND_FLAGS)(1 << 7)) #define MENU_SOUND_PAGEDOWN ((MENU_SOUND_FLAGS)(1 << 8)) #define MENU_SOUND_DELETE ((MENU_SOUND_FLAGS)(1 << 9)) #define MENU_SOUND_ARROWS (MENU_SOUND_UP | MENU_SOUND_DOWN | MENU_SOUND_LEFT | MENU_SOUND_RIGHT) #define MENU_SOUND_NONE ((MENU_SOUND_FLAGS)0) extern void SetMenuSounds (MENU_SOUND_FLAGS sound_0, MENU_SOUND_FLAGS sound_1); extern void GetMenuSounds (MENU_SOUND_FLAGS *sound_0, MENU_SOUND_FLAGS *sound_1); extern void PlaySound (SOUND S, SoundPosition Pos, ELEMENTPTR PositionalObject, BYTE Priority); extern void PlayMenuSound (MENU_SOUND_EFFECT S); extern void ProcessSound (SOUND Sound, ELEMENTPTR PositionalObject); extern SoundPosition CalcSoundPosition (ELEMENTPTR ElementPtr); extern SoundPosition NotPositional (void); extern void UpdateSoundPositions (void); extern void FlushSounds (void); extern void RemoveSoundsForObject (ELEMENTPTR PosObj); #endif /* _SOUNDS_H */ uqm-0.6.2/sc2/src/sc2code/element.h0000600000175000017500000001443210543202101015401 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ELEMENT_H #define _ELEMENT_H #include "battle.h" #include "displist.h" #include "units.h" #include "velocity.h" #include "libs/gfxlib.h" #define BATTLE_FRAME_RATE (ONE_SECOND / 24) #define SHIP_INFO_HEIGHT 65 #define CAPTAIN_XOFFS 4 #define CAPTAIN_YOFFS (SHIP_INFO_HEIGHT + 4) #define SHIP_STATUS_HEIGHT (STATUS_HEIGHT >> 1) #define BAD_GUY_YOFFS 0 #define GOOD_GUY_YOFFS SHIP_STATUS_HEIGHT #define STARCON_TEXT_HEIGHT 7 #define TINY_TEXT_HEIGHT 9 #define BATTLE_CREW_X 10 #define BATTLE_CREW_Y (64 - SAFE_Y) #define NORMAL_LIFE 1 typedef QUEUE_HANDLE HELEMENT; // Bits for ELEMENT_FLAGS: #define GOOD_GUY (1 << 0) #define BAD_GUY (1 << 1) #define PLAYER_SHIP (1 << 2) #define APPEARING (1 << 3) #define DISAPPEARING (1 << 4) #define CHANGING (1 << 5) #define NONSOLID (1 << 6) #define COLLISION (1 << 7) #define IGNORE_SIMILAR (1 << 8) #define DEFY_PHYSICS (1 << 9) #define FINITE_LIFE (1 << 10) #define PRE_PROCESS (1 << 11) #define POST_PROCESS (1 << 12) #define IGNORE_VELOCITY (1 << 13) #define CREW_OBJECT (1 << 14) #define BACKGROUND_OBJECT (1 << 15) #define HYPERJUMP_LIFE 15 #define NUM_EXPLOSION_FRAMES 12 #define GAME_SOUND_PRIORITY 2 typedef enum { VIEW_STABLE, VIEW_SCROLL, VIEW_CHANGE } VIEW_STATE; typedef UWORD ELEMENT_FLAGS; #define NO_PRIM NUM_PRIMS typedef struct state { POINT location; struct { FRAME frame; PFRAME farray; } image; } STATE; typedef STATE *PSTATE; // Any physical object in the simulation. typedef struct element { HELEMENT pred, succ; void (*preprocess_func) (struct element *ElementPtr); void (*postprocess_func) (struct element *ElementPtr); void (*collision_func) (struct element *ElementPtr0, PPOINT pPt0, struct element *ElementPtr1, PPOINT pPt1); void (*death_func) (struct element *ElementPtr); ELEMENT_FLAGS state_flags; COUNT life_span; COUNT crew_level; BYTE mass_points; BYTE turn_wait, thrust_wait; VELOCITY_DESC velocity; INTERSECT_CONTROL IntersectControl; COUNT PrimIndex; STATE current, next; PVOID pParent; // The ship this element belongs to. HELEMENT hTarget; } ELEMENT; typedef ELEMENT *PELEMENT; #define MAX_DISPLAY_PRIMS 280 extern COUNT DisplayFreeList; extern PRIMITIVE DisplayArray[MAX_DISPLAY_PRIMS]; #define AllocDisplayPrim() DisplayFreeList; \ DisplayFreeList = GetSuccLink (GetPrimLinks (&DisplayArray[DisplayFreeList])) #define FreeDisplayPrim(p) SetPrimLinks (&DisplayArray[p], END_OF_LIST, DisplayFreeList); \ DisplayFreeList = (p) #define STATEPTR PSTATE #define ELEMENTPTR PELEMENT #define GetElementStarShip(e,psd) *(psd) = (PVOID)(e)->pParent #define SetElementStarShip(e,psd) ((e)->pParent = (PVOID)(psd)) #define blast_offset thrust_wait #define hit_points crew_level #define next_turn thrust_wait #define MAX_CREW_SIZE 42 #define MAX_ENERGY_SIZE 42 #define MAX_SHIP_MASS 10 #define GRAVITY_MASS(m) ((m) > MAX_SHIP_MASS * 10) #define GRAVITY_THRESHOLD (COUNT)255 #define WHICH_SIDE(f) (((f) & BAD_GUY) >> 1) #define OBJECT_CLOAKED(eptr) \ (GetPrimType (&GLOBAL (DisplayArray[(eptr)->PrimIndex])) >= NUM_PRIMS \ || (GetPrimType (&GLOBAL (DisplayArray[(eptr)->PrimIndex])) == STAMPFILL_PRIM \ && GetPrimColor (&GLOBAL (DisplayArray[(eptr)->PrimIndex])) == BLACK_COLOR)) #define UNDEFINED_LEVEL 0 extern HELEMENT AllocElement (void); extern void FreeElement (HELEMENT hElement); #define PutElement(h) PutQueue (&disp_q, h) #define InsertElement(h,i) InsertQueue (&disp_q, h, i) #define GetHeadElement() GetHeadLink (&disp_q) #define GetTailElement() GetTailLink (&disp_q) #define LockElement(h,eptr) *(eptr) = (ELEMENTPTR)LockLink (&disp_q, h) #define UnlockElement(h) UnlockLink (&disp_q, h) #define GetPredElement(l) _GetPredLink (l) #define GetSuccElement(l) _GetSuccLink (l) extern void RemoveElement (HLINK hLink); extern void RedrawQueue (BOOLEAN clear); extern BOOLEAN DeltaEnergy (ELEMENTPTR ElementPtr, SIZE energy_delta); extern BOOLEAN DeltaCrew (ELEMENTPTR ElementPtr, SIZE crew_delta); extern void PreProcessStatus (PELEMENT ShipPtr); extern void PostProcessStatus (PELEMENT ShipPtr); extern void load_gravity_well (BYTE selector); extern void free_gravity_well (void); extern void spawn_planet (void); extern void spawn_asteroid (PELEMENT ElementPtr); extern void animation_preprocess (PELEMENT ElementPtr); extern void do_damage (ELEMENTPTR ElementPtr, SIZE damage); extern void collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1); extern void crew_preprocess (PELEMENT ElementPtr); extern void crew_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1); extern void AbandonShip (ELEMENTPTR ShipPtr, ELEMENTPTR TargetPtr, COUNT crew_loss); extern BOOLEAN TimeSpaceMatterConflict (ELEMENTPTR ElementPtr); extern COUNT PlotIntercept (ELEMENTPTR ElementPtr0, ELEMENTPTR ElementPtr1, COUNT max_turns, COUNT margin_of_error); extern BOOLEAN LoadKernel (int argc, char *argv[]); extern void FreeKernel (void); extern void InitDisplayList (void); extern void InitGalaxy (void); extern void MoveGalaxy (VIEW_STATE view_state, SIZE dx, SIZE dy); extern void ship_preprocess (PELEMENT ElementPtr); extern void ship_postprocess (PELEMENT ElementPtr); extern void ship_death (PELEMENT ShipPtr); extern BOOLEAN hyper_transition (PELEMENT ElementPtr); extern BOOLEAN CalculateGravity (PELEMENT ElementPtr); extern UWORD inertial_thrust (ELEMENTPTR ElementPtr); extern void SetUpElement (ELEMENTPTR ElementPtr); extern void BattleSong (BOOLEAN DoPlay); extern void FreeBattleSong (void); extern void InsertPrim (PRIM_LINKS *pLinks, COUNT primIndex, COUNT iPI); #endif /* _ELEMENT_H */ uqm-0.6.2/sc2/src/sc2code/istrtab.h0000600000175000017500000000746510543202100015427 0ustar joeyjoey#define STARCON_COLOR_MAP 0x00200004L #define STARCON_GAME_STRINGS 0x03800104L #define HYPER_COLOR_TAB 0x04800204L #define ARISPACE_COLOR_TAB 0x04a00304L #define ORBPLAN_COLOR_MAP 0x05200404L #define OOLITE_COLOR_TAB 0x09000504L #define OOLITE_XLAT_TAB 0x09000604L #define YTTRIC_COLOR_TAB 0x09200704L #define YTTRIC_XLAT_TAB 0x09400804L #define QUASI_DEGENERATE_COLOR_TAB 0x09600904L #define QUASI_DEGENERATE_XLAT_TAB 0x09800a04L #define LANTHANIDE_COLOR_TAB 0x09a00b04L #define TREASURE_COLOR_TAB 0x09c00c04L #define UREA_COLOR_TAB 0x09e00d04L #define UREA_XLAT_TAB 0x0a000e04L #define METAL_COLOR_TAB 0x0a200f04L #define METAL_XLAT_TAB 0x0a201004L #define RADIOACTIVE_COLOR_TAB 0x0a401104L #define OPALESCENT_COLOR_TAB 0x0a601204L #define OPALESCENT_XLAT_TAB 0x0a801304L #define CYANIC_COLOR_TAB 0x0aa01404L #define ACID_COLOR_TAB 0x0ac01504L #define ALKALI_COLOR_TAB 0x0ae01604L #define HALIDE_COLOR_TAB 0x0b001704L #define GREEN_COLOR_TAB 0x0b201804L #define COPPER_COLOR_TAB 0x0b401904L #define CARBIDE_COLOR_TAB 0x0b601a04L #define ULTRAMARINE_COLOR_TAB 0x0b801b04L #define NOBLE_COLOR_TAB 0x0ba01c04L #define AZURE_COLOR_TAB 0x0bc01d04L #define CHONDRITE_COLOR_TAB 0x0be01e04L #define CHONDRITE_XLAT_TAB 0x0be01f04L #define PURPLE_COLOR_TAB 0x0c002004L #define SUPER_DENSE_COLOR_TAB 0x0c202104L #define PELLUCID_COLOR_TAB 0x0c402204L #define DUST_COLOR_TAB 0x0c602304L #define MAROON_COLOR_TAB 0x0c802404L #define CIMMERIAN_COLOR_TAB 0x0ca02504L #define INFRARED_COLOR_TAB 0x0cc02604L #define SELENIC_COLOR_TAB 0x0ce02704L #define AURIC_COLOR_TAB 0x0d002804L #define FLUORESCENT_COLOR_TAB 0x0d202904L #define ULTRAVIOLET_COLOR_TAB 0x0d402a04L #define PLUTONIC_COLOR_TAB 0x0d602b04L #define RAINBOW_COLOR_TAB 0x0d802c04L #define RAINBOW_XLAT_TAB 0x0d802d04L #define CRACKED_COLOR_TAB 0x0da02e04L #define CRACKED_XLAT_TAB 0x0da02f04L #define SAPPHIRE_COLOR_TAB 0x0dc03004L #define SAPPHIRE_XLAT_TAB 0x0de03104L #define ORGANIC_COLOR_TAB 0x0e003204L #define XENOLITHIC_COLOR_TAB 0x0e203304L #define REDUX_COLOR_TAB 0x0e403404L #define REDUX_XLAT_TAB 0x0e403504L #define PRIMORDIAL_COLOR_TAB 0x0e603604L #define EMERALD_COLOR_TAB 0x0e803704L #define CHLORINE_COLOR_TAB 0x0ea03804L #define CHLORINE_XLAT_TAB 0x0ec03904L #define MAGNETIC_COLOR_TAB 0x0ee03a04L #define WATER_COLOR_TAB 0x0f003b04L #define TELLURIC_COLOR_TAB 0x0f203c04L #define HYDROCARBON_COLOR_TAB 0x0f403d04L #define IODINE_COLOR_TAB 0x0f603e04L #define VINYLOGOUS_COLOR_TAB 0x0f803f04L #define RUBY_COLOR_TAB 0x0fa04004L #define MAGMA_COLOR_TAB 0x0fc04104L #define CRIMSON_COLOR_TAB 0x0fe04204L #define GAS_XLAT_TAB 0x10004304L #define BLU_GAS_COLOR_TAB 0x10204404L #define CYA_GAS_COLOR_TAB 0x10404504L #define GRN_GAS_COLOR_TAB 0x10604604L #define GRY_GAS_COLOR_TAB 0x10804704L #define ORA_GAS_COLOR_TAB 0x10a04804L #define PUR_GAS_COLOR_TAB 0x10c04904L #define RED_GAS_COLOR_TAB 0x10e04a04L #define VIO_GAS_COLOR_TAB 0x11004b04L #define YEL_GAS_COLOR_TAB 0x11204c04L #define MOONBASE_STRTAB 0x11604d04L #define MAIDENS_STRTAB 0x11804e04L #define CHMMR_BASE_STRTAB 0x11a04f04L #define AQUA_STRTAB 0x11c05004L #define BURV_BCS_STRTAB 0x11e05104L #define TAALO_DEVICE_STRTAB 0x12005204L #define SUN_DEVICE_STRTAB 0x12205304L #define VAULT_STRTAB 0x12405404L #define WRECK_STRTAB 0x12605504L #define BOMB_STRTAB 0x12805604L #define BEAST_STRTAB 0x12a05704L #define EGG_CASE_STRTAB 0x12c05804L #define SPAPLUTO_STRTAB 0x12e05904L #define BURV_RUINS_STRTAB 0x13005a04L #define ANDROSYNTH_RUINS_STRTAB 0x13205b04L #define DRUUGE_RUINS_STRTAB 0x13405c04L #define PKUNK_RUINS_STRTAB 0x13605d04L #define RUINS_STRTAB 0x13a05e04L #define UMGAH_BCS_STRTAB 0x13c05f04L #define IPSUN_COLOR_MAP 0x05206004L #define HANGAR_COLOR_TAB 0x18a06104L #define INTROPRES_STRTAB 0x23c06204L #define FINALPRES_STRTAB 0x23e06304L #define CREDITS_STRTAB 0x24206404L #define JOYSTICK_ALPHA_STRTAB 0x24406504L #define SETUP_MENU_STRTAB 0x23a11f04L uqm-0.6.2/sc2/src/sc2code/imusicre.h0000600000175000017500000000103710543202103015567 0ustar joeyjoey#define HYPERSPACE_MUSIC 0x04c00006L #define QUASISPACE_MUSIC 0x04e00106L #define IP_MUSIC 0x13e00206L #define ORBIT1_MUSIC 0x14000306L #define ORBIT2_MUSIC 0x14000406L #define ORBIT3_MUSIC 0x14000506L #define ORBIT4_MUSIC 0x14000606L #define ORBIT5_MUSIC 0x14000706L #define REDALERT_MUSIC 0x14600806L #define OUTFIT_MUSIC 0x18800906L #define SHIPYARD_MUSIC 0x18c00a06L #define STARBASE_MUSIC 0x18e00b06L #define BATTLE_MUSIC 0x20a00c06L #define CREDITS_MUSIC 0x23400d06L #define MELEE_MUSIC 0x14200e06L #define MAINMENU_MUSIC 0x18200f06L uqm-0.6.2/sc2/src/sc2code/displist.c0000600000175000017500000001256710543202103015607 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "displist.h" #include "libs/log.h" /* * This file contains code for generic doubly linked lists. * If QUEUE_TABLE is defined, each lists has its own preallocated * pool of link structures. The size is specific on InitQueue(), * and poses a hard limit on the number of elements in the list. */ BOOLEAN InitQueue (PQUEUE pq, COUNT num_elements, OBJ_SIZE size) { SetHeadLink (pq, NULL_HANDLE); SetTailLink (pq, NULL_HANDLE); SetLinkSize (pq, size); #ifndef QUEUE_TABLE return (TRUE); #else /* QUEUE_TABLE */ SetFreeList (pq, NULL_HANDLE); #if 0 log_add (log_Debug, "InitQueue(): num_elements = %d (%d)", num_elements, (BYTE)num_elements); #endif if (AllocQueueTab (pq, num_elements) && LockQueueTab (pq)) { do FreeLink (pq, GetLinkAddr (pq, num_elements)); while (--num_elements); return (TRUE); } return (FALSE); #endif /* QUEUE_TABLE */ } BOOLEAN UninitQueue (PQUEUE pq) { #ifdef QUEUE_TABLE SetHeadLink (pq, NULL_HANDLE); SetTailLink (pq, NULL_HANDLE); SetFreeList (pq, NULL_HANDLE); UnlockQueueTab (pq); FreeQueueTab (pq); return (TRUE); #else /* !QUEUE_TABLE */ HLINK hLink; while ((hLink = GetHeadLink (pq)) != NULL_HANDLE) { RemoveQueue (pq, hLink); if (!FreeLink (pq, hLink)) return (FALSE); } return (TRUE); #endif /* QUEUE_TABLE */ } void ReinitQueue (PQUEUE pq) { SetHeadLink (pq, NULL_HANDLE); SetTailLink (pq, NULL_HANDLE); #ifdef QUEUE_TABLE { COUNT num_elements; SetFreeList (pq, NULL_HANDLE); num_elements = SizeQueueTab (pq); if (num_elements) { do FreeLink (pq, GetLinkAddr (pq, num_elements)); while (--num_elements); } } #endif /* QUEUE_TABLE */ } #ifdef QUEUE_TABLE HLINK AllocLink (PQUEUE pq) { HLINK hLink; hLink = GetFreeList (pq); if (hLink) { LINKPTR LinkPtr; LinkPtr = LockLink (pq, hLink); SetFreeList (pq, _GetSuccLink (LinkPtr)); UnlockLink (pq, hLink); } else log_add (log_Debug, "AllocLink(): No more elements"); return (hLink); } void FreeLink (PQUEUE pq, HLINK hLink) { LINKPTR LinkPtr; LinkPtr = LockLink (pq, hLink); _SetSuccLink (LinkPtr, GetFreeList (pq)); UnlockLink (pq, hLink); SetFreeList (pq, hLink); } #endif /* QUEUE_TABLE */ void PutQueue (PQUEUE pq, HLINK hLink) { LINKPTR LinkPtr; if (GetHeadLink (pq) == 0) SetHeadLink (pq, hLink); else { HLINK hTail; LINKPTR lpTail; hTail = GetTailLink (pq); lpTail = LockLink (pq, hTail); _SetSuccLink (lpTail, hLink); UnlockLink (pq, hTail); } LinkPtr = LockLink (pq, hLink); _SetPredLink (LinkPtr, GetTailLink (pq)); _SetSuccLink (LinkPtr, NULL_HANDLE); UnlockLink (pq, hLink); SetTailLink (pq, hLink); } void InsertQueue (PQUEUE pq, HLINK hLink, HLINK hRefLink) { if (hRefLink == 0) PutQueue (pq, hLink); else { LINKPTR LinkPtr, RefLinkPtr; LinkPtr = LockLink (pq, hLink); RefLinkPtr = LockLink (pq, hRefLink); _SetPredLink (LinkPtr, _GetPredLink (RefLinkPtr)); _SetPredLink (RefLinkPtr, hLink); _SetSuccLink (LinkPtr, hRefLink); if (GetHeadLink (pq) == hRefLink) SetHeadLink (pq, hLink); else { HLINK hPredLink; LINKPTR PredLinkPtr; hPredLink = _GetPredLink (LinkPtr); PredLinkPtr = LockLink (pq, hPredLink); _SetSuccLink (PredLinkPtr, hLink); UnlockLink (pq, hPredLink); } UnlockLink (pq, hRefLink); UnlockLink (pq, hLink); } } void RemoveQueue (PQUEUE pq, HLINK hLink) { LINKPTR LinkPtr; LinkPtr = LockLink (pq, hLink); if (GetHeadLink (pq) == hLink) { SetHeadLink (pq, _GetSuccLink (LinkPtr)); } else { HLINK hPredLink; LINKPTR PredLinkPtr; hPredLink = _GetPredLink (LinkPtr); PredLinkPtr = LockLink (pq, hPredLink); _SetSuccLink (PredLinkPtr, _GetSuccLink (LinkPtr)); UnlockLink (pq, hPredLink); } if (GetTailLink (pq) == hLink) { SetTailLink (pq, _GetPredLink (LinkPtr)); } else { HLINK hSuccLink, hPredLink; LINKPTR SuccLinkPtr; hSuccLink = _GetSuccLink (LinkPtr); SuccLinkPtr = LockLink (pq, hSuccLink); hPredLink = _GetPredLink (LinkPtr); _SetPredLink (SuccLinkPtr, hPredLink); UnlockLink (pq, hSuccLink); } UnlockLink (pq, hLink); } COUNT CountLinks (PQUEUE pq) { COUNT LinkCount; HLINK hLink, hNextLink; LinkCount = 0; for (hLink = GetHeadLink (pq); hLink; hLink = hNextLink) { LINKPTR LinkPtr; ++LinkCount; LinkPtr = LockLink (pq, hLink); hNextLink = _GetSuccLink (LinkPtr); UnlockLink (pq, hLink); } return (LinkCount); } void ForAllLinks (PQUEUE pq, void (*callback)(LINKPTR, void *), void *arg) { HLINK hLink, hNextLink; for (hLink = GetHeadLink (pq); hLink; hLink = hNextLink) { LINKPTR LinkPtr; LinkPtr = LockLink (pq, hLink); hNextLink = _GetSuccLink (LinkPtr); (*callback) (LinkPtr, arg); UnlockLink (pq, hLink); } } uqm-0.6.2/sc2/src/sc2code/load.c0000600000175000017500000004151610543202101014665 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "load.h" #include "build.h" #include "declib.h" #include "encount.h" #include "file.h" #include "globdata.h" #include "load.h" #include "options.h" #include "setup.h" #include "state.h" #include "libs/tasklib.h" #include "libs/log.h" //#define DEBUG_LOAD ACTIVITY NextActivity; // XXX: these should handle endian conversions later static inline COUNT cread_8 (DECODE_REF fh, PBYTE v) { BYTE t; if (!v) /* read value ignored */ v = &t; return cread (v, 1, 1, fh); } static inline COUNT cread_16 (DECODE_REF fh, PUWORD v) { UWORD t; if (!v) /* read value ignored */ v = &t; return cread (v, 2, 1, fh); } static inline COUNT cread_32 (DECODE_REF fh, PDWORD v) { DWORD t; if (!v) /* read value ignored */ v = &t; return cread (v, 4, 1, fh); } static inline COUNT cread_ptr (DECODE_REF fh) { DWORD t; return cread_32 (fh, &t); /* ptrs are useless in saves */ } static inline COUNT cread_a8 (DECODE_REF fh, PBYTE ar, COUNT count) { assert (ar != NULL); return cread (ar, 1, count, fh) == count; } static inline COUNT read_8 (PVOID fp, PBYTE v) { BYTE t; if (!v) /* read value ignored */ v = &t; return ReadResFile (v, 1, 1, fp); } static inline COUNT read_16 (PVOID fp, PUWORD v) { UWORD t; if (!v) /* read value ignored */ v = &t; return ReadResFile (v, 2, 1, fp); } static inline COUNT read_32 (PVOID fp, PDWORD v) { DWORD t; if (!v) /* read value ignored */ v = &t; return ReadResFile (v, 4, 1, fp); } static inline COUNT read_ptr (PVOID fp) { DWORD t; return read_32 (fp, &t); /* ptrs are useless in saves */ } static inline COUNT read_a8 (PVOID fp, PBYTE ar, COUNT count) { assert (ar != NULL); return ReadResFile (ar, 1, count, fp) == count; } static inline COUNT read_a16 (PVOID fp, PUWORD ar, COUNT count) { assert (ar != NULL); for ( ; count > 0; --count, ++ar) { if (read_16 (fp, ar) != 1) return 0; } return 1; } static void LoadShipQueue (DECODE_REF fh, PQUEUE pQueue, BOOLEAN MakeQ) { COUNT num_links; cread_16 (fh, &num_links); if (num_links && MakeQ) InitQueue (pQueue, num_links, sizeof (SHIP_FRAGMENT)); while (num_links--) { HSTARSHIP hStarShip; SHIP_FRAGMENTPTR FragPtr; COUNT Index; BYTE tmpb; cread_16 (fh, &Index); if (pQueue == &GLOBAL (avail_race_q)) hStarShip = GetStarShipFromIndex (pQueue, Index); else hStarShip = CloneShipFragment (Index, pQueue, 0); FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); if (pQueue != &GLOBAL (avail_race_q)) { // queues other than avail_race_q save SHIP_FRAGMENT elements // Read SHIP_FRAGMENT elements cread_16 (fh, &FragPtr->s.Player); cread_8 (fh, &FragPtr->s.Captain); cread_8 (fh, NULL); /* padding */ } // Read SHIP_INFO elements cread_16 (fh, &FragPtr->ShipInfo.ship_flags); cread_8 (fh, &FragPtr->ShipInfo.var1); cread_8 (fh, &FragPtr->ShipInfo.var2); cread_8 (fh, &tmpb); FragPtr->ShipInfo.crew_level = tmpb; cread_8 (fh, &tmpb); FragPtr->ShipInfo.max_crew = tmpb; cread_8 (fh, &FragPtr->ShipInfo.energy_level); cread_8 (fh, &FragPtr->ShipInfo.max_energy); cread_16 (fh, &FragPtr->ShipInfo.loc.x); cread_16 (fh, &FragPtr->ShipInfo.loc.y); if (pQueue == &GLOBAL (avail_race_q)) { // avail_race_q contains information not about specific ships, // but about a race. EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr = (EXTENDED_SHIP_FRAGMENTPTR) FragPtr; cread_16 (fh, &ExtFragPtr->ShipInfo.actual_strength); cread_16 (fh, &ExtFragPtr->ShipInfo.known_strength); cread_16 (fh, &ExtFragPtr->ShipInfo.known_loc.x); cread_16 (fh, &ExtFragPtr->ShipInfo.known_loc.y); cread_8 (fh, &ExtFragPtr->ShipInfo.growth_err_term); cread_8 (fh, &ExtFragPtr->ShipInfo.func_index); cread_16 (fh, &ExtFragPtr->ShipInfo.dest_loc.x); cread_16 (fh, &ExtFragPtr->ShipInfo.dest_loc.y); cread_16 (fh, NULL); /* alignment padding */ } UnlockStarShip (pQueue, hStarShip); } } static void LoadEncounter (ENCOUNTERPTR EncounterPtr, DECODE_REF fh) { COUNT i; cread_ptr (fh); /* useless ptr; HENCOUNTER pred */ EncounterPtr->pred = 0; cread_ptr (fh); /* useless ptr; HENCOUNTER succ */ EncounterPtr->succ = 0; cread_ptr (fh); /* useless ptr; HELEMENT hElement */ EncounterPtr->hElement = 0; cread_16 (fh, &EncounterPtr->transition_state); cread_16 (fh, &EncounterPtr->origin.x); cread_16 (fh, &EncounterPtr->origin.y); cread_16 (fh, &EncounterPtr->radius); // EXTENDED_STAR_DESC fields cread_16 (fh, &EncounterPtr->SD.star_pt.x); cread_16 (fh, &EncounterPtr->SD.star_pt.y); cread_8 (fh, &EncounterPtr->SD.Type); cread_8 (fh, &EncounterPtr->SD.Index); cread_16 (fh, NULL); /* alignment padding */ // Load each entry in the SHIP_INFO array: for (i = 0; i < MAX_HYPER_SHIPS; i++) { SHIP_INFOPTR ShipInfo = &EncounterPtr->SD.ShipList[i]; BYTE tmpb; cread_16 (fh, &ShipInfo->ship_flags); cread_8 (fh, &ShipInfo->var1); cread_8 (fh, &ShipInfo->var2); cread_8 (fh, &tmpb); ShipInfo->crew_level = tmpb; cread_8 (fh, &tmpb); ShipInfo->max_crew = tmpb; cread_8 (fh, &ShipInfo->energy_level); cread_8 (fh, &ShipInfo->max_energy); cread_16 (fh, &ShipInfo->loc.x); cread_16 (fh, &ShipInfo->loc.y); cread_32 (fh, NULL); /* useless val; STRING race_strings */ ShipInfo->race_strings = 0; cread_ptr (fh); /* useless ptr; FRAME icons */ ShipInfo->icons = 0; cread_ptr (fh); /* useless ptr; FRAME melee_icon */ ShipInfo->melee_icon = 0; } // Load the stuff after the SHIP_INFO array: cread_32 (fh, &EncounterPtr->log_x); cread_32 (fh, &EncounterPtr->log_y); } static void LoadEvent (EVENTPTR EventPtr, DECODE_REF fh) { cread_ptr (fh); /* useless ptr; HEVENT pred */ EventPtr->pred = 0; cread_ptr (fh); /* useless ptr; HEVENT succ */ EventPtr->succ = 0; cread_8 (fh, &EventPtr->day_index); cread_8 (fh, &EventPtr->month_index); cread_16 (fh, &EventPtr->year_index); cread_8 (fh, &EventPtr->func_index); cread_8 (fh, NULL); /* padding */ cread_16 (fh, NULL); /* padding */ } static void DummyLoadQueue (PQUEUE QueuePtr, DECODE_REF fh) { /* QUEUE should never actually be loaded since it contains * purely internal representation and the lists * involved are actually loaded separately */ (void)QueuePtr; /* silence compiler */ /* QUEUE format with QUEUE_TABLE defined -- UQM default */ cread_ptr (fh); /* HLINK head */ cread_ptr (fh); /* HLINK tail */ cread_ptr (fh); /* PBYTE pq_tab */ cread_ptr (fh); /* HLINK free_list */ cread_16 (fh, NULL); /* MEM_HANDLE hq_tab */ cread_16 (fh, NULL); /* COUNT object_size */ cread_8 (fh, NULL); /* BYTE num_objects */ cread_8 (fh, NULL); /* padding */ cread_16 (fh, NULL); /* padding */ } static void LoadClockState (PCLOCK_STATE ClockPtr, DECODE_REF fh) { cread_8 (fh, &ClockPtr->day_index); cread_8 (fh, &ClockPtr->month_index); cread_16 (fh, &ClockPtr->year_index); cread_16 (fh, &ClockPtr->tick_count); cread_16 (fh, &ClockPtr->day_in_ticks); cread_ptr (fh); /* not loading ptr; Semaphore clock_sem */ cread_ptr (fh); /* not loading ptr; Task clock_task */ cread_32 (fh, &ClockPtr->TimeCounter); /* theoretically useless */ DummyLoadQueue (&ClockPtr->event_q, fh); } static void LoadGameState (PGAME_STATE GSPtr, DECODE_REF fh) { DWORD tmpd; cread_8 (fh, &GSPtr->cur_state); /* obsolete */ cread_8 (fh, &GSPtr->glob_flags); cread_8 (fh, &GSPtr->CrewCost); cread_8 (fh, &GSPtr->FuelCost); cread_a8 (fh, GSPtr->ModuleCost, NUM_MODULES); cread_a8 (fh, GSPtr->ElementWorth, NUM_ELEMENT_CATEGORIES); cread_ptr (fh); /* not loading ptr; PPRIMITIVE DisplayArray */ cread_16 (fh, &GSPtr->CurrentActivity); cread_16 (fh, NULL); /* CLOCK_STATE alignment padding */ LoadClockState (&GSPtr->GameClock, fh); cread_16 (fh, &GSPtr->autopilot.x); cread_16 (fh, &GSPtr->autopilot.y); cread_16 (fh, &GSPtr->ip_location.x); cread_16 (fh, &GSPtr->ip_location.y); /* STAMP ShipStamp */ cread_16 (fh, &GSPtr->ShipStamp.origin.x); cread_16 (fh, &GSPtr->ShipStamp.origin.y); cread_32 (fh, &tmpd); /* abused ptr to store DWORD */ GSPtr->ShipStamp.frame = (FRAME)tmpd; /* VELOCITY_DESC velocity */ cread_16 (fh, &GSPtr->velocity.TravelAngle); cread_16 (fh, &GSPtr->velocity.vector.width); cread_16 (fh, &GSPtr->velocity.vector.height); cread_16 (fh, &GSPtr->velocity.fract.width); cread_16 (fh, &GSPtr->velocity.fract.height); cread_16 (fh, &GSPtr->velocity.error.width); cread_16 (fh, &GSPtr->velocity.error.height); cread_16 (fh, &GSPtr->velocity.incr.width); cread_16 (fh, &GSPtr->velocity.incr.height); cread_16 (fh, NULL); /* VELOCITY_DESC padding */ cread_32 (fh, &GSPtr->BattleGroupRef); DummyLoadQueue (&GSPtr->avail_race_q, fh); DummyLoadQueue (&GSPtr->npc_built_ship_q, fh); DummyLoadQueue (&GSPtr->encounter_q, fh); DummyLoadQueue (&GSPtr->built_ship_q, fh); cread_a8 (fh, GSPtr->GameState, sizeof (GSPtr->GameState)); assert (sizeof (GSPtr->GameState) % 4 == 3); cread_8 (fh, NULL); /* GAME_STATE alignment padding */ } static BOOLEAN LoadSisState (PSIS_STATE SSPtr, PVOID fp) { if ( read_32 (fp, &SSPtr->log_x) != 1 || read_32 (fp, &SSPtr->log_y) != 1 || read_32 (fp, &SSPtr->ResUnits) != 1 || read_32 (fp, &SSPtr->FuelOnBoard) != 1 || read_16 (fp, &SSPtr->CrewEnlisted) != 1 || read_16 (fp, &SSPtr->TotalElementMass) != 1 || read_16 (fp, &SSPtr->TotalBioMass) != 1 || read_a8 (fp, SSPtr->ModuleSlots, NUM_MODULE_SLOTS) != 1 || read_a8 (fp, SSPtr->DriveSlots, NUM_DRIVE_SLOTS) != 1 || read_a8 (fp, SSPtr->JetSlots, NUM_JET_SLOTS) != 1 || read_8 (fp, &SSPtr->NumLanders) != 1 || read_a16 (fp, SSPtr->ElementAmounts, NUM_ELEMENT_CATEGORIES) != 1 || read_a8 (fp, SSPtr->ShipName, SIS_NAME_SIZE) != 1 || read_a8 (fp, SSPtr->CommanderName, SIS_NAME_SIZE) != 1 || read_a8 (fp, SSPtr->PlanetName, SIS_NAME_SIZE) != 1 || read_16 (fp, NULL) != 1 /* padding */ ) return FALSE; else return TRUE; } static BOOLEAN LoadSummary (SUMMARY_DESC *SummPtr, PVOID fp) { if (!LoadSisState (&SummPtr->SS, fp)) return FALSE; if ( read_8 (fp, &SummPtr->Activity) != 1 || read_8 (fp, &SummPtr->Flags) != 1 || read_8 (fp, &SummPtr->day_index) != 1 || read_8 (fp, &SummPtr->month_index) != 1 || read_16 (fp, &SummPtr->year_index) != 1 || read_8 (fp, &SummPtr->MCreditLo) != 1 || read_8 (fp, &SummPtr->MCreditHi) != 1 || read_8 (fp, &SummPtr->NumShips) != 1 || read_8 (fp, &SummPtr->NumDevices) != 1 || read_a8 (fp, SummPtr->ShipList, MAX_BUILT_SHIPS) != 1 || read_a8 (fp, SummPtr->DeviceList, MAX_EXCLUSIVE_DEVICES) != 1 || read_16 (fp, NULL) != 1 /* padding */ ) return FALSE; else return TRUE; } static void LoadStarDesc (STAR_DESCPTR SDPtr, DECODE_REF fh) { cread_16 (fh, &SDPtr->star_pt.x); cread_16 (fh, &SDPtr->star_pt.y); cread_8 (fh, &SDPtr->Type); cread_8 (fh, &SDPtr->Index); cread_8 (fh, &SDPtr->Prefix); cread_8 (fh, &SDPtr->Postfix); } BOOLEAN LoadGame (COUNT which_game, SUMMARY_DESC *SummPtr) { uio_Stream *in_fp; char file[PATH_MAX]; char buf[256]; SUMMARY_DESC loc_sd; GAME_STATE_FILE *fp; DECODE_REF fh; COUNT num_links; STAR_DESC SD; ACTIVITY Activity; sprintf (file, "starcon2.%02u", which_game); in_fp = res_OpenResFile (saveDir, file, "rb"); if (!in_fp) return FALSE; if (!LoadSummary (&loc_sd, in_fp)) { log_add (log_Error, "Warning: Savegame is corrupt"); res_CloseResFile (in_fp); return FALSE; } if (!SummPtr) { SummPtr = &loc_sd; } else { // only need summary for displaying to user memcpy (SummPtr, &loc_sd, sizeof (*SummPtr)); res_CloseResFile (in_fp); return TRUE; } // Crude check for big-endian/little-endian incompatibilities. // year_index is suitable as it's a multi-byte value within // a specific recognisable range. if (SummPtr->year_index < START_YEAR || SummPtr->year_index >= START_YEAR + YEARS_TO_KOHRAH_VICTORY + 1 /* Utwig intervention */ + 1 /* time to destroy all races, plenty */ + 25 /* for cheaters */) { log_add (log_Error, "Warning: Savegame corrupt or from " "an incompatible platform."); res_CloseResFile (in_fp); return FALSE; } GlobData.SIS_state = SummPtr->SS; if ((fh = copen (in_fp, FILE_STREAM, STREAM_READ)) == 0) { res_CloseResFile (in_fp); return FALSE; } ReinitQueue (&GLOBAL (GameClock.event_q)); ReinitQueue (&GLOBAL (encounter_q)); ReinitQueue (&GLOBAL (npc_built_ship_q)); ReinitQueue (&GLOBAL (built_ship_q)); memset (&GLOBAL (GameState[0]), 0, sizeof (GLOBAL (GameState))); Activity = GLOBAL (CurrentActivity); LoadGameState (&GlobData.Game_state, fh); NextActivity = GLOBAL (CurrentActivity); GLOBAL (CurrentActivity) = Activity; // It shouldn't be possible to ever save with TimeCounter != 0 // But if it does happen, it needs to be reset to 0, since on load // the clock semaphore is gauranteed to be 0 if (GLOBAL (GameClock.TimeCounter) != 0) log_add (log_Warning, "Warning: Game clock wasn't stopped during " "save, Savegame may be corrupt!\n"); GLOBAL (GameClock.TimeCounter) = 0; LoadShipQueue (fh, &GLOBAL (avail_race_q), FALSE); if (!(NextActivity & START_INTERPLANETARY)) LoadShipQueue (fh, &GLOBAL (npc_built_ship_q), FALSE); LoadShipQueue (fh, &GLOBAL (built_ship_q), FALSE); // Load the game events (compressed) cread_16 (fh, &num_links); { #ifdef DEBUG_LOAD log_add (log_Debug, "EVENTS:"); #endif /* DEBUG_LOAD */ while (num_links--) { HEVENT hEvent; EVENTPTR EventPtr; hEvent = AllocEvent (); LockEvent (hEvent, &EventPtr); LoadEvent (EventPtr, fh); #ifdef DEBUG_LOAD log_add (log_Debug, "\t%u/%u/%u -- %u", EventPtr->month_index, EventPtr->day_index, EventPtr->year_index, EventPtr->func_index); #endif /* DEBUG_LOAD */ UnlockEvent (hEvent); PutEvent (hEvent); } } // Load the encounters (black globes in HS/QS (compressed)) cread_16 (fh, &num_links); { while (num_links--) { BYTE i, NumShips; HENCOUNTER hEncounter; ENCOUNTERPTR EncounterPtr; hEncounter = AllocEncounter (); LockEncounter (hEncounter, &EncounterPtr); LoadEncounter (EncounterPtr, fh); NumShips = LONIBBLE (EncounterPtr->SD.Index); for (i = 0; i < NumShips; ++i) { HSTARSHIP hStarShip; SHIP_FRAGMENTPTR TemplatePtr; hStarShip = GetStarShipFromIndex ( &GLOBAL (avail_race_q), EncounterPtr->SD.ShipList[i].var1); TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip); EncounterPtr->SD.ShipList[i].race_strings = TemplatePtr->ShipInfo.race_strings; EncounterPtr->SD.ShipList[i].icons = TemplatePtr->ShipInfo.icons; EncounterPtr->SD.ShipList[i].melee_icon = TemplatePtr->ShipInfo.melee_icon; UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } UnlockEncounter (hEncounter); PutEncounter (hEncounter); } } // Copy the star info file from the compressed stream fp = OpenStateFile (STARINFO_FILE, "wb"); if (fp) { DWORD flen; cread_32 (fh, &flen); while (flen) { COUNT num_bytes; num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; cread (buf, num_bytes, 1, fh); WriteStateFile (buf, num_bytes, 1, fp); flen -= num_bytes; } CloseStateFile (fp); } // Copy the defined groupinfo file from the compressed stream fp = OpenStateFile (DEFGRPINFO_FILE, "wb"); if (fp) { DWORD flen; cread_32 (fh, &flen); while (flen) { COUNT num_bytes; num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; cread (buf, num_bytes, 1, fh); WriteStateFile (buf, num_bytes, 1, fp); flen -= num_bytes; } CloseStateFile (fp); } // Copy the random groupinfo file from the compressed stream fp = OpenStateFile (RANDGRPINFO_FILE, "wb"); if (fp) { DWORD flen; cread_32 (fh, &flen); while (flen) { COUNT num_bytes; num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; cread (buf, num_bytes, 1, fh); WriteStateFile (buf, num_bytes, 1, fp); flen -= num_bytes; } CloseStateFile (fp); } LoadStarDesc (&SD, fh); cclose (fh); res_CloseResFile (in_fp); EncounterGroup = 0; EncounterRace = -1; ReinitQueue (&race_q[0]); ReinitQueue (&race_q[1]); CurStarDescPtr = FindStar (NULL, &SD.star_pt, 0, 0); if (!(NextActivity & START_ENCOUNTER) && LOBYTE (NextActivity) == IN_INTERPLANETARY) NextActivity |= START_INTERPLANETARY; return TRUE; } uqm-0.6.2/sc2/src/sc2code/menustat.h0000700000175000017500000000251610543202103015613 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MENUSTAT_H #define _MENUSTAT_H #include "libs/gfxlib.h" #include "libs/sndlib.h" #include "libs/tasklib.h" typedef struct menu_state { BOOLEAN (*InputFunc) (struct menu_state *pMS); COUNT MenuRepeatDelay; SIZE Initialized; BYTE CurState; FRAME CurFrame; STRING CurString; POINT first_item; SIZE delta_item; FRAME ModuleFrame; Task flash_task; RECT flash_rect0, flash_rect1; FRAME flash_frame0, flash_frame1; MUSIC_REF hMusic; void *Extra; } MENU_STATE; typedef MENU_STATE *PMENU_STATE; extern PMENU_STATE pMenuState; #endif /* _MENUSTAT_H */ uqm-0.6.2/sc2/src/sc2code/globdata.c0000600000175000017500000002575710543202103015536 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "globdata.h" #include "coderes.h" #include "encount.h" #include "master.h" #include "setup.h" #include "resinst.h" #include "nameref.h" #include "build.h" #include "state.h" #include "gamestr.h" #include #ifdef STATE_DEBUG # include "libs/log.h" #endif static void CreateRadar (void); CONTEXT RadarContext; FRAME PlayFrame; GLOBDATA GlobData; BOOLEAN initedSIS = 0; BYTE getGameState (int startBit, int endBit) { return (BYTE) (((startBit >> 3) == (endBit >> 3) ? (GLOBAL (GameState[startBit >> 3]) >> (startBit & 7)) : ((GLOBAL (GameState[startBit >> 3]) >> (startBit & 7)) | (GLOBAL (GameState[endBit >> 3]) << (endBit - startBit - (endBit & 7))))) & ((1 << (endBit - startBit + 1)) - 1)); } void setGameState (int startBit, int endBit, BYTE val #ifdef STATE_DEBUG , const char *name #endif ) { GLOBAL (GameState[startBit >> 3]) = (GLOBAL (GameState[startBit >> 3]) & (BYTE) ~(((1 << (endBit - startBit + 1)) - 1) << (startBit & 7))) | (BYTE)((val) << (startBit & 7)); if ((startBit >> 3) < (endBit >> 3)) { GLOBAL (GameState[endBit >> 3]) = (GLOBAL (GameState[endBit >> 3]) & (BYTE)~((1 << ((endBit & 7) + 1)) - 1)) | (BYTE)((val) >> (endBit - startBit - (endBit & 7))); } #ifdef STATE_DEBUG log_add (log_Debug, "State '%s' set to %d.", name, (int)val); #endif } DWORD getGameState32 (int startBit) { DWORD v; int shift; for (v = 0, shift = 0; shift < 32; shift += 8, startBit += 8) { v |= getGameState (startBit, startBit + 7) << shift; } return v; } void setGameState32 (int startBit, DWORD val #ifdef STATE_DEBUG , const char *name #endif ) { DWORD v = val; int i; for (i = 0; i < 4; ++i, v >>= 8, startBit += 8) { setGameState (startBit, startBit + 7, v & 0xff #ifdef STATE_DEBUG , "(ignored)" #endif ); } #ifdef STATE_DEBUG log_add (log_Debug, "State '%s' set to %u.", name, (unsigned)val); #endif } static void CreateRadar (void) { if (RadarContext == 0) { RECT r; CONTEXT OldContext; RadarContext = CaptureContext (CreateContext ()); OldContext = SetContext (RadarContext); SetContextFGFrame (Screen); r.corner.x = RADAR_X; r.corner.y = RADAR_Y; r.extent.width = RADAR_WIDTH; r.extent.height = RADAR_HEIGHT; SetContextClipRect (&r); SetContext (OldContext); } } BOOLEAN LoadSC2Data (void) { if (FlagStatFrame == 0) { MEM_HANDLE hOldIndex; hOldIndex = SetResourceIndex (hResIndex); FlagStatFrame = CaptureDrawable ( LoadGraphic (FLAGSTAT_MASK_PMAP_ANIM)); if (FlagStatFrame == NULL) return FALSE; MiscDataFrame = CaptureDrawable ( LoadGraphic (MISCDATA_MASK_PMAP_ANIM)); if (MiscDataFrame == NULL) return FALSE; FontGradFrame = CaptureDrawable ( LoadGraphic (FONTGRAD_PMAP_ANIM)); SetResourceIndex (hOldIndex); } CreateRadar (); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { GLOBAL (ShipStamp.origin.x) = GLOBAL (ShipStamp.origin.y) = -1; } return TRUE; } BOOLEAN InitSIS (void) { COUNT i; InitGlobData (); PlayFrame = CaptureDrawable (LoadGraphic (PLAYMENU_ANIM)); { COUNT num_ships; RES_TYPE rt; RES_INSTANCE ri; RES_PACKAGE rp; rt = GET_TYPE (ARILOU_SHIP_INDEX); ri = GET_INSTANCE (ARILOU_SHIP_INDEX); rp = GET_PACKAGE (ARILOU_SHIP_INDEX); num_ships = (GET_PACKAGE (BLACKURQ_SHIP_INDEX) - rp + 1) + 2; /* Yehat Rebels and Ur-Quan probe */ InitQueue (&GLOBAL (avail_race_q), num_ships, sizeof (EXTENDED_SHIP_FRAGMENT)); for (i = 0; i < num_ships; ++i) { DWORD ship_ref; HSTARSHIP hStarShip; if (i < num_ships - 2) ship_ref = MAKE_RESOURCE (rp++, rt, ri++); else if (i == num_ships - 2) ship_ref = YEHAT_SHIP_INDEX; else /* (i == num_ships - 1) */ ship_ref = PROBE_RES_INDEX; hStarShip = Build (&GLOBAL (avail_race_q), ship_ref, 0, 0); if (hStarShip) { SHIP_FRAGMENTPTR FragPtr; EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip); if (i < num_ships - 1) { HSTARSHIP hMasterShip; STARSHIPPTR MasterShipPtr; hMasterShip = FindMasterShip (ship_ref); MasterShipPtr = LockStarShip (&master_q, hMasterShip); FragPtr->ShipInfo = ((SHIP_FRAGMENTPTR)MasterShipPtr)->ShipInfo; UnlockStarShip (&master_q, hMasterShip); } else { // Ur-Quan probe. load_ship ((STARSHIPPTR)FragPtr, FALSE); FragPtr->ShipInfo = FragPtr->RaceDescPtr->ship_info; FragPtr->RaceDescPtr->ship_info.melee_icon = 0; FragPtr->RaceDescPtr->ship_info.icons = 0; FragPtr->RaceDescPtr->ship_info.race_strings = 0; free_ship ((STARSHIPPTR)FragPtr, FALSE); } FragPtr->ShipInfo.ship_flags = BAD_GUY; ExtFragPtr = (EXTENDED_SHIP_FRAGMENTPTR)FragPtr; ExtFragPtr->ShipInfo.known_strength = 0; ExtFragPtr->ShipInfo.known_loc = ExtFragPtr->ShipInfo.loc; if (FragPtr->ShipInfo.var2 == (BYTE)~0) ExtFragPtr->ShipInfo.actual_strength = (COUNT)~0; else if (i == YEHAT_REBEL_SHIP) ExtFragPtr->ShipInfo.actual_strength = 0; else ExtFragPtr->ShipInfo.actual_strength = (COUNT)FragPtr->ShipInfo.var2 << 1; ExtFragPtr->ShipInfo.growth_fract = 0; ExtFragPtr->ShipInfo.growth_err_term = 255 >> 1; ExtFragPtr->ShipInfo.energy_level = 0; ExtFragPtr->ShipInfo.days_left = 0; FragPtr->RaceDescPtr = (RACE_DESCPTR)&ExtFragPtr->ShipInfo; UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } } } InitSISContexts (); LoadSC2Data (); InitPlanetInfo (); InitGroupInfo (TRUE); GLOBAL (glob_flags) = NUM_READ_SPEEDS >> 1; GLOBAL (ElementWorth[COMMON]) = 1; GLOBAL_SIS (ElementAmounts[COMMON]) = 0; GLOBAL (ElementWorth[CORROSIVE]) = 2; GLOBAL_SIS (ElementAmounts[CORROSIVE]) = 0; GLOBAL (ElementWorth[BASE_METAL]) = 3; GLOBAL_SIS (ElementAmounts[BASE_METAL]) = 0; GLOBAL (ElementWorth[NOBLE]) = 4; GLOBAL_SIS (ElementAmounts[NOBLE]) = 0; GLOBAL (ElementWorth[RARE_EARTH]) = 5; GLOBAL_SIS (ElementAmounts[RARE_EARTH]) = 0; GLOBAL (ElementWorth[PRECIOUS]) = 6; GLOBAL_SIS (ElementAmounts[PRECIOUS]) = 0; GLOBAL (ElementWorth[RADIOACTIVE]) = 8; GLOBAL_SIS (ElementAmounts[RADIOACTIVE]) = 0; GLOBAL (ElementWorth[EXOTIC]) = 25; GLOBAL_SIS (ElementAmounts[EXOTIC]) = 0; for (i = 0; i < NUM_DRIVE_SLOTS; ++i) GLOBAL_SIS (DriveSlots[i]) = EMPTY_SLOT + 0; GLOBAL_SIS (DriveSlots[5]) = GLOBAL_SIS (DriveSlots[6]) = FUSION_THRUSTER; for (i = 0; i < NUM_JET_SLOTS; ++i) GLOBAL_SIS (JetSlots[i]) = EMPTY_SLOT + 1; GLOBAL_SIS (JetSlots[0]) = GLOBAL_SIS (JetSlots[6]) = TURNING_JETS; for (i = 0; i < NUM_MODULE_SLOTS; ++i) GLOBAL_SIS (ModuleSlots[i]) = EMPTY_SLOT + 2; GLOBAL_SIS (ModuleSlots[15]) = GUN_WEAPON; GLOBAL_SIS (ModuleSlots[2]) = CREW_POD; GLOBAL_SIS (CrewEnlisted) = CREW_POD_CAPACITY; GLOBAL_SIS (ModuleSlots[8]) = STORAGE_BAY; GLOBAL_SIS (ModuleSlots[1]) = FUEL_TANK; GLOBAL_SIS (FuelOnBoard) = 10 * FUEL_TANK_SCALE; InitQueue (&GLOBAL (built_ship_q), MAX_BUILT_SHIPS, sizeof (SHIP_FRAGMENT)); InitQueue (&GLOBAL (npc_built_ship_q), (MAX_BATTLE_GROUPS >> 1), sizeof (SHIP_FRAGMENT)); InitQueue (&GLOBAL (encounter_q), 16, sizeof (ENCOUNTER)); GLOBAL (CurrentActivity) = IN_INTERPLANETARY | START_INTERPLANETARY; GLOBAL_SIS (ResUnits) = 0; GLOBAL (CrewCost) = 3; GLOBAL (FuelCost) = 20; GLOBAL (ModuleCost[PLANET_LANDER]) = 500 / MODULE_COST_SCALE; GLOBAL (ModuleCost[FUSION_THRUSTER]) = 500 / MODULE_COST_SCALE; GLOBAL (ModuleCost[TURNING_JETS]) = 500 / MODULE_COST_SCALE; GLOBAL (ModuleCost[CREW_POD]) = 2000 / MODULE_COST_SCALE; GLOBAL (ModuleCost[STORAGE_BAY]) = 750 / MODULE_COST_SCALE; GLOBAL (ModuleCost[FUEL_TANK]) = 500 / MODULE_COST_SCALE; GLOBAL (ModuleCost[DYNAMO_UNIT]) = 2000 / MODULE_COST_SCALE; GLOBAL (ModuleCost[GUN_WEAPON]) = 2000 / MODULE_COST_SCALE; GLOBAL_SIS (NumLanders) = 1; utf8StringCopy (GLOBAL_SIS (ShipName), sizeof (GLOBAL_SIS (ShipName)), GAME_STRING (NAMING_STRING_BASE + 2)); utf8StringCopy (GLOBAL_SIS (CommanderName), sizeof (GLOBAL_SIS (CommanderName)), GAME_STRING (NAMING_STRING_BASE + 3)); ActivateStarShip (HUMAN_SHIP, 0); CloneShipFragment (HUMAN_SHIP, &GLOBAL (built_ship_q), 0); GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (SOL_X); GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (SOL_Y); CurStarDescPtr = 0; GLOBAL (autopilot.x) = GLOBAL (autopilot.y) = ~0; /* In case the program is exited before the full game is terminated, * make sure that the temporary files are deleted. * This can be removed if we make sure if the full game is terminated * before the game is exited. * The initedSIS variable is added so the uninit won't happen more * than once, as you can't remove the atexit function (when the full game * ends). */ initedSIS = TRUE; atexit (UninitSIS); return (TRUE); } void FreeSC2Data (void) { DestroyContext (ReleaseContext (RadarContext)); RadarContext = 0; DestroyDrawable (ReleaseDrawable (FontGradFrame)); FontGradFrame = 0; DestroyDrawable (ReleaseDrawable (MiscDataFrame)); MiscDataFrame = 0; DestroyDrawable (ReleaseDrawable (FlagStatFrame)); FlagStatFrame = 0; } void UninitSIS (void) { HSTARSHIP hStarShip; if (!initedSIS) return; UninitQueue (&GLOBAL (encounter_q)); UninitQueue (&GLOBAL (npc_built_ship_q)); UninitQueue (&GLOBAL (built_ship_q)); UninitGroupInfo (); UninitPlanetInfo (); // FreeSC2Data (); hStarShip = GetTailLink (&GLOBAL (avail_race_q)); if (hStarShip) { STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip (&GLOBAL (avail_race_q), hStarShip); DestroyDrawable (ReleaseDrawable ( StarShipPtr->RaceDescPtr->ship_info.melee_icon)); DestroyDrawable (ReleaseDrawable ( StarShipPtr->RaceDescPtr->ship_info.icons)); DestroyStringTable (ReleaseStringTable ( StarShipPtr->RaceDescPtr->ship_info.race_strings)); UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } UninitQueue (&GLOBAL (avail_race_q)); DestroyDrawable (ReleaseDrawable (PlayFrame)); PlayFrame = 0; initedSIS = FALSE; } void InitGlobData (void) { COUNT i; i = GLOBAL (glob_flags); memset ((PBYTE)&GlobData, 0, sizeof (GlobData)); GLOBAL (glob_flags) = (BYTE)i; GLOBAL (DisplayArray) = DisplayArray; // The clock semaphore was initially initialized as '1' // but it is always cleared before set, so it toggled between // 2 and 1, which doesn't actually do anything. GLOBAL (GameClock.clock_sem) = CreateSemaphore(0, "Clock", SYNC_CLASS_TOPLEVEL); } uqm-0.6.2/sc2/src/sc2code/ires_ind.h0000600000175000017500000000377510543202102015555 0ustar joeyjoey#define ARILOU_SHIP_INDEX 0x00600007L #define CHMMR_SHIP_INDEX 0x00800107L #define EARTHLING_SHIP_INDEX 0x00a00207L #define ORZ_SHIP_INDEX 0x00c00307L #define PKUNK_SHIP_INDEX 0x00e00407L #define SHOFIXTI_SHIP_INDEX 0x01000507L #define SPATHI_SHIP_INDEX 0x01200607L #define SUPOX_SHIP_INDEX 0x01400707L #define THRADD_SHIP_INDEX 0x01600807L #define UTWIG_SHIP_INDEX 0x01800907L #define VUX_SHIP_INDEX 0x01a00a07L #define YEHAT_SHIP_INDEX 0x01c00b07L #define MELNORME_SHIP_INDEX 0x01e00c07L #define DRUUGE_SHIP_INDEX 0x02000d07L #define ILWRATH_SHIP_INDEX 0x02200e07L #define MYCON_SHIP_INDEX 0x02400f07L #define SLYLANDRO_SHIP_INDEX 0x02601007L #define UMGAH_SHIP_INDEX 0x02801107L #define URQUAN_SHIP_INDEX 0x02a01207L #define ZOQFOTPIK_SHIP_INDEX 0x02c01307L #define SYREEN_SHIP_INDEX 0x02e01407L #define BLACKURQ_SHIP_INDEX 0x03001507L #define ANDROSYN_SHIP_INDEX 0x03201607L #define CHENJESU_SHIP_INDEX 0x03401707L #define MMRNMHRM_SHIP_INDEX 0x03601807L #define ARILOU_CONVERSATION 0x14a01907L #define CHMMR_CONVERSATION 0x14c01a07L #define COMMANDER_CONVERSATION 0x14e01b07L #define ORZ_CONVERSATION 0x15001c07L #define PKUNK_CONVERSATION 0x15201d07L #define SHOFIXTI_CONVERSATION 0x15401e07L #define SPATHI_CONVERSATION 0x15601f07L #define SUPOX_CONVERSATION 0x15802007L #define THRADD_CONVERSATION 0x15a02107L #define UTWIG_CONVERSATION 0x15c02207L #define VUX_CONVERSATION 0x15e02307L #define YEHAT_CONVERSATION 0x16002407L #define MELNORME_CONVERSATION 0x16202507L #define DRUUGE_CONVERSATION 0x16402607L #define ILWRATH_CONVERSATION 0x16602707L #define MYCON_CONVERSATION 0x16802807L #define SLYLANDRO_CONVERSATION 0x16a02907L #define UMGAH_CONVERSATION 0x16c02a07L #define URQUAN_CONVERSATION 0x16e02b07L #define ZOQFOTPIK_CONVERSATION 0x17002c07L #define SYREEN_CONVERSATION 0x17202d07L #define BLACKURQ_CONVERSATION 0x17402e07L #define TALKING_PET_CONVERSATION 0x17602f07L #define SLYLANDRO_HOME_CONVERSATION 0x17803007L #define SIS_RES_INDEX 0x17c03107L #define SAMATRA_RES_INDEX 0x17e03207L #define PROBE_RES_INDEX 0x18003307L uqm-0.6.2/sc2/src/sc2code/state.h0000600000175000017500000000660010543202101015066 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STATE_H #define _STATE_H #include "port.h" #include "libs/compiler.h" #include extern void InitPlanetInfo (void); extern void UninitPlanetInfo (void); extern void GetPlanetInfo (void); extern void PutPlanetInfo (void); extern void InitGroupInfo (BOOLEAN FirstTime); extern void UninitGroupInfo (void); extern BOOLEAN GetGroupInfo (DWORD offset, BYTE which_group); extern DWORD PutGroupInfo (DWORD offset, BYTE which_group); #define GROUPS_RANDOM ((DWORD)(0L)) #define GROUPS_ADD_NEW ((DWORD)(~0L)) #define GROUP_LIST ((BYTE)0) #define GROUP_INIT_IP ((BYTE)~0) #define GROUP_LOAD_IP GROUP_LIST #define GROUP_SAVE_IP ((BYTE)~0) extern void BuildGroups (void); #define MAX_DESC_CHARS 60 typedef UNICODE GAME_DESC[MAX_DESC_CHARS + 1]; typedef struct GAME_STATE_FILE GAME_STATE_FILE; #define STARINFO_FILE 0 //"starinfo.dat" #define STAR_BUFSIZE (NUM_SOLAR_SYSTEMS * sizeof (DWORD) \ + 3800 * (3 * sizeof (DWORD))) #define RANDGRPINFO_FILE 1 //"randgrp.dat" #define RAND_BUFSIZE (4 * 1024) #define DEFGRPINFO_FILE 2 //"defgrp.dat" #define DEF_BUFSIZE (10 * 1024) typedef enum { STARINFO, RANDGRPINFO, DEFGRPINFO } INFO_TYPE; GAME_STATE_FILE* OpenStateFile (int stateFile, const char *mode); void CloseStateFile (GAME_STATE_FILE *fp); void DeleteStateFile (int stateFile); DWORD LengthStateFile (GAME_STATE_FILE *fp); int ReadStateFile (PVOID lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp); int WriteStateFile (PVOID lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp); int SeekStateFile (GAME_STATE_FILE *fp, long offset, int whence); static inline COUNT sread_8 (PVOID fp, PBYTE v) { BYTE t; if (!v) /* read value ignored */ v = &t; return ReadStateFile (v, 1, 1, fp); } static inline COUNT sread_16 (PVOID fp, PUWORD v) { UWORD t; if (!v) /* read value ignored */ v = &t; return ReadStateFile (v, 2, 1, fp); } static inline COUNT sread_32 (PVOID fp, PDWORD v) { DWORD t; if (!v) /* read value ignored */ v = &t; return ReadStateFile (v, 4, 1, fp); } static inline COUNT sread_a32 (PVOID fp, PDWORD ar, COUNT count) { assert (ar != NULL); for ( ; count > 0; --count, ++ar) { if (sread_32 (fp, ar) != 1) return 0; } return 1; } static inline COUNT swrite_8 (PVOID fp, BYTE v) { return WriteStateFile (&v, 1, 1, fp); } static inline COUNT swrite_16 (PVOID fp, UWORD v) { return WriteStateFile (&v, 2, 1, fp); } static inline COUNT swrite_32 (PVOID fp, DWORD v) { return WriteStateFile (&v, 4, 1, fp); } static inline COUNT swrite_a32 (PVOID fp, PDWORD ar, COUNT count) { for ( ; count > 0; --count, ++ar) { if (swrite_32 (fp, *ar) != 1) return 0; } return 1; } #endif /* _STATE_H */ uqm-0.6.2/sc2/src/sc2code/hyper.h0000600000175000017500000000163110543202101015074 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _HYPER_H #define _HYPER_H extern void FreeHyperData (void); extern void check_hyperspace_encounter (void); #endif /* _HYPER_H */ uqm-0.6.2/sc2/src/sc2code/gameopt.h0000600000175000017500000000163710543202101015407 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _GAMEOPT_H #define _GAMEOPT_H #include "compiler.h" #include "libs/gfxlib.h" extern void ConfirmSaveLoad (STAMP *MsgStamp); extern BOOLEAN GameOptions (void); #endif /* _GAMEOPT_H */ uqm-0.6.2/sc2/src/sc2code/credits.c0000600000175000017500000004241210543202103015401 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "credits.h" #include "controls.h" #include "encount.h" #include "options.h" #include "oscill.h" #include "comm.h" #include "resinst.h" #include "nameref.h" #include "settings.h" #include "sounds.h" #include "setup.h" #include "libs/graphics/gfx_common.h" #include "libs/sound/sound.h" #include // Rates in pixel lines per second #define CREDITS_BASE_RATE 9 #define CREDITS_MAX_RATE 130 // Maximum frame rate #define CREDITS_FRAME_RATE 36 #define CREDITS_TIMEOUT (ONE_SECOND * 5) static volatile int CreditsRate; static volatile BOOLEAN OutTakesRunning; static volatile BOOLEAN CreditsRunning; static STRING CreditsTab; static FRAME CreditsBack; typedef struct { int size; DWORD res; FONT font; } FONT_SIZE_DEF; static FONT_SIZE_DEF CreditsFont[] = { { 13, PT13AA_FONT, 0 }, { 17, PT17AA_FONT, 0 }, { 45, PT45AA_FONT, 0 }, { 0, 0, 0 }, }; static FRAME Credits_MakeTextFrame (int w, int h, COLOR TransColor) { FRAME OldFrame; FRAME f; f = CaptureDrawable (CreateDrawable (WANT_PIXMAP, w, h, 1)); SetFrameTransparentColor (f, TransColor); OldFrame = SetContextFGFrame (f); SetContextBackGroundColor (TransColor); ClearDrawable (); SetContextFGFrame (OldFrame); return f; } static int ParseTextLines (TEXT *Lines, int MaxLines, char *Buffer) { int i; const char* pEnd = Buffer + strlen (Buffer); for (i = 0; i < MaxLines && Buffer < pEnd; ++i, ++Lines) { char* pTerm = strchr (Buffer, '\n'); if (!pTerm) pTerm = Buffer + strlen (Buffer); *pTerm = '\0'; /* terminate string */ Lines->pStr = Buffer; Lines->CharCount = ~0; Buffer = pTerm + 1; } return i; } #define MAX_TEXT_LINES 50 #define MAX_TEXT_COLS 5 static FRAME Credits_RenderTextFrame (CONTEXT TempContext, int *istr, int dir, COLOR BackColor, COLOR ForeColor) { FRAME f; CONTEXT OldContext; FRAME OldFrame; TEXT TextLines[MAX_TEXT_LINES]; STRINGPTR pStr = NULL; int size; char salign[32]; char *scol; int scaned; int i, rows, cnt; char buf[2048]; FONT_SIZE_DEF *fdef; SIZE leading; TEXT t; RECT r; typedef struct { TEXT_ALIGN align; COORD basex; } col_format_t; col_format_t colfmt[MAX_TEXT_COLS]; if (*istr < 0 || *istr >= GetStringTableCount (CreditsTab)) { // check if next one is within range int next_s = *istr + dir; if (next_s < 0 || next_s >= GetStringTableCount (CreditsTab)) return 0; *istr = next_s; } // skip empty lines while (*istr >= 0 && *istr < GetStringTableCount (CreditsTab)) { pStr = GetStringAddress ( SetAbsStringTableIndex (CreditsTab, *istr)); *istr += dir; if (pStr && *pStr != '\0') break; } if (!pStr || *pStr == '\0') return 0; if (2 != sscanf (pStr, "%d %31s %n", &size, salign, &scaned) || size <= 0) return 0; pStr += scaned; utf8StringCopy (buf, sizeof (buf), pStr); rows = ParseTextLines (TextLines, MAX_TEXT_LINES, buf); if (rows == 0) return 0; // parse text columns for (i = 0, cnt = rows; i < rows; ++i) { char *nextcol; int icol; // we abuse the baseline here, but only a tiny bit // every line starts at col 0 TextLines[i].baseline.x = 0; TextLines[i].baseline.y = i + 1; for (icol = 1, nextcol = strchr (TextLines[i].pStr, '\t'); icol < MAX_TEXT_COLS && nextcol; ++icol, nextcol = strchr (nextcol, '\t')) { *nextcol = '\0'; ++nextcol; if (cnt < MAX_TEXT_LINES) { TextLines[cnt].pStr = nextcol; TextLines[cnt].CharCount = ~0; TextLines[cnt].baseline.x = icol; TextLines[cnt].baseline.y = i + 1; ++cnt; } } } // init alignments for (i = 0; i < MAX_TEXT_COLS; ++i) { colfmt[i].align = ALIGN_LEFT; colfmt[i].basex = SCREEN_WIDTH / 64; } // find the right font for (fdef = CreditsFont; fdef->size && size > fdef->size; ++fdef) ; if (!fdef->size) return 0; t.align = ALIGN_LEFT; t.baseline.x = 100; // any value will do t.baseline.y = 100; // any value will do t.pStr = " "; t.CharCount = 1; LockMutex (GraphicsLock); OldContext = SetContext (TempContext); // get font dimensions SetContextFont (fdef->font); GetContextFontLeading (&leading); // get left/right margin TextRect (&t, &r, NULL_PTR); // parse text column alignment for (i = 0, scol = strtok (salign, ","); scol && i < MAX_TEXT_COLS; ++i, scol = strtok (NULL, ",")) { char c; int x; int n; // default colfmt[i].align = ALIGN_LEFT; colfmt[i].basex = r.extent.width; n = sscanf (scol, "%c/%d", &c, &x); if (n < 1) { // DOES NOT COMPUTE! :) continue; } switch (c) { case 'L': colfmt[i].align = ALIGN_LEFT; if (n >= 2) colfmt[i].basex = x; break; case 'C': colfmt[i].align = ALIGN_CENTER; if (n >= 2) colfmt[i].basex = x; else colfmt[i].basex = SCREEN_WIDTH / 2; break; case 'R': colfmt[i].align = ALIGN_RIGHT; if (n >= 2) colfmt[i].basex = x; else colfmt[i].basex = SCREEN_WIDTH - r.extent.width; break; } } for (i = 0; i < cnt; ++i) { // baseline contains coords in row/col quantities col_format_t *fmt = colfmt + TextLines[i].baseline.x; TextLines[i].align = fmt->align; TextLines[i].baseline.x = fmt->basex; TextLines[i].baseline.y *= leading; } f = Credits_MakeTextFrame (SCREEN_WIDTH, leading * rows + (leading >> 1), BackColor); OldFrame = SetContextFGFrame (f); // draw text SetContextForeGroundColor (ForeColor); for (i = 0; i < cnt; ++i) font_DrawText (TextLines + i); SetContextFGFrame (OldFrame); SetContext (OldContext); UnlockMutex (GraphicsLock); return f; } #define CREDIT_FRAMES 32 static int credit_roll_task (void *data) { Task task = (Task) data; CONTEXT OldContext; DWORD TimeIn; CONTEXT DrawContext; CONTEXT LocalContext; FRAME Frame; COLOR TransColor, TextFore, TextBack; STAMP TaskStamp; STAMP s; FRAME cf[CREDIT_FRAMES]; // preped text frames int ci[CREDIT_FRAMES]; // strtab indices int first = 0, last; int dy = 0, total_h, disp_h, deficit_h = 0; int strcnt; CreditsRunning = TRUE; memset(cf, 0, sizeof(cf)); strcnt = GetStringTableCount (CreditsTab); TransColor = BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x10), 0x01); TextBack = BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00); TextFore = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F); LocalContext = CaptureContext (CreateContext ()); DrawContext = CaptureContext (CreateContext ()); total_h = disp_h = SCREEN_HEIGHT; LockMutex (GraphicsLock); // prep our local context OldContext = SetContext (LocalContext); // prep the first frame cf[0] = Credits_MakeTextFrame (1, total_h, TransColor); ci[0] = -1; last = 1; // prep the local screen copy Frame = Credits_MakeTextFrame (SCREEN_WIDTH, disp_h, TransColor); SetContextFGFrame (Frame); // prep our task context SetContext (DrawContext); SetContextFGFrame (Screen); SetContext (OldContext); UnlockMutex (GraphicsLock); TaskStamp.origin.x = TaskStamp.origin.y = 0; TaskStamp.frame = Frame; // stary background is the first screen frame LockMutex (GraphicsLock); OldContext = SetContext (LocalContext); // draw s.origin.x = s.origin.y = 0; s.frame = CreditsBack; DrawStamp (&s); // draw clipped rect, if any if (OutTakesRunning) { SetContextForeGroundColor (TransColor); DrawFilledRectangle (&CommWndRect); } SetContext (OldContext); UnlockMutex (GraphicsLock); while (!Task_ReadState (task, TASK_EXIT)) { RECT fr; int i; int rate, direction, dirstep; TimeIn = GetTimeCounter (); rate = abs (CreditsRate); if (rate != 0) { // scroll direction; forward or backward direction = CreditsRate / rate; // step in pixels dirstep = (rate + CREDITS_FRAME_RATE - 1) / CREDITS_FRAME_RATE; rate = ONE_SECOND * dirstep / rate; // step is also directional dirstep *= direction; } else { // scroll stopped direction = 0; dirstep = 0; // one second interframe rate = ONE_SECOND; } // draw the credits // comm animations play with contexts so we need to make // sure the context is not desynced LockMutex (GraphicsLock); OldContext = SetContext (DrawContext); DrawStamp (&TaskStamp); SetContext (OldContext); FlushGraphics (); UnlockMutex (GraphicsLock); // prepare next screen frame dy += dirstep; // cap scroll if (dy < -(disp_h / 20)) { // at the begining // accelerated slow down if (CreditsRate < 0) CreditsRate -= CreditsRate / 10 - 1; } else if (deficit_h > disp_h / 25) { // frame deficit -- task almost over // accelerated slow down if (CreditsRate > 0) CreditsRate -= CreditsRate / 10 + 1; CreditsRunning = (CreditsRate != 0); } else if (!CreditsRunning) { // resumed CreditsRunning = TRUE; } if (first != last) { // clean up frames that scrolled off the screen if (direction > 0) { // forward scroll GetFrameRect (cf[first], &fr); if (dy >= (int)fr.extent.height) { // past this frame already total_h -= fr.extent.height; DestroyDrawable (ReleaseDrawable (cf[first])); cf[first] = 0; // next frame first = (first + 1) % CREDIT_FRAMES; dy = 0; } } else if (direction < 0) { // backward scroll int index = (last - 1 + CREDIT_FRAMES) % CREDIT_FRAMES; GetFrameRect (cf[index], &fr); if (total_h - dy - (int)fr.extent.height >= disp_h) { // past this frame already last = index; total_h -= fr.extent.height; DestroyDrawable (ReleaseDrawable (cf[last])); cf[last] = 0; } } } // render new text frames if needed if (direction > 0) { // forward scroll int next_s = 0; // get next string if (first != last) next_s = ci[(last - 1 + CREDIT_FRAMES) % CREDIT_FRAMES] + 1; while (total_h - dy < disp_h && next_s < strcnt) { cf[last] = Credits_RenderTextFrame (LocalContext, &next_s, direction, TextBack, TextFore); ci[last] = next_s - 1; if (cf[last]) { GetFrameRect (cf[last], &fr); total_h += fr.extent.height; last = (last + 1) % CREDIT_FRAMES; } } } else if (direction < 0) { // backward scroll int next_s = strcnt - 1; // get next string if (first != last) next_s = ci[first] - 1; while (dy < 0 && next_s >= 0) { int index = (first - 1 + CREDIT_FRAMES) % CREDIT_FRAMES; cf[index] = Credits_RenderTextFrame (LocalContext, &next_s, direction, TextBack, TextFore); ci[index] = next_s + 1; if (cf[index]) { GetFrameRect (cf[index], &fr); total_h += fr.extent.height; first = index; dy += fr.extent.height; } } } // draw next screen frame LockMutex (GraphicsLock); OldContext = SetContext (LocalContext); // draw background s.origin.x = s.origin.y = 0; s.frame = CreditsBack; DrawStamp (&s); // draw text frames s.origin.y = -dy; for (i = first; i != last; i = (i + 1) % CREDIT_FRAMES) { s.frame = cf[i]; DrawStamp (&s); GetFrameRect (s.frame, &fr); s.origin.y += fr.extent.height; } if (direction > 0) deficit_h = disp_h - s.origin.y; // draw clipped rect, if any if (OutTakesRunning) { SetContextForeGroundColor (TransColor); DrawFilledRectangle (&CommWndRect); } SetContext (OldContext); UnlockMutex (GraphicsLock); // wait till begining of next screen frame while (GetTimeCounter () < TimeIn + rate && !Task_ReadState (task, TASK_EXIT)) { SleepThreadUntil (ONE_SECOND / CREDITS_FRAME_RATE / 2); } } DestroyContext (ReleaseContext (DrawContext)); DestroyContext (ReleaseContext (LocalContext)); // free remaining frames DestroyDrawable (ReleaseDrawable (Frame)); for ( ; first != last; first = (first + 1) % CREDIT_FRAMES) DestroyDrawable (ReleaseDrawable (cf[first])); FinishTask (task); return 0; } static Task StartCredits (void) { Task task; FONT_SIZE_DEF *fdef; CreditsTab = CaptureStringTable (LoadStringTable (CREDITS_STRTAB)); if (!CreditsTab) return 0; CreditsBack = CaptureDrawable (LoadGraphic (CREDITS_BACK_ANIM)); // load fonts for (fdef = CreditsFont; fdef->size; ++fdef) fdef->font = CaptureFont (LoadFont (fdef->res)); CreditsRate = CREDITS_BASE_RATE; CreditsRunning = FALSE; task = AssignTask (credit_roll_task, 4096, "credit roll"); return task; } static void FreeCredits (void) { FONT_SIZE_DEF *fdef; DestroyStringTable (ReleaseStringTable (CreditsTab)); CreditsTab = 0; DestroyDrawable (ReleaseDrawable (CreditsBack)); CreditsBack = 0; // free fonts for (fdef = CreditsFont; fdef->size; ++fdef) { DestroyFont (ReleaseFont (fdef->font)); fdef->font = 0; } } static void OutTakes (void) { #define NUM_OUTTAKES 15 static long outtake_list[NUM_OUTTAKES] = { ZOQFOTPIK_CONVERSATION, TALKING_PET_CONVERSATION, ORZ_CONVERSATION, UTWIG_CONVERSATION, THRADD_CONVERSATION, SUPOX_CONVERSATION, SYREEN_CONVERSATION, SHOFIXTI_CONVERSATION, PKUNK_CONVERSATION, YEHAT_CONVERSATION, DRUUGE_CONVERSATION, URQUAN_CONVERSATION, VUX_CONVERSATION, BLACKURQ_CONVERSATION, ARILOU_CONVERSATION }; BOOLEAN oldsubtitles = optSubtitles; int i = 0; optSubtitles = TRUE; sliderDisabled = TRUE; oscillDisabled = TRUE; for (i = 0; (i < NUM_OUTTAKES) && !(GLOBAL (CurrentActivity) & CHECK_ABORT); i++) { InitCommunication (outtake_list[i]); } optSubtitles = oldsubtitles; sliderDisabled = FALSE; oscillDisabled = FALSE; } typedef struct { // standard state required by DoInput BOOLEAN (*InputFunc) (PVOID pInputState); COUNT MenuRepeatDelay; BOOLEAN AllowCancel; BOOLEAN AllowSpeedChange; BOOLEAN CloseWhenDone; DWORD CloseTimeOut; } CREDITS_INPUT_STATE; static BOOLEAN DoCreditsInput (PVOID pIS) { CREDITS_INPUT_STATE *pCIS = (CREDITS_INPUT_STATE *) pIS; if (CreditsRunning) { // cancel timeout if resumed (or just running) pCIS->CloseTimeOut = 0; } if ((GLOBAL (CurrentActivity) & CHECK_ABORT) || (pCIS->AllowCancel && (PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_CANCEL])) ) { // aborted return FALSE; } if (pCIS->AllowSpeedChange && (PulsedInputState.menu[KEY_MENU_UP] || PulsedInputState.menu[KEY_MENU_DOWN])) { // speed adjustment int newrate = CreditsRate; int step = abs (CreditsRate) / 5 + 1; if (PulsedInputState.menu[KEY_MENU_DOWN]) newrate += step; else if (PulsedInputState.menu[KEY_MENU_UP]) newrate -= step; if (newrate < -CREDITS_MAX_RATE) newrate = -CREDITS_MAX_RATE; else if (newrate > CREDITS_MAX_RATE) newrate = CREDITS_MAX_RATE; CreditsRate = newrate; } if (!CreditsRunning) { // always allow cancelling once credits run through pCIS->AllowCancel = TRUE; } if (!CreditsRunning && pCIS->CloseWhenDone) { // auto-close controlled by timeout if (pCIS->CloseTimeOut == 0) { // set timeout pCIS->CloseTimeOut = GetTimeCounter () + CREDITS_TIMEOUT; } else if (GetTimeCounter () > pCIS->CloseTimeOut) { // all done! return FALSE; } } if (!CreditsRunning && (PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_CANCEL])) { // credits finished and exit requested return FALSE; } SleepThread (ONE_SECOND / 30); return TRUE; } void Credits (BOOLEAN WithOuttakes) { BYTE fade_buf[1]; MUSIC_REF hMusic; Task CredTask; CREDITS_INPUT_STATE cis; hMusic = LoadMusic (CREDITS_MUSIC); LockMutex (GraphicsLock); SetContext (ScreenContext); SetContextClipRect (NULL_PTR); SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); ClearDrawable (); fade_buf[0] = FadeAllToColor; XFormColorMap ((COLORMAPPTR)fade_buf, 0); UnlockMutex (GraphicsLock); // set the position of outtakes comm CommWndRect.corner.x = ((SCREEN_WIDTH - SIS_SCREEN_WIDTH) >> 1); CommWndRect.corner.y = 5; // launch credits and wait for the task to start up CredTask = StartCredits (); while (CredTask && !CreditsRunning && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) { UpdateInputState (); SleepThread(ONE_SECOND / 20); } if (WithOuttakes) { OutTakesRunning = TRUE; OutTakes (); OutTakesRunning = FALSE; } if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) { if (hMusic) PlayMusic (hMusic, TRUE, 1); // nothing to do now but wait until credits // are done or canceled by user cis.MenuRepeatDelay = 0; cis.InputFunc = DoCreditsInput; cis.AllowCancel = !WithOuttakes; cis.CloseWhenDone = !WithOuttakes; cis.AllowSpeedChange = TRUE; SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); DoInput (&cis, TRUE); } if (CredTask) ConcludeTask (CredTask); FadeMusic (0, ONE_SECOND / 2); LockMutex (GraphicsLock); SetContext (ScreenContext); fade_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND / 2)); FlushColorXForms (); UnlockMutex (GraphicsLock); if (hMusic) { StopMusic (); DestroyMusic (hMusic); } FadeMusic (NORMAL_VOLUME, 0); FreeCredits (); } uqm-0.6.2/sc2/src/sc2code/setup.c0000600000175000017500000001330110543202103015077 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "setup.h" #include "coderes.h" #include "controls.h" #include "options.h" #include "nameref.h" #ifdef NETPLAY # include "netplay/netmelee.h" #endif #include "init.h" #include "intel.h" #include "resinst.h" #include "sounds.h" #include "libs/compiler.h" #include "libs/uio.h" #include "libs/file.h" #include "libs/graphics/gfx_common.h" #include "libs/threadlib.h" #include "libs/vidlib.h" #include "libs/log.h" #include #include #include ACTIVITY LastActivity; BYTE PlayerControl[NUM_PLAYERS]; // XXX: These declarations should really go to the file they belong to. MEM_HANDLE hResIndex; CONTEXT ScreenContext; CONTEXT SpaceContext; CONTEXT StatusContext; CONTEXT OffScreenContext; CONTEXT TaskContext; SIZE screen_width, screen_height; FRAME Screen; FONT StarConFont; FONT MicroFont; FONT TinyFont; QUEUE race_q[NUM_PLAYERS]; FRAME ActivityFrame; FRAME StatusFrame; FRAME FlagStatFrame; FRAME MiscDataFrame; FRAME FontGradFrame; Mutex GraphicsLock; STRING GameStrings; uio_Repository *repository; uio_DirHandle *rootDir; static void InitPlayerInput (void) { HumanInput[0] = p1_combat_summary; HumanInput[1] = p2_combat_summary; ComputerInput = computer_intelligence; #ifdef NETPLAY NetworkInput = networkBattleInput; #endif } void UninitPlayerInput (void) { #if DEMO_MODE DestroyInputDevice (ReleaseInputDevice (DemoInput)); #endif /* DEMO_MODE */ } BOOLEAN LoadKernel (int argc, char *argv[]) { #define MIN_K_REQUIRED (580000L / 1024) if (!InitGraphics (argc, argv, MIN_K_REQUIRED)) return FALSE; InitSound (argc, argv); InitVideo (TRUE); ScreenContext = CaptureContext (CreateContext ()); if (ScreenContext == NULL) return FALSE; Screen = CaptureDrawable (CreateDisplay (WANT_MASK | WANT_PIXMAP, &screen_width, &screen_height)); if (Screen == NULL) return FALSE; SetContext (ScreenContext); SetContextFGFrame (Screen); SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); hResIndex = InitResourceSystem ("starcon.lst", RES_INDEX, NULL); if (hResIndex == 0) return FALSE; INIT_INSTANCES (); { COLORMAP ColorMapTab; ColorMapTab = CaptureColorMap (LoadColorMap (STARCON_COLOR_MAP)); SetColorMap (GetColorMapAddress (ColorMapTab)); DestroyColorMap (ReleaseColorMap (ColorMapTab)); } InitPlayerInput (); GLOBAL (CurrentActivity) = (ACTIVITY)~0; return TRUE; } BOOLEAN InitContexts (void) { RECT r; StatusContext = CaptureContext (CreateContext ()); if (StatusContext == NULL) return FALSE; SetContext (StatusContext); SetContextFGFrame (Screen); r.corner.x = SPACE_WIDTH + SAFE_X; r.corner.y = SAFE_Y; r.extent.width = STATUS_WIDTH; r.extent.height = STATUS_HEIGHT; SetContextClipRect (&r); SpaceContext = CaptureContext (CreateContext ()); if (SpaceContext == NULL) return FALSE; OffScreenContext = CaptureContext (CreateContext ()); if (OffScreenContext == NULL) return FALSE; if (!InitQueue (&disp_q, 100, sizeof (ELEMENT))) return FALSE; return TRUE; } BOOLEAN InitKernel (void) { COUNT counter; for (counter = 0; counter < NUM_PLAYERS; ++counter) InitQueue (&race_q[counter], MAX_SHIPS_PER_SIDE, sizeof (STARSHIP)); StarConFont = CaptureFont (LoadFont (STARCON_FONT)); if (StarConFont == NULL) return FALSE; TinyFont = CaptureFont (LoadFont (TINY_FONT)); if (TinyFont == NULL) return FALSE; ActivityFrame = CaptureDrawable (LoadGraphic (ACTIVITY_ANIM)); if (ActivityFrame == NULL) return FALSE; StatusFrame = CaptureDrawable (LoadGraphic (STATUS_MASK_PMAP_ANIM)); if (StatusFrame == NULL) return FALSE; GameStrings = CaptureStringTable (LoadStringTable (STARCON_GAME_STRINGS)); if (GameStrings == 0) return FALSE; MicroFont = CaptureFont (LoadFont (MICRO_FONT)); if (MicroFont == NULL) return FALSE; MenuSounds = CaptureSound (LoadSound (MENU_SOUNDS)); if (MenuSounds == 0) return FALSE; InitSpace (); return TRUE; } BOOLEAN InitGameKernel (void) { if (ActivityFrame == 0) { InitKernel (); InitContexts (); } return TRUE; } void SetPlayerInput (void) { COUNT which_player; for (which_player = 0; which_player < NUM_PLAYERS; ++which_player) { if (PlayerControl[which_player] & COMPUTER_CONTROL) PlayerInput[which_player] = ComputerInput; else if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE) { // Full game. if (which_player == 0) PlayerInput[which_player] = HumanInput[0]; else { PlayerInput[which_player] = ComputerInput; PlayerControl[which_player] = COMPUTER_CONTROL | AWESOME_RATING; } } #ifdef NETPLAY else if (PlayerControl[which_player] & NETWORK_CONTROL) PlayerInput[which_player] = NetworkInput; #endif else PlayerInput[which_player] = HumanInput[which_player]; } } int initIO (void) { uio_init (); repository = uio_openRepository (0); rootDir = uio_openDir (repository, "/", 0); if (rootDir == NULL) { log_add (log_Fatal, "Could not open '/' dir."); return -1; } return 0; } void uninitIO (void) { uio_closeDir (rootDir); uio_closeRepository (repository); uio_unInit (); } uqm-0.6.2/sc2/src/sc2code/intel.c0000600000175000017500000000364610543202103015065 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "intel.h" #include "controls.h" #include "globdata.h" #include "setup.h" #include "libs/log.h" #include SIZE cur_player; BATTLE_INPUT_STATE computer_intelligence (COUNT player, STARSHIPPTR StarShipPtr) { BATTLE_INPUT_STATE InputState; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) return 0; if (StarShipPtr) { if (PlayerControl[player] & CYBORG_CONTROL) { InputState = tactical_intelligence (player, StarShipPtr); // allow a player to warp-escape in cyborg mode if (player == 0) InputState |= (*(HumanInput[player])) (player, StarShipPtr) & BATTLE_ESCAPE; } else InputState = (*(HumanInput[player])) (player, StarShipPtr); } else if (!(PlayerControl[player] & PSYTRON_CONTROL)) InputState = 0; else { switch (LOBYTE (GLOBAL (CurrentActivity))) { case SUPER_MELEE: { SleepThread (ONE_SECOND >> 1); InputState = BATTLE_WEAPON; /* pick a random ship */ break; } default: // Should not happen. Satisfying compiler. log_add (log_Warning, "Warning: Unexpected state in " "computer_intelligence()."); InputState = 0; break; } } return InputState; } uqm-0.6.2/sc2/src/sc2code/collide.h0000600000175000017500000000402310543202100015355 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _COLLIDE_H #define _COLLIDE_H #include "element.h" #define COLLISION_TURN_WAIT 1 #define COLLISION_THRUST_WAIT 3 #define SKIP_COLLISION (NONSOLID | DISAPPEARING) #define CollidingElement(e) \ (!((e)->state_flags & SKIP_COLLISION)) #define CollisionPossible(e0,e1) \ (CollidingElement (e0) \ && (!(((e1)->state_flags & (e0)->state_flags) & COLLISION) \ && ((!(((e1)->state_flags & (e0)->state_flags) & IGNORE_SIMILAR) \ || (e1)->pParent != (e0)->pParent)) \ && ((e1)->mass_points || (e0)->mass_points))) #define InitIntersectStartPoint(eptr) \ { \ (eptr)->IntersectControl.IntersectStamp.origin.x = \ WORLD_TO_DISPLAY ((eptr)->current.location.x); \ (eptr)->IntersectControl.IntersectStamp.origin.y = \ WORLD_TO_DISPLAY ((eptr)->current.location.y); \ } #define InitIntersectEndPoint(eptr) \ { \ (eptr)->IntersectControl.EndPoint.x = \ WORLD_TO_DISPLAY ((eptr)->next.location.x); \ (eptr)->IntersectControl.EndPoint.y = \ WORLD_TO_DISPLAY ((eptr)->next.location.y); \ } #define InitIntersectFrame(eptr) \ { \ (eptr)->IntersectControl.IntersectStamp.frame = \ SetEquFrameIndex ((eptr)->next.image.farray[0], \ (eptr)->next.image.frame); \ } extern void collide (ELEMENTPTR ElementPtr0, ELEMENTPTR ElementPtr1); #endif /* _COLLIDE_H */ uqm-0.6.2/sc2/src/sc2code/shipstat.c0000600000175000017500000002631710543202101015607 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "colors.h" #include "globdata.h" #include "options.h" #include "build.h" #include "setup.h" #include "libs/gfxlib.h" void DrawCrewFuelString (COORD y, SIZE state) { STAMP Stamp; Stamp.origin.y = y + GAUGE_YOFFS + STARCON_TEXT_HEIGHT; if (state == 0) { Stamp.origin.x = CREW_XOFFS + (STAT_WIDTH >> 1) + 6; if (optWhichMenu == OPT_PC) Stamp.frame = SetAbsFrameIndex (StatusFrame, 4); else Stamp.frame = SetAbsFrameIndex (StatusFrame, 0); DrawStamp (&Stamp); } Stamp.origin.x = ENERGY_XOFFS + (STAT_WIDTH >> 1) - 5; if (optWhichMenu == OPT_PC) Stamp.frame = SetAbsFrameIndex (StatusFrame, 5); else Stamp.frame = SetAbsFrameIndex (StatusFrame, 1); if (state >= 0) DrawStamp (&Stamp); else { #define LOW_FUEL_COLOR BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E) SetContextForeGroundColor (LOW_FUEL_COLOR); DrawFilledStamp (&Stamp); } } static void DrawShipNameString (UNICODE *pStr, COUNT CharCount, COORD y) { TEXT Text; FONT OldFont; OldFont = SetContextFont (StarConFont); Text.pStr = pStr; Text.CharCount = CharCount; Text.align = ALIGN_CENTER; Text.baseline.y = STARCON_TEXT_HEIGHT + 3 + y; Text.baseline.x = STATUS_WIDTH >> 1; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); font_DrawText (&Text); --Text.baseline.y; SetContextForeGroundColor (BLACK_COLOR); font_DrawText (&Text); SetContextFont (OldFont); } void ClearShipStatus (COORD y) { RECT r; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); r.corner.x = 2; r.corner.y = 3 + y; r.extent.width = STATUS_WIDTH - 4; r.extent.height = SHIP_INFO_HEIGHT - 3; DrawFilledRectangle (&r); } void OutlineShipStatus (COORD y) { RECT r; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); r.corner.x = 0; r.corner.y = 1 + y; r.extent.width = STATUS_WIDTH; r.extent.height = 1; DrawFilledRectangle (&r); ++r.corner.y; --r.extent.width; DrawFilledRectangle (&r); r.extent.width = 1; r.extent.height = SHIP_INFO_HEIGHT - 2; DrawFilledRectangle (&r); ++r.corner.x; DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); r.corner.x = STATUS_WIDTH - 1; DrawFilledRectangle (&r); r.corner.x = STATUS_WIDTH - 2; ++r.corner.y; --r.extent.height; DrawFilledRectangle (&r); SetContextForeGroundColor (BLACK_COLOR); r.corner.x = 0; r.corner.y = y; r.extent.width = STATUS_WIDTH; r.extent.height = 1; DrawFilledRectangle (&r); } void InitShipStatus (STARSHIPPTR StarShipPtr, PRECT pClipRect) { RECT r; COORD y, y_stat; STAMP Stamp; CONTEXT OldContext; SHIP_INFOPTR SIPtr; SIPtr = &StarShipPtr->RaceDescPtr->ship_info; y_stat = (SIPtr->ship_flags & GOOD_GUY) ? GOOD_GUY_YOFFS : BAD_GUY_YOFFS; OldContext = SetContext (StatusContext); y = y_stat; if (pClipRect) { GetContextClipRect (&r); r.corner.x += pClipRect->corner.x; r.corner.y += (pClipRect->corner.y & ~1); r.extent = pClipRect->extent; r.extent.height += pClipRect->corner.y & 1; SetContextClipRect (&r); SetFrameHot (Screen, MAKE_HOT_SPOT ( pClipRect->corner.x, (pClipRect->corner.y & ~1))); } BatchGraphics (); OutlineShipStatus (y); ClearShipStatus (y); Stamp.origin.x = (STATUS_WIDTH >> 1); Stamp.origin.y = 31 + y; Stamp.frame = IncFrameIndex (SIPtr->icons); DrawStamp (&Stamp); { SIZE crew_height, energy_height; #define MIN(a, b) (((a) <= (b)) ? (a) : (b)) crew_height = ((MIN(SIPtr->max_crew, MAX_CREW_SIZE) + 1) & ~1) + 1; #undef MIN energy_height = (((SIPtr->max_energy + 1) >> 1) << 1) + 1; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); r.corner.x = CREW_XOFFS - 1; r.corner.y = GAUGE_YOFFS + 1 + y; r.extent.width = STAT_WIDTH + 2; r.extent.height = 1; DrawFilledRectangle (&r); r.corner.x = ENERGY_XOFFS - 1; DrawFilledRectangle (&r); r.corner.x = ENERGY_XOFFS + STAT_WIDTH; r.corner.y -= energy_height; r.extent.width = 1; r.extent.height = energy_height; DrawFilledRectangle (&r); r.corner.x = CREW_XOFFS + STAT_WIDTH; r.corner.y = (GAUGE_YOFFS + 1 + y) - crew_height; r.extent.width = 1; r.extent.height = crew_height; DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); r.corner.x = CREW_XOFFS - 1; r.corner.y = GAUGE_YOFFS - crew_height + y; r.extent.width = STAT_WIDTH + 2; r.extent.height = 1; DrawFilledRectangle (&r); r.corner.x = ENERGY_XOFFS - 1; r.corner.y = GAUGE_YOFFS - energy_height + y; DrawFilledRectangle (&r); r.extent.width = 1; r.extent.height = energy_height + 1; DrawFilledRectangle (&r); r.corner.x = CREW_XOFFS - 1; r.corner.y = GAUGE_YOFFS - crew_height + y; r.extent.height = crew_height + 1; DrawFilledRectangle (&r); SetContextForeGroundColor (BLACK_COLOR); r.extent.width = STAT_WIDTH; r.corner.x = CREW_XOFFS; r.extent.height = crew_height; r.corner.y = y - r.extent.height + GAUGE_YOFFS + 1; DrawFilledRectangle (&r); r.corner.x = ENERGY_XOFFS; r.extent.height = energy_height; r.corner.y = y - r.extent.height + GAUGE_YOFFS + 1; DrawFilledRectangle (&r); } if (StarShipPtr->captains_name_index || LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE) { STRING locString; DrawCrewFuelString (y, 0); locString = SetAbsStringTableIndex (SIPtr->race_strings, 1); DrawShipNameString ( (UNICODE *)GetStringAddress (locString), GetStringLength (locString),y); { UNICODE buf[30]; TEXT Text; FONT OldFont; OldFont = SetContextFont (TinyFont); if (!(GLOBAL (CurrentActivity) & IN_BATTLE)) { sprintf (buf, "%d", SIPtr->ship_cost); Text.pStr = buf; Text.CharCount = (COUNT)~0; } else { locString = SetAbsStringTableIndex (SIPtr->race_strings, StarShipPtr->captains_name_index); Text.pStr = (UNICODE *)GetStringAddress (locString); Text.CharCount = GetStringLength (locString); } Text.align = ALIGN_CENTER; Text.baseline.x = STATUS_WIDTH >> 1; Text.baseline.y = y + GAUGE_YOFFS + 3; SetContextForeGroundColor (BLACK_COLOR); font_DrawText (&Text); SetContextFont (OldFont); } } else if (StarShipPtr->captains_name_index == 0) { if (SIPtr->ship_flags & GOOD_GUY) { DrawCrewFuelString (y, 0); DrawShipNameString (GLOBAL_SIS (ShipName), (COUNT)~0, y); } } { SIZE crew_delta, energy_delta; crew_delta = SIPtr->crew_level; energy_delta = SIPtr->energy_level; SIPtr->crew_level = SIPtr->energy_level = 0; DeltaStatistics (StarShipPtr, crew_delta, energy_delta); } UnbatchGraphics (); if (pClipRect) { SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); r.corner.x = SPACE_WIDTH + SAFE_X; r.corner.y = SAFE_Y; r.extent.width = STATUS_WIDTH; r.extent.height = STATUS_HEIGHT; SetContextClipRect (&r); } SetContext (OldContext); } // Pre: -crew_delta <= StarShipPtr->crew_level // crew_delta <= StarShipPtr->max_crew - StarShipPtr->crew_level void DeltaStatistics (STARSHIPPTR StarShipPtr, SIZE crew_delta, SIZE energy_delta) { COORD x, y; RECT r; SHIP_INFOPTR ShipInfoPtr; if (crew_delta == 0 && energy_delta == 0) return; ShipInfoPtr = &StarShipPtr->RaceDescPtr->ship_info; x = 0; y = GAUGE_YOFFS + ((ShipInfoPtr->ship_flags & GOOD_GUY) ? GOOD_GUY_YOFFS : BAD_GUY_YOFFS); r.extent.width = UNIT_WIDTH; r.extent.height = UNIT_HEIGHT; if (crew_delta != 0) { COUNT oldNumBlocks, newNumBlocks, blockI; COUNT newCrewLevel; #define MIN(a, b) (((a) <= (b)) ? (a) : (b)) oldNumBlocks = MIN(ShipInfoPtr->crew_level, MAX_CREW_SIZE); newCrewLevel = ShipInfoPtr->crew_level + crew_delta; newNumBlocks = MIN(newCrewLevel, MAX_CREW_SIZE); #undef MIN if (crew_delta > 0) { r.corner.y = (y + 1) - (((oldNumBlocks + 1) >> 1) * (UNIT_HEIGHT + 1)); #define CREW_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02) #define ROBOT_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08) SetContextForeGroundColor ( (ShipInfoPtr->ship_flags & CREW_IMMUNE) ? ROBOT_UNIT_COLOR : CREW_UNIT_COLOR); for (blockI = oldNumBlocks; blockI < newNumBlocks; blockI++) { r.corner.x = x + (CREW_XOFFS + 1); if (!(blockI & 1)) { r.corner.x += UNIT_WIDTH + 1; r.corner.y -= UNIT_HEIGHT + 1; } DrawFilledRectangle (&r); } } else /* crew_delta < 0 */ { SetContextForeGroundColor (BLACK_COLOR); r.corner.y = (y + 1) - (((oldNumBlocks + 2) >> 1) * (UNIT_HEIGHT + 1)); for (blockI = oldNumBlocks; blockI > newNumBlocks; blockI--) { r.corner.x = x + (CREW_XOFFS + 1 + UNIT_WIDTH + 1); if (!(blockI & 1)) { r.corner.x -= UNIT_WIDTH + 1; r.corner.y += UNIT_HEIGHT + 1; } DrawFilledRectangle (&r); } } if (ShipInfoPtr->ship_flags & PLAYER_CAPTAIN) { if (((ShipInfoPtr->crew_level > MAX_CREW_SIZE) != (newCrewLevel > MAX_CREW_SIZE) || ShipInfoPtr->crew_level == 0) && newCrewLevel != 0) { // The block indicating the captain needs to change color. #define PLAYER_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09) SetContextForeGroundColor ( (newCrewLevel > MAX_CREW_SIZE) ? CREW_UNIT_COLOR : PLAYER_UNIT_COLOR); r.corner.x = x + (CREW_XOFFS + 1) + (UNIT_WIDTH + 1); r.corner.y = y - UNIT_HEIGHT; DrawFilledRectangle (&r); } } ShipInfoPtr->crew_level = newCrewLevel; if (ShipInfoPtr->max_crew > MAX_CREW_SIZE || ShipInfoPtr->ship_flags & PLAYER_CAPTAIN) { // All crew doesn't fit in the graphics; print a number. // Always print a number for the SIS in the full game. DrawBattleCrewAmount (StarShipPtr); } } if (energy_delta != 0) { if (energy_delta > 0) { #define FUEL_UNIT_COLOR BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) SetContextForeGroundColor (FUEL_UNIT_COLOR); r.corner.y = (y + 1) - (((ShipInfoPtr->energy_level + 1) >> 1) * (UNIT_HEIGHT + 1)); do { r.corner.x = x + (ENERGY_XOFFS + 1); if (!(ShipInfoPtr->energy_level & 1)) { r.corner.x += UNIT_WIDTH + 1; r.corner.y -= UNIT_HEIGHT + 1; } DrawFilledRectangle (&r); ++ShipInfoPtr->energy_level; } while (--energy_delta); } else { SetContextForeGroundColor (BLACK_COLOR); r.corner.y = (y + 1) - (((ShipInfoPtr->energy_level + 2) >> 1) * (UNIT_HEIGHT + 1)); do { r.corner.x = x + (ENERGY_XOFFS + 1 + UNIT_WIDTH + 1); if (!(ShipInfoPtr->energy_level & 1)) { r.corner.x -= UNIT_WIDTH + 1; r.corner.y += UNIT_HEIGHT + 1; } DrawFilledRectangle (&r); --ShipInfoPtr->energy_level; } while (++energy_delta); } } } uqm-0.6.2/sc2/src/sc2code/clock.h0000600000175000017500000000565610543202101015053 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _CLOCK_H #define _CLOCK_H #include "libs/tasklib.h" #include "displist.h" #define START_YEAR 2155 #define UPDATE_DAY (1 << 0) #define UPDATE_MONTH (1 << 1) #define UPDATE_YEAR (1 << 2) typedef struct { BYTE day_index, month_index; COUNT year_index; SIZE tick_count, day_in_ticks; Semaphore clock_sem; Task clock_task; DWORD TimeCounter; QUEUE event_q; } CLOCK_STATE; typedef CLOCK_STATE *PCLOCK_STATE; typedef QUEUE_HANDLE HEVENT; typedef struct event { HEVENT pred, succ; BYTE day_index, month_index; COUNT year_index; BYTE func_index; } EVENT; typedef EVENT *PEVENT; typedef enum { ABSOLUTE_EVENT = 0, RELATIVE_EVENT } EVENT_TYPE; #define EVENTPTR PEVENT #define AllocEvent() AllocLink (&GLOBAL (GameClock.event_q)) #define PutEvent(h) PutQueue (&GLOBAL (GameClock.event_q), (h)) #define InsertEvent(h,i) InsertQueue (&GLOBAL (GameClock.event_q), (h), (i)) #define GetHeadEvent() GetHeadLink (&GLOBAL (GameClock.event_q)) #define GetTailEvent() GetTailLink (&GLOBAL (GameClock.event_q)) #define LockEvent(h,eptr) *(eptr) = (EVENTPTR)LockLink ( \ &GLOBAL (GameClock.event_q), (h)) #define UnlockEvent(h) UnlockLink (&GLOBAL (GameClock.event_q), (h)) #define RemoveEvent(h) RemoveQueue (&GLOBAL (GameClock.event_q), (h)) #define FreeEvent(h) FreeLink (&GLOBAL (GameClock.event_q), (h)) #define GetPredEvent(l) _GetPredLink (l) #define GetSuccEvent(l) _GetSuccLink (l) #define ForAllEvents(callback, arg) ForAllLinks(&GLOBAL (GameClock.event_q), \ (void (*)(LINKPTR, void *)) (callback), (arg)) /* rates are in seconds per game day */ #define HYPERSPACE_CLOCK_RATE 5 #define INTERPLANETARY_CLOCK_RATE 30 extern BOOLEAN InitGameClock (void); extern BOOLEAN UninitGameClock (void); extern void SuspendGameClock (void); extern void ResumeGameClock (void); extern BOOLEAN GameClockRunning (void); extern void SetGameClockRate (COUNT seconds_per_day); extern BOOLEAN ValidateEvent (EVENT_TYPE type, PCOUNT pmonth_index, PCOUNT pday_index, PCOUNT pyear_index); extern HEVENT AddEvent (EVENT_TYPE type, COUNT month_index, COUNT day_index, COUNT year_index, BYTE func_index); extern void EventHandler (BYTE selector); extern SIZE ClockTick (void); #endif /* _CLOCK_H */ uqm-0.6.2/sc2/src/sc2code/comm.h0000600000175000017500000000313710543202101014703 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _COMM_H #define _COMM_H #include "globdata.h" #include "libs/compiler.h" #include "libs/gfxlib.h" typedef enum { DONE_SUBTITLE, NEXT_SUBTITLE, READ_SUBTITLE, SPACE_SUBTITLE, WAIT_SUBTITLE, } SUBTITLE_STATE; #ifdef COMM_INTERNAL #define SLIDER_Y 107 #define SLIDER_HEIGHT 15 #include "commanim.h" void DrawAlienFrame (FRAME aframe, PSEQUENCE pSeq); BOOLEAN SetClearSubtitle (BOOLEAN flag, SUBTITLE_STATE *sub_state); extern LOCDATA CommData; extern volatile BOOLEAN ClearSummary; #endif extern void init_communication (void); extern void uninit_communication (void); extern SUBTITLE_STATE do_subtitles (UNICODE *pStr); extern void AlienTalkSegue (COUNT wait_track); BOOLEAN getLineWithinWidth(TEXT *pText, const unsigned char **startNext, SIZE maxWidth, COUNT maxChars); void RedrawSubtitles (void); extern RECT CommWndRect; /* comm window rect */ #endif /* _COMM_H */ uqm-0.6.2/sc2/src/sc2code/velocity.h0000600000175000017500000000364210543202101015607 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _VELOCITY_H #define _VELOCITY_H #include /* for memset */ #include "libs/gfxlib.h" typedef struct velocity_desc { COUNT TravelAngle; EXTENT vector; EXTENT fract; EXTENT error; EXTENT incr; } VELOCITY_DESC; typedef VELOCITY_DESC *PVELOCITY; typedef PVELOCITY VELOCITYPTR; #define ZeroVelocityComponents(pv) memset(pv,0,sizeof (*(pv))) #define GetVelocityTravelAngle(pv) (pv)->TravelAngle extern void GetCurrentVelocityComponents (VELOCITYPTR velocityptr, PSIZE pdx, PSIZE pdy); extern void GetNextVelocityComponents (VELOCITYPTR velocityptr, PSIZE pdx, PSIZE pdy, COUNT num_frames); extern void SetVelocityVector (VELOCITYPTR velocityptr, SIZE magnitude, COUNT facing); extern void SetVelocityComponents (VELOCITYPTR velocityptr, SIZE dx, SIZE dy); extern void DeltaVelocityComponents (VELOCITYPTR velocityptr, SIZE dx, SIZE dy); static inline DWORD VelocitySquared (SIZE dx, SIZE dy) { return (DWORD)((long)dx * dx + (long)dy * dy); } #define VELOCITY_SHIFT 5 #define VELOCITY_SCALE (1<>VELOCITY_SHIFT) #define WORLD_TO_VELOCITY(l) ((l)< #define MAX_SAVED_GAMES 50 #define SUMMARY_X_OFFS 14 #define SUMMARY_SIDE_OFFS 7 #define SAVES_PER_PAGE 5 static BOOLEAN DoSettings (PMENU_STATE pMS); static BOOLEAN DoNaming (PMENU_STATE pMS); static PMENU_STATE pLocMenuState; static BYTE prev_save; //keeps track of the last slot that was saved or loaded void ConfirmSaveLoad (STAMP *MsgStamp) { RECT r, clip_r; TEXT t; SetContextFont (StarConFont); GetContextClipRect (&clip_r); if (clip_r.extent.width == 0) { clip_r.corner.x = clip_r.corner.y = 0; clip_r.extent.width = SCREEN_WIDTH; clip_r.extent.height = SCREEN_HEIGHT; } t.baseline.x = clip_r.extent.width >> 1; t.baseline.y = (clip_r.extent.height >> 1) + 3; t.align = ALIGN_CENTER; t.CharCount = (COUNT)~0; if (MsgStamp) t.pStr = GAME_STRING (SAVEGAME_STRING_BASE + 0); else t.pStr = GAME_STRING (SAVEGAME_STRING_BASE + 1); TextRect (&t, &r, NULL_PTR); r.corner.x -= 4; r.corner.y -= 4; r.extent.width += 8; r.extent.height += 8; if (MsgStamp) { MsgStamp->origin = r.corner; r.corner.x += clip_r.corner.x; r.corner.y += clip_r.corner.y; MsgStamp->frame = CaptureDrawable (LoadDisplayPixmap (&r, (FRAME)0)); r.corner.x -= clip_r.corner.x; r.corner.y -= clip_r.corner.y; } DrawStarConBox (&r, 2, BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F), TRUE, BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x0F)); font_DrawText (&t); } enum { SAVE_GAME = 0, LOAD_GAME, QUIT_GAME, SETTINGS }; static BOOLEAN DoGameOptions (PMENU_STATE pMS); enum { SOUND_ON_SETTING, SOUND_OFF_SETTING, MUSIC_ON_SETTING, MUSIC_OFF_SETTING, CYBORG_OFF_SETTING, CYBORG_NORMAL_SETTING, CYBORG_DOUBLE_SETTING, CYBORG_SUPER_SETTING, CHANGE_CAPTAIN_SETTING, CHANGE_SHIP_SETTING, EXIT_MENU_SETTING }; enum { NO_QUIT_MENU, YES_QUIT_MENU }; static void FeedbackSetting (BYTE which_setting) { UNICODE buf[128]; const char *tmpstr; buf[0] = '\0'; // pre-terminate buffer in case snprintf() overflows buf[sizeof (buf) - 1] = '\0'; switch (which_setting) { case SOUND_ON_SETTING: case SOUND_OFF_SETTING: snprintf (buf, sizeof (buf) - 1, "%s %s", GAME_STRING (OPTION_STRING_BASE + 0), GLOBAL (glob_flags) & SOUND_DISABLED ? GAME_STRING (OPTION_STRING_BASE + 3) : GAME_STRING (OPTION_STRING_BASE + 4)); break; case MUSIC_ON_SETTING: case MUSIC_OFF_SETTING: snprintf (buf, sizeof (buf) - 1, "%s %s", GAME_STRING (OPTION_STRING_BASE + 1), GLOBAL (glob_flags) & MUSIC_DISABLED ? GAME_STRING (OPTION_STRING_BASE + 3) : GAME_STRING (OPTION_STRING_BASE + 4)); break; case CYBORG_OFF_SETTING: case CYBORG_NORMAL_SETTING: case CYBORG_DOUBLE_SETTING: case CYBORG_SUPER_SETTING: if (optWhichMenu == OPT_PC && which_setting > CYBORG_NORMAL_SETTING) { if (which_setting == CYBORG_DOUBLE_SETTING) tmpstr = "+"; else tmpstr = "++"; } else tmpstr = ""; snprintf (buf, sizeof (buf) - 1, "%s %s%s", GAME_STRING (OPTION_STRING_BASE + 2), !(GLOBAL (glob_flags) & CYBORG_ENABLED) ? GAME_STRING (OPTION_STRING_BASE + 3) : GAME_STRING (OPTION_STRING_BASE + 4), tmpstr); break; case CHANGE_CAPTAIN_SETTING: case CHANGE_SHIP_SETTING: utf8StringCopy (buf, sizeof (buf), GAME_STRING (NAMING_STRING_BASE + 0)); break; } LockMutex (GraphicsLock); DrawStatusMessage (buf); UnlockMutex (GraphicsLock); } static void FeedbackQuit (BYTE which_setting) { const UNICODE *buf = ""; switch (which_setting) { case NO_QUIT_MENU: buf = GAME_STRING (QUITMENU_STRING_BASE + 3); // "Don't Quit" break; case YES_QUIT_MENU: buf = GAME_STRING (QUITMENU_STRING_BASE + 4); // "Quit Game" break; } LockMutex (GraphicsLock); DrawStatusMessage (buf); UnlockMutex (GraphicsLock); } #define DDSHS_NORMAL 0 #define DDSHS_EDIT 1 #define DDSHS_BLOCKCUR 2 static BOOLEAN DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, COUNT state) { COUNT rel_index; RECT r; TEXT lf; COLOR BackGround, ForeGround; FONT Font; LockMutex (GraphicsLock); rel_index = (COUNT)(which_string - pMS->first_item.y); { r.corner.x = 2; r.extent.width = SHIP_NAME_WIDTH; r.extent.height = SHIP_NAME_HEIGHT; SetContext (StatusContext); if (pMS->CurState == CHANGE_CAPTAIN_SETTING) { Font = TinyFont; r.corner.y = 10; ++r.corner.x; r.extent.width -= 2; lf.baseline.x = r.corner.x + (r.extent.width >> 1) - 1; BackGround = BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09); ForeGround = BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B); } else { Font = StarConFont; r.corner.y = 20; lf.baseline.x = r.corner.x + (r.extent.width >> 1); BackGround = BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D); ForeGround = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7D); } lf.baseline.y = r.corner.y + r.extent.height - 1; lf.align = ALIGN_CENTER; } SetContextFont (Font); lf.pStr = ((GAME_DESC *)pMS->Extra)[rel_index]; lf.CharCount = (COUNT)~0; if (!(state & DDSHS_EDIT)) { // normal state SetFlashRect (SFR_MENU_3DO, (FRAME)0); if (pMS->InputFunc == DoNaming) { if (pMS->CurState == CHANGE_CAPTAIN_SETTING) DrawCaptainsName (); else { DrawFlagshipName (TRUE); if (pMenuState && pMenuState->InputFunc == DoOutfit) DrawFlagshipName (FALSE); } } else { // XXX: remnants of DOS? this function is never actually // called outside DoNaming nowadays, which makes this // code utterly dead if (state == 0) { COLOR OldColor; OldColor = SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); SetContextForeGroundColor (OldColor); } font_DrawText (&lf); } } else { // editing state COUNT i; RECT text_r; BYTE char_deltas[MAX_DESC_CHARS]; PBYTE pchar_deltas; TextRect (&lf, &text_r, char_deltas); if ((text_r.extent.width + 2) >= r.extent.width) { // the text does not fit the input box size and so // will not fit when displayed later UnlockMutex (GraphicsLock); // disallow the change return (FALSE); } SetContextForeGroundColor (BackGround); DrawFilledRectangle (&r); pchar_deltas = char_deltas; for (i = pMS->first_item.x; i > 0; --i) text_r.corner.x += (SIZE)*pchar_deltas++; if ((COUNT)pMS->first_item.x < lf.CharCount) /* end of line */ --text_r.corner.x; if (state & DDSHS_BLOCKCUR) { // Use block cursor for keyboardless systems if ((COUNT)pMS->first_item.x == lf.CharCount) { // cursor at end-line -- use insertion point text_r.extent.width = 1; } else if ((COUNT)pMS->first_item.x + 1 == lf.CharCount) { // extra pixel for last char margin text_r.extent.width = (SIZE)*pchar_deltas + 2; } else { // normal mid-line char text_r.extent.width = (SIZE)*pchar_deltas + 1; } } else { // Insertion point cursor text_r.extent.width = 1; } text_r.corner.y = r.corner.y; text_r.extent.height = r.extent.height; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&text_r); SetContextForeGroundColor (ForeGround); font_DrawText (&lf); SetFlashRect (&r, (FRAME)0); } UnlockMutex (GraphicsLock); return (TRUE); } static BOOLEAN OnNameChange (PTEXTENTRY_STATE pTES) { PMENU_STATE pMS = (PMENU_STATE) pTES->CbParam; COUNT hl = DDSHS_EDIT; pMS->first_item.x = pTES->CursorPos; if (pTES->JoystickMode) hl |= DDSHS_BLOCKCUR; return DrawDescriptionString (pMS, 0, hl); } static BOOLEAN DoNaming (PMENU_STATE pMS) { GAME_DESC buf; TEXTENTRY_STATE tes; UNICODE *Setting; pMS->Initialized = TRUE; pMS->InputFunc = DoNaming; buf[0] = '\0'; // XXX: this code abuses MENU_STATE struct members to store // some values: // first_item.x - current cursor position // first_item.y - must be set to 0; DrawDescriptionString() // treats it as base index into array of strings // supplied in Extra pMS->first_item.x = 0; pMS->first_item.y = 0; pMS->Extra = buf; DrawDescriptionString (pMS, 0, DDSHS_EDIT); LockMutex (GraphicsLock); DrawStatusMessage (GAME_STRING (NAMING_STRING_BASE + 0)); UnlockMutex (GraphicsLock); if (pMS->CurState == CHANGE_CAPTAIN_SETTING) { Setting = GLOBAL_SIS (CommanderName); tes.MaxSize = sizeof (GLOBAL_SIS (CommanderName)); } else { Setting = GLOBAL_SIS (ShipName); tes.MaxSize = sizeof (GLOBAL_SIS (ShipName)); } // text entry setup tes.Initialized = FALSE; tes.MenuRepeatDelay = 0; tes.BaseStr = buf; tes.CursorPos = 0; tes.CbParam = pMS; tes.ChangeCallback = OnNameChange; tes.FrameCallback = 0; if (DoTextEntry (&tes)) utf8StringCopy (Setting, tes.MaxSize, buf); else utf8StringCopy (buf, sizeof (buf), Setting); DrawDescriptionString (pMS, 0, DDSHS_NORMAL); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); pMS->InputFunc = DoSettings; if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) FeedbackSetting (pMS->CurState); return (TRUE); } static BOOLEAN DoSettings (PMENU_STATE pMS) { BYTE cur_speed; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); cur_speed = (BYTE)(GLOBAL (glob_flags) & COMBAT_SPEED_MASK) >> COMBAT_SPEED_SHIFT; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); if (!pMS->Initialized) { DrawMenuStateStrings (PM_SOUND_ON, pMS->CurState); FeedbackSetting (pMS->CurState); pMS->Initialized = TRUE; pMS->InputFunc = DoSettings; } else if (PulsedInputState.menu[KEY_MENU_CANCEL] || (PulsedInputState.menu[KEY_MENU_SELECT] && pMS->CurState == EXIT_MENU_SETTING)) { LockMutex (GraphicsLock); DrawStatusMessage (NULL_PTR); UnlockMutex (GraphicsLock); pMS->CurState = SETTINGS; pMS->InputFunc = DoGameOptions; pMS->Initialized = 0; } else if (PulsedInputState.menu[KEY_MENU_SELECT]) { switch (pMS->CurState) { case SOUND_ON_SETTING: case SOUND_OFF_SETTING: ToggleSoundEffect (); pMS->CurState ^= 1; DrawMenuStateStrings (PM_SOUND_ON, pMS->CurState); break; case MUSIC_ON_SETTING: case MUSIC_OFF_SETTING: ToggleMusic (); pMS->CurState ^= 1; DrawMenuStateStrings (PM_SOUND_ON, pMS->CurState); break; case CHANGE_CAPTAIN_SETTING: case CHANGE_SHIP_SETTING: pMS->Initialized = FALSE; pMS->InputFunc = DoNaming; return (TRUE); default: if (cur_speed++ < NUM_COMBAT_SPEEDS - 1) GLOBAL (glob_flags) |= CYBORG_ENABLED; else { cur_speed = 0; GLOBAL (glob_flags) &= ~CYBORG_ENABLED; } GLOBAL (glob_flags) = (BYTE)((GLOBAL (glob_flags) & ~COMBAT_SPEED_MASK) | (cur_speed << COMBAT_SPEED_SHIFT)); pMS->CurState = CYBORG_OFF_SETTING + cur_speed; DrawMenuStateStrings (PM_SOUND_ON, pMS->CurState); } FeedbackSetting (pMS->CurState); } else if (DoMenuChooser (pMS, PM_SOUND_ON)) FeedbackSetting (pMS->CurState); return (TRUE); } static BOOLEAN DoQuitMenu (PMENU_STATE pMS) { if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); if (!pMS->Initialized) { DrawMenuStateStrings (PM_NO_QUIT, pMS->CurState); FeedbackQuit (pMS->CurState); pMS->Initialized = TRUE; pMS->InputFunc = DoQuitMenu; } else if (PulsedInputState.menu[KEY_MENU_CANCEL] || (PulsedInputState.menu[KEY_MENU_SELECT] && pMS->CurState == NO_QUIT_MENU)) { LockMutex (GraphicsLock); DrawStatusMessage (NULL_PTR); UnlockMutex (GraphicsLock); pMS->CurState = QUIT_GAME; pMS->InputFunc = DoGameOptions; pMS->Initialized = 0; } else if (PulsedInputState.menu[KEY_MENU_SELECT]) { switch (pMS->CurState) { case NO_QUIT_MENU: break; case YES_QUIT_MENU: GLOBAL (CurrentActivity) |= CHECK_ABORT; ExitRequested = FALSE; break; } FeedbackQuit (pMS->CurState); } else if (DoMenuChooser (pMS, PM_NO_QUIT)) FeedbackQuit (pMS->CurState); return (TRUE); } static void DrawCargo (COUNT redraw_state) { BYTE i; RECT r; SetContext (SpaceContext); if (redraw_state) { STAMP s; if (redraw_state == 2) { SetContextForeGroundColor (BLACK_COLOR); r.corner.x = 1 + SUMMARY_X_OFFS; r.corner.y = 12; r.extent.width = ((SIS_SCREEN_WIDTH - STATUS_WIDTH) >> 1) - r.corner.x; r.extent.height = 62 - r.corner.y; DrawFilledRectangle (&r); GetFrameRect (SetRelFrameIndex ( pLocMenuState->ModuleFrame, 1), &r); r.extent.width += SUMMARY_X_OFFS + SUMMARY_SIDE_OFFS; DrawFilledRectangle (&r); } else { s.origin.x = 0; s.origin.y = 0; s.frame = SetAbsFrameIndex (pLocMenuState->ModuleFrame, GetFrameCount (pLocMenuState->ModuleFrame) - 1); if (!pLocMenuState->Initialized) { DrawStamp (&s); s.origin.x = SUMMARY_X_OFFS + 1; s.frame = DecFrameIndex (s.frame); if (pLocMenuState->delta_item == SAVE_GAME) s.frame = DecFrameIndex (s.frame); DrawStamp (&s); if (((SUMMARY_DESC *)pLocMenuState->Extra) [pLocMenuState->CurState].year_index == 0) return; } else { GetContextClipRect (&r); r.extent.height = 136; SetContextClipRect (&r); DrawStamp (&s); r.extent.height = SIS_SCREEN_HEIGHT; SetContextClipRect (&r); } } s.frame = SetAbsFrameIndex ( MiscDataFrame, (NUM_SCANDOT_TRANSITIONS << 1) + 3 ); if (redraw_state == 2 || (redraw_state == 1 /*&& !(((SUMMARY_DESC *)pLocMenuState->Extra) [pLocMenuState->CurState].Flags & AFTER_BOMB_INSTALLED)*/)) { s.origin.x = 7 + SUMMARY_X_OFFS - SUMMARY_SIDE_OFFS + 3; s.origin.y = 17; for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) { if (i == NUM_ELEMENT_CATEGORIES >> 1) { s.origin.x += 36; s.origin.y = 17; } DrawStamp (&s); s.frame = SetRelFrameIndex (s.frame, 5); s.origin.y += 12; } } s.origin.x = 24 + SUMMARY_X_OFFS - SUMMARY_SIDE_OFFS; s.origin.y = 68; s.frame = SetAbsFrameIndex (s.frame, 68); DrawStamp (&s); } else { TEXT t; UNICODE buf[40]; static const COLOR cargo_color[] = { BUILD_COLOR (MAKE_RGB15 (0x02, 0x0E, 0x13), 0x00), BUILD_COLOR (MAKE_RGB15 (0x19, 0x00, 0x00), 0x00), BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x00), BUILD_COLOR (MAKE_RGB15 (0x03, 0x05, 0x1E), 0x00), BUILD_COLOR (MAKE_RGB15 (0x00, 0x18, 0x00), 0x00), BUILD_COLOR (MAKE_RGB15 (0x1B, 0x1B, 0x00), 0x00), BUILD_COLOR (MAKE_RGB15 (0x1E, 0x0D, 0x00), 0x00), BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x14), 0x05), BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x19), 0x00), }; r.extent.width = 23; r.extent.height = SHIP_NAME_HEIGHT; SetContextFont (StarConFont); t.baseline.x = 33 + SUMMARY_X_OFFS - SUMMARY_SIDE_OFFS + 3; t.baseline.y = 20; t.align = ALIGN_RIGHT; t.pStr = buf; for (i = 0; i < NUM_ELEMENT_CATEGORIES; ++i) { if (i == NUM_ELEMENT_CATEGORIES >> 1) { t.baseline.x += 36; t.baseline.y = 20; } SetContextForeGroundColor (BLACK_COLOR); r.corner.x = t.baseline.x - r.extent.width + 1; r.corner.y = t.baseline.y - r.extent.height + 1; DrawFilledRectangle (&r); SetContextForeGroundColor (cargo_color[i]); sprintf (buf, "%u", GLOBAL_SIS (ElementAmounts[i])); t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += 12; } t.baseline.x = 50 + SUMMARY_X_OFFS; t.baseline.y = 71; SetContextForeGroundColor (BLACK_COLOR); r.corner.x = t.baseline.x - r.extent.width + 1; r.corner.y = t.baseline.y - r.extent.height + 1; DrawFilledRectangle (&r); SetContextForeGroundColor (cargo_color[i]); sprintf (buf, "%u", GLOBAL_SIS (TotalBioMass)); t.CharCount = (COUNT)~0; font_DrawText (&t); } } static void ShowSummary (SUMMARY_DESC *pSD) { RECT r; STAMP s; if (pSD->year_index == 0) { // Unused save slot, draw 'Empty Game' message. s.origin.x = s.origin.y = 0; s.frame = SetAbsFrameIndex (pLocMenuState->ModuleFrame, GetFrameCount (pLocMenuState->ModuleFrame) - 4); DrawStamp (&s); r.corner.x = 2; r.corner.y = 139; r.extent.width = SIS_SCREEN_WIDTH - 4; r.extent.height = 7; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); DrawFilledRectangle (&r); } else { // Game slot used, draw information about save game. BYTE i; RECT OldRect; TEXT t; QUEUE player_q; CONTEXT OldContext; SIS_STATE SaveSS; UNICODE buf[256]; SaveSS = GlobData.SIS_state; player_q = GLOBAL (built_ship_q); OldContext = SetContext (StatusContext); GetContextClipRect (&OldRect); r.corner.x = SIS_ORG_X + ((SIS_SCREEN_WIDTH - STATUS_WIDTH) >> 1) + SAFE_X - 16 + SUMMARY_X_OFFS; // r.corner.x = SIS_ORG_X + ((SIS_SCREEN_WIDTH - STATUS_WIDTH) >> 1); r.corner.y = SIS_ORG_Y; r.extent.width = STATUS_WIDTH; r.extent.height = STATUS_HEIGHT; SetContextClipRect (&r); GlobData.SIS_state = pSD->SS; InitQueue (&GLOBAL (built_ship_q), MAX_BUILT_SHIPS, sizeof (SHIP_FRAGMENT)); for (i = 0; i < pSD->NumShips; ++i) CloneShipFragment (pSD->ShipList[i], &GLOBAL (built_ship_q), 0); DateToString (buf, sizeof buf, pSD->month_index, pSD->day_index, pSD->year_index), ClearSISRect (DRAW_SIS_DISPLAY); DrawStatusMessage (buf); UninitQueue (&GLOBAL (built_ship_q)); SetContextClipRect (&OldRect); SetContext (SpaceContext); BatchGraphics (); DrawCargo (0); s.origin.y = 13; r.extent.width = r.extent.height = 16; SetContextForeGroundColor (BLACK_COLOR); for (i = 0; i < 4; ++i) { BYTE j; s.origin.x = 140 + SUMMARY_X_OFFS + SUMMARY_SIDE_OFFS; for (j = 0; j < 4; ++j) { if ((i << 2) + j >= pSD->NumDevices) { r.corner = s.origin; DrawFilledRectangle (&r); } else { s.frame = SetAbsFrameIndex ( MiscDataFrame, 77 + pSD->DeviceList[(i << 2) + j] ); DrawStamp (&s); } s.origin.x += 18; } s.origin.y += 18; } UnbatchGraphics (); SetContextFont (StarConFont); t.baseline.x = 173 + SUMMARY_X_OFFS + SUMMARY_SIDE_OFFS; t.align = ALIGN_CENTER; t.CharCount = (COUNT)~0; t.pStr = buf; if (pSD->Flags & AFTER_BOMB_INSTALLED) { s.origin.x = SUMMARY_X_OFFS - SUMMARY_SIDE_OFFS + 6; s.origin.y = 0; s.frame = SetRelFrameIndex ( pLocMenuState->ModuleFrame, 0); DrawStamp (&s); s.origin.x = SUMMARY_X_OFFS + SUMMARY_SIDE_OFFS; s.frame = IncFrameIndex (s.frame); DrawStamp (&s); } else { SetContext (RadarContext); GetContextClipRect (&OldRect); r.corner.x = SIS_ORG_X + 10 + SUMMARY_X_OFFS - SUMMARY_SIDE_OFFS; r.corner.y = SIS_ORG_Y + 84; r.extent = OldRect.extent; SetContextClipRect (&r); UnlockMutex (GraphicsLock); InitLander ((unsigned char)(pSD->Flags | OVERRIDE_LANDER_FLAGS)); LockMutex (GraphicsLock); SetContextClipRect (&OldRect); SetContext (SpaceContext); sprintf (buf, "%u", GLOBAL_SIS (ResUnits)); t.baseline.y = 102; r.extent.width = 76; r.extent.height = SHIP_NAME_HEIGHT; r.corner.x = t.baseline.x - (r.extent.width >> 1); r.corner.y = t.baseline.y - SHIP_NAME_HEIGHT + 1; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x00, 0x10), 0x01)); font_DrawText (&t); t.CharCount = (COUNT)~0; } t.baseline.y = 126; sprintf (buf, "%u", MAKE_WORD (pSD->MCreditLo, pSD->MCreditHi)); r.extent.width = 30; r.extent.height = SHIP_NAME_HEIGHT; r.corner.x = t.baseline.x - (r.extent.width >> 1); r.corner.y = t.baseline.y - SHIP_NAME_HEIGHT + 1; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x00, 0x10), 0x01)); font_DrawText (&t); r.corner.x = 2; r.corner.y = 139; r.extent.width = SIS_SCREEN_WIDTH - 4; r.extent.height = 7; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); DrawFilledRectangle (&r); t.baseline.x = /*r.corner.x + (SIS_MESSAGE_WIDTH >> 1)*/ 6; t.baseline.y = r.corner.y + (r.extent.height - 1); t.align = ALIGN_LEFT; t.pStr = buf; r.corner.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); r.corner.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); switch (pSD->Activity) { case IN_LAST_BATTLE: case IN_INTERPLANETARY: case IN_PLANET_ORBIT: case IN_STARBASE: { BYTE QuasiState; STAR_DESCPTR SDPtr; QuasiState = GET_GAME_STATE (ARILOU_SPACE_SIDE); SET_GAME_STATE (ARILOU_SPACE_SIDE, 0); SDPtr = FindStar (NULL_PTR, &r.corner, 1, 1); SET_GAME_STATE (ARILOU_SPACE_SIDE, QuasiState); if (SDPtr) { GetClusterName (SDPtr, buf); r.corner = SDPtr->star_pt; break; } } default: buf[0] = '\0'; break; case IN_HYPERSPACE: utf8StringCopy (buf, sizeof (buf), GAME_STRING (NAVIGATION_STRING_BASE + 0)); break; case IN_QUASISPACE: utf8StringCopy (buf, sizeof (buf), GAME_STRING (NAVIGATION_STRING_BASE + 1)); break; } SetContextFont (TinyFont); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33)); t.CharCount = (COUNT)~0; font_DrawText (&t); t.align = ALIGN_CENTER; t.baseline.x = SIS_SCREEN_WIDTH - 57 - 3 + (SIS_TITLE_WIDTH >> 1); if (pSD->Activity == IN_STARBASE) utf8StringCopy (buf, sizeof (buf), GAME_STRING (STARBASE_STRING_BASE)); else if (pSD->Activity == IN_PLANET_ORBIT) utf8StringCopy (buf, sizeof (buf), GLOBAL_SIS (PlanetName)); else sprintf (buf, "%03u.%01u : %03u.%01u", r.corner.x / 10, r.corner.x % 10, r.corner.y / 10, r.corner.y % 10); t.CharCount = (COUNT)~0; font_DrawText (&t); SetContext (OldContext); GLOBAL (built_ship_q) = player_q; GlobData.SIS_state = SaveSS; } } static void LoadGameDescriptions (SUMMARY_DESC *pSD) { COUNT i; for (i = 0; i < MAX_SAVED_GAMES; ++i, ++pSD) { if (!LoadGame (i, pSD)) pSD->year_index = 0; } } static BOOLEAN DoPickGame (PMENU_STATE pMS) { BYTE NewState; SUMMARY_DESC *pSD; BOOLEAN first_time; if (GLOBAL (CurrentActivity) & CHECK_ABORT) { pMS->ModuleFrame = 0; return (FALSE); } first_time = (BOOLEAN)(pMS->Initialized == 0); SetMenuSounds (MENU_SOUND_ARROWS | MENU_SOUND_PAGEUP | MENU_SOUND_PAGEDOWN, MENU_SOUND_SELECT); if (!pMS->Initialized) { pMS->delta_item = (SIZE)pMS->CurState; pMS->CurState = NewState = prev_save; pMS->InputFunc = DoPickGame; SleepThreadUntil ((DWORD)pMS->CurFrame); pMS->CurFrame = 0; PauseMusic (); StopSound (); FadeMusic (NORMAL_VOLUME, 0); { extern FRAME PlayFrame; pMS->ModuleFrame = SetAbsFrameIndex (PlayFrame, 41); } LockMutex (GraphicsLock); SetTransitionSource (NULL); BatchGraphics (); Restart: SetContext (SpaceContext); LoadGameDescriptions ((SUMMARY_DESC *)pMS->Extra); DrawCargo (1); pMS->Initialized = TRUE; goto ChangeGameSelection; } else if (PulsedInputState.menu[KEY_MENU_CANCEL]) { LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); pMS->ModuleFrame = 0; pMS->CurState = (BYTE)pMS->delta_item; ResumeMusic (); if (pSolarSysState) { #define DRAW_REFRESH (1 << 5) #define REPAIR_SCAN (1 << 6) extern BYTE draw_sys_flags; if (pSolarSysState->MenuState.Initialized < 3) draw_sys_flags |= DRAW_REFRESH; else if (pSolarSysState->MenuState.Initialized == 4) draw_sys_flags |= REPAIR_SCAN; } return (FALSE); } else if (PulsedInputState.menu[KEY_MENU_SELECT]) { pSD = &((SUMMARY_DESC *)pMS->Extra)[pMS->CurState]; prev_save = pMS->CurState; if (pMS->delta_item == SAVE_GAME || pSD->year_index) { LockMutex (GraphicsLock); if (pMS->delta_item == SAVE_GAME) { STAMP MsgStamp; ConfirmSaveLoad (&MsgStamp); if (SaveGame ((COUNT)pMS->CurState, pSD)) { DestroyDrawable (ReleaseDrawable (MsgStamp.frame)); GLOBAL (CurrentActivity) |= CHECK_LOAD; } else { SetFlashRect (NULL_PTR, (FRAME)0); DrawStamp (&MsgStamp); DestroyDrawable (ReleaseDrawable (MsgStamp.frame)); UnlockMutex (GraphicsLock); SaveProblem (); pMS->Initialized = FALSE; NewState = pMS->CurState; LockMutex (GraphicsLock); BatchGraphics (); goto Restart; } ResumeMusic (); if (pSolarSysState) { #define DRAW_REFRESH (1 << 5) #define REPAIR_SCAN (1 << 6) extern BYTE draw_sys_flags; if (pSolarSysState->MenuState.Initialized < 3) draw_sys_flags |= DRAW_REFRESH; else if (pSolarSysState->MenuState.Initialized == 4) draw_sys_flags |= REPAIR_SCAN; } } else { ConfirmSaveLoad (0); if (LoadGame ((COUNT)pMS->CurState, NULL_PTR)) GLOBAL (CurrentActivity) |= CHECK_LOAD; } SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); pMS->ModuleFrame = 0; pMS->CurState = (BYTE)pMS->delta_item; return (FALSE); } } else { NewState = pMS->CurState; if (PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_PAGE_UP]) { if (NewState == 0) NewState = MAX_SAVED_GAMES - 1; else if ((NewState - SAVES_PER_PAGE) > 0) NewState -= SAVES_PER_PAGE; else NewState = 0; } else if (PulsedInputState.menu[KEY_MENU_RIGHT] || PulsedInputState.menu[KEY_MENU_PAGE_DOWN]) { if (NewState == MAX_SAVED_GAMES - 1) NewState = 0; else if ((NewState + SAVES_PER_PAGE) < MAX_SAVED_GAMES - 1) NewState += SAVES_PER_PAGE; else NewState = MAX_SAVED_GAMES - 1; } else if (PulsedInputState.menu[KEY_MENU_UP]) { if (NewState == 0) NewState = MAX_SAVED_GAMES - 1; else NewState--; } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { if (NewState == MAX_SAVED_GAMES - 1) NewState = 0; else NewState++; } if (NewState != pMS->CurState) { RECT r; TEXT t; BYTE i, SHIFT; UNICODE buf[256]; UNICODE buf2[80]; LockMutex (GraphicsLock); BatchGraphics (); if (((SUMMARY_DESC *)pMS->Extra)[NewState].year_index != 0) { if (!(((SUMMARY_DESC *)pMS->Extra)[NewState].Flags & AFTER_BOMB_INSTALLED)) { if (((SUMMARY_DESC *)pMS->Extra)[pMS->CurState].year_index == 0) DrawCargo (1); else if (((SUMMARY_DESC *)pMS->Extra)[pMS->CurState].Flags & AFTER_BOMB_INSTALLED) DrawCargo (2); } else if (((SUMMARY_DESC *)pMS->Extra)[pMS->CurState].year_index == 0) DrawCargo (3); } ChangeGameSelection: pMS->CurState = NewState; ShowSummary (&((SUMMARY_DESC *)pMS->Extra)[pMS->CurState]); SetContextFont (TinyFont); r.extent.width = 240; r.extent.height = 65; r.corner.x = 1; r.corner.y = 160; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); t.CharCount = (COUNT)~0; t.pStr = buf; t.align = ALIGN_LEFT; #if 0 /* This code will return in modified form later. */ if (optSmoothScroll == OPT_3DO) // 'Smooth' Scrolling { if (NewState <= (SAVES_PER_PAGE / 2)) SHIFT = NewState; else if ((NewState > (SAVES_PER_PAGE / 2)) && (NewState < (MAX_SAVED_GAMES - (SAVES_PER_PAGE / 2)))) SHIFT = (SAVES_PER_PAGE / 2); else //if (NewState >= (MAX_SAVED_GAMES - (SAVES_PER_PAGE / 2))) SHIFT = SAVES_PER_PAGE - (MAX_SAVED_GAMES - NewState) ; } else // 'Per-Page' Scrolling #endif SHIFT = NewState - ((NewState / SAVES_PER_PAGE) * SAVES_PER_PAGE); for (i = 0; i < SAVES_PER_PAGE && NewState - SHIFT + i < MAX_SAVED_GAMES; i++) { SetContextForeGroundColor ((i == SHIFT) ? (BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33)): (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01))); r.extent.width = 15; if (MAX_SAVED_GAMES > 99) r.extent.width += 5; r.extent.height = 11; r.corner.x = 8; r.corner.y = 160 + (i * 13); DrawRectangle (&r); t.baseline.x = r.corner.x + 3; t.baseline.y = r.corner.y + 8; sprintf (buf, "%02i", NewState - SHIFT + i); if (MAX_SAVED_GAMES > 99) sprintf (buf, "%03i", NewState - SHIFT + i); font_DrawText (&t); r.extent.width = 204 - SAFE_X; r.corner.x = 30 + SAFE_X; DrawRectangle (&r); t.baseline.x = r.corner.x + 3; if (((SUMMARY_DESC *)pMS->Extra)[NewState - SHIFT + i].year_index == 0) sprintf (buf, GAME_STRING (SAVEGAME_STRING_BASE + 3)); // "Empty Slot" else { DateToString (buf2, sizeof buf2, ((SUMMARY_DESC *)pMS->Extra)[NewState - SHIFT + i].month_index, ((SUMMARY_DESC *)pMS->Extra)[NewState - SHIFT + i].day_index, ((SUMMARY_DESC *)pMS->Extra)[NewState - SHIFT + i].year_index); sprintf (buf, "%s %s", GAME_STRING (SAVEGAME_STRING_BASE + 4), buf2); // "Saved Game - Date:" } font_DrawText (&t); } if (LastActivity == CHECK_LOAD) { BYTE clut_buf[] = {FadeAllToColor}; UnbatchGraphics (); LastActivity = 0; XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 2); } else { if (first_time) { r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT; ScreenTransition (3, &r); } UnbatchGraphics (); } SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); } } return (TRUE); } static BOOLEAN PickGame (PMENU_STATE pMS) { BOOLEAN retval; CONTEXT OldContext; SUMMARY_DESC desc_array[MAX_SAVED_GAMES]; RECT DlgRect; STAMP DlgStamp; if (pSolarSysState) { ++pSolarSysState->MenuState.Initialized; pSolarSysState->PauseRotate = 1; TaskSwitch (); } LockMutex (GraphicsLock); OldContext = SetContext (SpaceContext); DlgStamp.origin.x = 0; DlgStamp.origin.y = 0; DlgRect.corner.x = SIS_ORG_X; DlgRect.corner.y = SIS_ORG_Y; DlgRect.extent.width = SIS_SCREEN_WIDTH; DlgRect.extent.height = SIS_SCREEN_HEIGHT; DlgStamp.frame = CaptureDrawable (LoadDisplayPixmap ( &DlgRect, (FRAME)0)); pMS->Initialized = FALSE; pMS->InputFunc = DoPickGame; pMS->Extra = desc_array; UnlockMutex (GraphicsLock); DoInput (pMS, TRUE); LockMutex (GraphicsLock); pMS->Initialized = -1; pMS->InputFunc = DoGameOptions; retval = TRUE; if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) { if (pMS->CurState == SAVE_GAME) GLOBAL (CurrentActivity) &= ~CHECK_LOAD; retval = FALSE; } if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { if (CommData.ConversationPhrases || !(pSolarSysState && pSolarSysState->MenuState.Initialized < 3)) { SetTransitionSource (&DlgRect); BatchGraphics (); DrawStamp(&DlgStamp); ScreenTransition (3, &DlgRect); UnbatchGraphics (); } if (pSolarSysState) { /* We're in interplanetary, so we let the IP * functions know we're ready to draw stuff * again and then update the frame twice; once * for the screen transition, and once to draw * the ships afterwards. */ --pSolarSysState->MenuState.Initialized; pSolarSysState->PauseRotate = 0; IP_frame (); IP_frame (); if (CommData.ConversationPhrases == 0 && !PLRPlaying ((MUSIC_REF)~0)) { if (pSolarSysState->MenuState.Initialized < 3) { PlayMusic (SpaceMusic, TRUE, 1); } else { PlayMusic (LanderMusic, TRUE, 1); } } } } DestroyDrawable (ReleaseDrawable (DlgStamp.frame)); SetContext (OldContext); UnlockMutex (GraphicsLock); return (retval); } static BOOLEAN DoGameOptions (PMENU_STATE pMS) { BOOLEAN force_select = FALSE; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); if (LastActivity == CHECK_LOAD) force_select = TRUE; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); if (pMS->Initialized <= 0) { if (LastActivity == CHECK_LOAD) pMS->CurState = LOAD_GAME; DrawMenuStateStrings (PM_SAVE_GAME, pMS->CurState); pMS->Initialized = 1; pMS->InputFunc = DoGameOptions; } else if (PulsedInputState.menu[KEY_MENU_CANCEL] || (PulsedInputState.menu[KEY_MENU_SELECT] && pMS->CurState == SETTINGS + 1)) { pMS->CurState = SETTINGS + 1; return (FALSE); } else if (PulsedInputState.menu[KEY_MENU_SELECT] || force_select) { switch (pMS->CurState) { case SAVE_GAME: case LOAD_GAME: pMS->CurFrame = (FRAME)FadeMusic (0, ONE_SECOND >> 1); // XXX: what is going on here? A DWORD is cast // to a FRAME. return PickGame (pMS); case QUIT_GAME: pMS->Initialized = FALSE; pMS->CurState = NO_QUIT_MENU; pMS->InputFunc = DoQuitMenu; break; case SETTINGS: pMS->Initialized = FALSE; pMS->InputFunc = DoSettings; pMS->CurState = SOUND_ON_SETTING; break; } } else DoMenuChooser (pMS, PM_SAVE_GAME); return (TRUE); } BOOLEAN GameOptions (void) { MENU_STATE MenuState; pLocMenuState = &MenuState; memset (pLocMenuState, 0, sizeof (MenuState)); MenuState.InputFunc = DoGameOptions; MenuState.CurState = SAVE_GAME; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); DoInput ((PVOID)&MenuState, TRUE); pLocMenuState = 0; return ((GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) ? FALSE : TRUE); } uqm-0.6.2/sc2/src/sc2code/commglue.c0000600000175000017500000002042510543202103015554 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "commglue.h" #include "races.h" #include #include #include #include #include "libs/log.h" int NPCNumberPhrase (int number, UNICODE **ptrack); void NPCPhrase_cb (int index, TFB_TrackCB cb) { UNICODE *pStr, numbuf[400]; void *pClip, *pTimeStamp; switch (index) { case GLOBAL_PLAYER_NAME: pStr = GLOBAL_SIS (CommanderName); pClip = 0; pTimeStamp = 0; break; case GLOBAL_SHIP_NAME: pStr = GLOBAL_SIS (ShipName); pClip = 0; pTimeStamp = 0; break; case GLOBAL_PLAYER_LOCATION: { SIZE dx, dy; COUNT adx, ady; dx = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)) - 333; adx = dx >= 0 ? dx : -dx; dy = 9812 - LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); ady = dy >= 0 ? dy : -dy; sprintf (numbuf, "%+04d.%01u,%+04d.%01u", (SIZE)(dy / 10), (COUNT)(ady % 10), (SIZE)(dx / 10), (COUNT)(adx % 10)); pStr = numbuf; pClip = 0; pTimeStamp = 0; break; } case 0: { return; } default: if (index < 0) { if (index > UNREASONABLE_NUMBER) { if (CommData.AlienNumberSpeech) { NPCNumberPhrase (-index, NULL); return; } sprintf (numbuf, "%d", -index); } else { COUNT i; STRING S; index -= GLOBAL_ALLIANCE_NAME; i = GET_GAME_STATE (NEW_ALLIANCE_NAME); S = SetAbsStringTableIndex (CommData.ConversationPhrases, (index - 1) + i); strcpy (numbuf, (UNICODE *)GetStringAddress (S)); if (i == 3) strcat (numbuf, GLOBAL_SIS (CommanderName)); } pStr = numbuf; pClip = 0; pTimeStamp = 0; } else { pStr = (UNICODE *)GetStringAddress ( SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) ); pClip = GetStringSoundClip ( SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) ); pTimeStamp = GetStringTimeStamp ( SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1) ); } break; } SpliceTrack (pClip, pStr, pTimeStamp, cb); } int NPCNumberPhrase (int number, UNICODE **ptrack) { #define MAX_NUMBER_TRACKS 20 NUMBER_SPEECH speech = CommData.AlienNumberSpeech; COUNT i; int queued = 0; int toplevel = 0; UNICODE *TrackNames[MAX_NUMBER_TRACKS]; UNICODE numbuf[60]; if (!speech) return 0; if (!ptrack) { toplevel = 1; sprintf (numbuf, "%d", number); ptrack = TrackNames; } for (i = 0; i < speech->NumDigits; ++i) { SPEECH_DIGIT* dig = speech->Digits + i; int quot; quot = number / dig->Divider; if (quot == 0) continue; quot -= dig->Subtrahend; if (quot < 0) continue; if (dig->StrDigits) { COUNT index; assert (quot < 10); index = dig->StrDigits[quot]; if (index == 0) continue; index -= 1; *ptrack++ = GetStringSoundClip (SetAbsStringTableIndex ( CommData.ConversationPhrases, index )); queued++; } else { int ctracks = NPCNumberPhrase (quot, ptrack); ptrack += ctracks; queued += ctracks; } if (dig->Names != 0) { SPEECH_DIGITNAME* name; for (name = dig->Names; name->Divider; ++name) { if (number % name->Divider <= name->MaxRemainder) { *ptrack++ = GetStringSoundClip ( SetAbsStringTableIndex ( CommData.ConversationPhrases, (COUNT) (name->StrIndex - 1) )); queued++; break; } } } else if (dig->CommonNameIndex != 0) { *ptrack++ = GetStringSoundClip (SetAbsStringTableIndex ( CommData.ConversationPhrases, (COUNT) (dig->CommonNameIndex - 1) )); queued++; } number %= dig->Divider; } if (toplevel) { if (queued == 0) { // nothing queued, say "zero" *ptrack++ = GetStringSoundClip (SetAbsStringTableIndex ( CommData.ConversationPhrases, speech->Digits[speech->NumDigits - 1].StrDigits[0] )); } *ptrack++ = NULL; // term SpliceMultiTrack (TrackNames, numbuf); } return queued; } void GetAllianceName (UNICODE *buf, RESPONSE_REF name_1) { COUNT i; STRING S; i = GET_GAME_STATE (NEW_ALLIANCE_NAME); S = SetAbsStringTableIndex (CommData.ConversationPhrases, (name_1 - 1) + i); // XXX: this should someday be changed so that the function takes // the buffer size as an argument strcpy (buf, (UNICODE *)GetStringAddress (S)); if (i == 3) { strcat (buf, GLOBAL_SIS (CommanderName)); strcat (buf, (UNICODE *)GetStringAddress (SetRelStringTableIndex (S, 1))); } } void construct_response (UNICODE *buf, int R /* promoted from RESPONSE_REF */, ...) { UNICODE *buf_start = buf; UNICODE *name; va_list vlist; va_start (vlist, R); do { COUNT len; STRING S; S = SetAbsStringTableIndex (CommData.ConversationPhrases, R - 1); strcpy (buf, (UNICODE *)GetStringAddress (S)); len = strlen (buf); buf += len; name = va_arg (vlist, UNICODE *); if (name) { len = strlen (name); strncpy (buf, name, len); buf += len; /* if ((R = va_arg (vlist, RESPONSE_REF)) == (RESPONSE_REF)-1) name = 0; */ R = va_arg(vlist, int); if (R == ((RESPONSE_REF) -1)) name = 0; } } while (name); va_end (vlist); *buf = '\0'; // XXX: this should someday be changed so that the function takes // the buffer size as an argument if ((buf_start == shared_phrase_buf) && (buf > shared_phrase_buf + sizeof (shared_phrase_buf))) { log_add (log_Fatal, "Error: shared_phrase_buf size exceeded," " please increase!\n"); exit (EXIT_FAILURE); } } LOCDATAPTR init_race (RESOURCE comm_id) { switch (comm_id) { case ARILOU_CONVERSATION: return ((LOCDATAPTR)init_arilou_comm ()); case BLACKURQ_CONVERSATION: return ((LOCDATAPTR)init_blackurq_comm ()); case CHMMR_CONVERSATION: return ((LOCDATAPTR)init_chmmr_comm ()); case COMMANDER_CONVERSATION: if (!GET_GAME_STATE (STARBASE_AVAILABLE)) return ((LOCDATAPTR)init_commander_comm ()); else return ((LOCDATAPTR)init_starbase_comm ()); case DRUUGE_CONVERSATION: return ((LOCDATAPTR)init_druuge_comm ()); case ILWRATH_CONVERSATION: return ((LOCDATAPTR)init_ilwrath_comm ()); case MELNORME_CONVERSATION: return ((LOCDATAPTR)init_melnorme_comm ()); case MYCON_CONVERSATION: return ((LOCDATAPTR)init_mycon_comm ()); case ORZ_CONVERSATION: return ((LOCDATAPTR)init_orz_comm ()); case PKUNK_CONVERSATION: return ((LOCDATAPTR)init_pkunk_comm ()); case SHOFIXTI_CONVERSATION: return ((LOCDATAPTR)init_shofixti_comm ()); case SLYLANDRO_CONVERSATION: return ((LOCDATAPTR)init_slyland_comm ()); case SLYLANDRO_HOME_CONVERSATION: return ((LOCDATAPTR)init_slylandro_comm ()); case SPATHI_CONVERSATION: if (!(GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) & (1 << 7))) return ((LOCDATAPTR)init_spathi_comm ()); else return ((LOCDATAPTR)init_spahome_comm ()); case SUPOX_CONVERSATION: return ((LOCDATAPTR)init_supox_comm ()); case SYREEN_CONVERSATION: return ((LOCDATAPTR)init_syreen_comm ()); case TALKING_PET_CONVERSATION: return ((LOCDATAPTR)init_talkpet_comm ()); case THRADD_CONVERSATION: return ((LOCDATAPTR)init_thradd_comm ()); case UMGAH_CONVERSATION: return ((LOCDATAPTR)init_umgah_comm ()); case URQUAN_CONVERSATION: return ((LOCDATAPTR)init_urquan_comm ()); case UTWIG_CONVERSATION: return ((LOCDATAPTR)init_utwig_comm ()); case VUX_CONVERSATION: return ((LOCDATAPTR)init_vux_comm ()); case YEHAT_REBEL_CONVERSATION: return ((LOCDATAPTR)init_rebel_yehat_comm ()); case YEHAT_CONVERSATION: return ((LOCDATAPTR)init_yehat_comm ()); case ZOQFOTPIK_CONVERSATION: return ((LOCDATAPTR)init_zoqfot_comm ()); default: return ((LOCDATAPTR)init_chmmr_comm ()); } } uqm-0.6.2/sc2/src/sc2code/setupmenu.c0000644000175000017500000010573310547610304016021 0ustar joeyjoey// Copyright Michael Martin, 2004. /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "setupmenu.h" #include "controls.h" #include "options.h" #include "setup.h" #include "sounds.h" #include "libs/gfxlib.h" #include "libs/graphics/gfx_common.h" #include "libs/graphics/widgets.h" #include "libs/graphics/tfb_draw.h" #include "libs/strlib.h" #include "libs/reslib.h" #include "libs/inplib.h" #include "libs/sound/sound.h" #include "libs/resource/stringbank.h" #include "libs/log.h" #include "resinst.h" #include "nameref.h" static STRING SetupTab; typedef struct setup_menu_state { BOOLEAN (*InputFunc) (struct setup_menu_state *pInputState); COUNT MenuRepeatDelay; BOOLEAN initialized; int anim_frame_count; DWORD NextTime; } SETUP_MENU_STATE; typedef SETUP_MENU_STATE *PSETUP_MENU_STATE; static BOOLEAN DoSetupMenu (PSETUP_MENU_STATE pInputState); static BOOLEAN done; static WIDGET *current, *next; static int quit_main_menu (WIDGET *self, int event); static int quit_sub_menu (WIDGET *self, int event); static int do_graphics (WIDGET *self, int event); static int do_audio (WIDGET *self, int event); static int do_engine (WIDGET *self, int event); static int do_resources (WIDGET *self, int event); static int do_keyconfig (WIDGET *self, int event); static int do_advanced (WIDGET *self, int event); static int do_editkeys (WIDGET *self, int event); static void change_template (WIDGET_CHOICE *self, int oldval); static void rename_template (WIDGET_TEXTENTRY *self); static void rebind_control (WIDGET_CONTROLENTRY *widget); static void clear_control (WIDGET_CONTROLENTRY *widget); #ifdef HAVE_OPENGL #define RES_OPTS 4 #else #define RES_OPTS 2 #endif #define MENU_COUNT 8 #define CHOICE_COUNT 21 #define SLIDER_COUNT 3 #define BUTTON_COUNT 10 #define LABEL_COUNT 4 #define TEXTENTRY_COUNT 1 #define CONTROLENTRY_COUNT 7 /* The space for our widgets */ static WIDGET_MENU_SCREEN menus[MENU_COUNT]; static WIDGET_CHOICE choices[CHOICE_COUNT]; static WIDGET_SLIDER sliders[SLIDER_COUNT]; static WIDGET_BUTTON buttons[BUTTON_COUNT]; static WIDGET_LABEL labels[LABEL_COUNT]; static WIDGET_TEXTENTRY textentries[TEXTENTRY_COUNT]; static WIDGET_CONTROLENTRY controlentries[CONTROLENTRY_COUNT]; /* The hardcoded data that isn't strings */ typedef int (*HANDLER)(WIDGET *, int); static int choice_widths[CHOICE_COUNT] = { 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 3, 3, 2, 3, 3, 3 }; static HANDLER button_handlers[BUTTON_COUNT] = { quit_main_menu, quit_sub_menu, do_graphics, do_engine, do_audio, do_resources, do_keyconfig, do_advanced, do_editkeys, do_keyconfig }; static int menu_sizes[MENU_COUNT] = { 7, 5, 6, 9, 2, 5, #ifdef HAVE_OPENGL 5, #else 4, #endif 11 }; static int menu_bgs[MENU_COUNT] = { 0, 1, 1, 2, 3, 1, 2, 1 }; /* These refer to uninitialized widgets, but that's OK; we'll fill * them in before we touch them */ static WIDGET *main_widgets[] = { (WIDGET *)(&buttons[2]), (WIDGET *)(&buttons[3]), (WIDGET *)(&buttons[4]), (WIDGET *)(&buttons[5]), (WIDGET *)(&buttons[6]), (WIDGET *)(&buttons[7]), (WIDGET *)(&buttons[0]) }; static WIDGET *graphics_widgets[] = { (WIDGET *)(&choices[0]), (WIDGET *)(&choices[10]), (WIDGET *)(&choices[2]), (WIDGET *)(&choices[3]), (WIDGET *)(&buttons[1]) }; static WIDGET *audio_widgets[] = { (WIDGET *)(&sliders[0]), (WIDGET *)(&sliders[1]), (WIDGET *)(&sliders[2]), (WIDGET *)(&choices[14]), (WIDGET *)(&choices[9]), (WIDGET *)(&buttons[1]) }; static WIDGET *engine_widgets[] = { (WIDGET *)(&choices[4]), (WIDGET *)(&choices[5]), (WIDGET *)(&choices[6]), (WIDGET *)(&choices[7]), (WIDGET *)(&choices[8]), (WIDGET *)(&choices[13]), (WIDGET *)(&choices[11]), (WIDGET *)(&choices[17]), (WIDGET *)(&buttons[1]) }; static WIDGET *advanced_widgets[] = { #ifdef HAVE_OPENGL (WIDGET *)(&choices[1]), #endif (WIDGET *)(&choices[12]), (WIDGET *)(&choices[15]), (WIDGET *)(&choices[16]), (WIDGET *)(&buttons[1]) }; static WIDGET *keyconfig_widgets[] = { (WIDGET *)(&choices[18]), (WIDGET *)(&choices[19]), (WIDGET *)(&labels[1]), (WIDGET *)(&buttons[8]), (WIDGET *)(&buttons[1]) }; static WIDGET *editkeys_widgets[] = { (WIDGET *)(&choices[20]), (WIDGET *)(&labels[2]), (WIDGET *)(&textentries[0]), (WIDGET *)(&controlentries[0]), (WIDGET *)(&controlentries[1]), (WIDGET *)(&controlentries[2]), (WIDGET *)(&controlentries[3]), (WIDGET *)(&controlentries[4]), (WIDGET *)(&controlentries[5]), (WIDGET *)(&controlentries[6]), (WIDGET *)(&buttons[9]) }; static WIDGET *incomplete_widgets[] = { (WIDGET *)(&labels[0]), (WIDGET *)(&buttons[1]) }; static WIDGET **menu_widgets[MENU_COUNT] = { main_widgets, graphics_widgets, audio_widgets, engine_widgets, incomplete_widgets, keyconfig_widgets, advanced_widgets, editkeys_widgets }; static int quit_main_menu (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { next = NULL; return TRUE; } (void)self; return FALSE; } static int quit_sub_menu (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { next = (WIDGET *)(&menus[0]); (*next->receiveFocus) (next, WIDGET_EVENT_SELECT); return TRUE; } (void)self; return FALSE; } static int do_graphics (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { next = (WIDGET *)(&menus[1]); (*next->receiveFocus) (next, WIDGET_EVENT_DOWN); return TRUE; } (void)self; return FALSE; } static int do_audio (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { next = (WIDGET *)(&menus[2]); (*next->receiveFocus) (next, WIDGET_EVENT_DOWN); return TRUE; } (void)self; return FALSE; } static int do_engine (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { next = (WIDGET *)(&menus[3]); (*next->receiveFocus) (next, WIDGET_EVENT_DOWN); return TRUE; } (void)self; return FALSE; } static int do_resources (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { next = (WIDGET *)(&menus[4]); (*next->receiveFocus) (next, WIDGET_EVENT_DOWN); return TRUE; } (void)self; return FALSE; } static int do_keyconfig (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { next = (WIDGET *)(&menus[5]); (*next->receiveFocus) (next, WIDGET_EVENT_DOWN); return TRUE; } (void)self; return FALSE; } static int do_advanced (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { next = (WIDGET *)(&menus[6]); (*next->receiveFocus) (next, WIDGET_EVENT_DOWN); return TRUE; } (void)self; return FALSE; } static void populate_editkeys (int template) { int i, j; strncpy (textentries[0].value, input_templates[template].name, textentries[0].maxlen); textentries[0].value[textentries[0].maxlen-1] = 0; for (i = 0; i < NUM_KEYS; i++) { for (j = 0; j < 2; j++) { InterrogateInputState (template, i, j, controlentries[i].controlname[j], WIDGET_CONTROLENTRY_WIDTH); } } } static int do_editkeys (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { next = (WIDGET *)(&menus[7]); /* Prepare the components */ choices[20].selected = 0; populate_editkeys (0); (*next->receiveFocus) (next, WIDGET_EVENT_DOWN); return TRUE; } (void)self; return FALSE; } static void change_template (WIDGET_CHOICE *self, int oldval) { populate_editkeys (self->selected); } static void rename_template (WIDGET_TEXTENTRY *self) { /* TODO: This will have to change if the size of the input_templates name is changed. It would probably be nice to track this symbolically or ensure that self->value's buffer is always at least this big; this will require some reworking of widgets */ strncpy (input_templates[choices[20].selected].name, self->value, 30); input_templates[choices[20].selected].name[29] = 0; } #define NUM_STEPS 20 #define X_STEP (SCREEN_WIDTH / NUM_STEPS) #define Y_STEP (SCREEN_HEIGHT / NUM_STEPS) #define MENU_FRAME_RATE (ONE_SECOND / 20) static void SetDefaults (void) { GLOBALOPTS opts; GetGlobalOptions (&opts); if (opts.res == OPTVAL_CUSTOM) { choices[0].numopts = RES_OPTS + 1; } else { choices[0].numopts = RES_OPTS; } choices[0].selected = opts.res; choices[1].selected = opts.driver; choices[2].selected = opts.scaler; choices[3].selected = opts.scanlines; choices[4].selected = opts.menu; choices[5].selected = opts.text; choices[6].selected = opts.cscan; choices[7].selected = opts.scroll; choices[8].selected = opts.subtitles; choices[9].selected = opts.music; choices[10].selected = opts.fullscreen; choices[11].selected = opts.intro; choices[12].selected = opts.fps; choices[13].selected = opts.meleezoom; choices[14].selected = opts.stereo; choices[15].selected = opts.adriver; choices[16].selected = opts.aquality; choices[17].selected = opts.shield; choices[18].selected = opts.player1; choices[19].selected = opts.player2; choices[20].selected = 0; sliders[0].value = opts.musicvol; sliders[1].value = opts.sfxvol; sliders[2].value = opts.speechvol; } static void PropagateResults (void) { GLOBALOPTS opts; opts.res = choices[0].selected; opts.driver = choices[1].selected; opts.scaler = choices[2].selected; opts.scanlines = choices[3].selected; opts.menu = choices[4].selected; opts.text = choices[5].selected; opts.cscan = choices[6].selected; opts.scroll = choices[7].selected; opts.subtitles = choices[8].selected; opts.music = choices[9].selected; opts.fullscreen = choices[10].selected; opts.intro = choices[11].selected; opts.fps = choices[12].selected; opts.meleezoom = choices[13].selected; opts.stereo = choices[14].selected; opts.adriver = choices[15].selected; opts.aquality = choices[16].selected; opts.shield = choices[17].selected; opts.player1 = choices[18].selected; opts.player2 = choices[19].selected; opts.musicvol = sliders[0].value; opts.sfxvol = sliders[1].value; opts.speechvol = sliders[2].value; SetGlobalOptions (&opts); } static BOOLEAN DoSetupMenu (PSETUP_MENU_STATE pInputState) { if (!pInputState->initialized) { SetDefaultMenuRepeatDelay (); pInputState->NextTime = GetTimeCounter (); SetDefaults (); current = NULL; next = (WIDGET *)(&menus[0]); (*next->receiveFocus) (next, WIDGET_EVENT_DOWN); pInputState->initialized = TRUE; } if (current != next) { SetTransitionSource (NULL); } BatchGraphics (); (*next->draw)(next, 0, 0); if (current != next) { ScreenTransition (3, NULL); current = next; } UnbatchGraphics (); if (PulsedInputState.menu[KEY_MENU_UP]) { Widget_Event (WIDGET_EVENT_UP); } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { Widget_Event (WIDGET_EVENT_DOWN); } else if (PulsedInputState.menu[KEY_MENU_LEFT]) { Widget_Event (WIDGET_EVENT_LEFT); } else if (PulsedInputState.menu[KEY_MENU_RIGHT]) { Widget_Event (WIDGET_EVENT_RIGHT); } if (PulsedInputState.menu[KEY_MENU_SELECT]) { Widget_Event (WIDGET_EVENT_SELECT); } if (PulsedInputState.menu[KEY_MENU_CANCEL]) { Widget_Event (WIDGET_EVENT_CANCEL); } if (PulsedInputState.menu[KEY_MENU_DELETE]) { Widget_Event (WIDGET_EVENT_DELETE); } SleepThreadUntil (pInputState->NextTime + MENU_FRAME_RATE); pInputState->NextTime = GetTimeCounter (); return !((GLOBAL (CurrentActivity) & CHECK_ABORT) || (next == NULL)); } static void redraw_menu (void) { BatchGraphics (); (*next->draw)(next, 0, 0); UnbatchGraphics (); } static BOOLEAN OnTextEntryChange (PTEXTENTRY_STATE pTES) { WIDGET_TEXTENTRY *widget = (WIDGET_TEXTENTRY *) pTES->CbParam; widget->cursor_pos = pTES->CursorPos; if (pTES->JoystickMode) widget->state |= WTE_BLOCKCUR; else widget->state &= ~WTE_BLOCKCUR; // XXX TODO: Here, we can examine the text entered so far // to make sure it fits on the screen, for example, // and return FALSE to disallow the last change return TRUE; // allow change } static BOOLEAN OnTextEntryFrame (PTEXTENTRY_STATE pTES) { WIDGET_TEXTENTRY *widget = (WIDGET_TEXTENTRY *) pTES->CbParam; redraw_menu (); SleepThreadUntil (pTES->NextTime); pTES->NextTime = GetTimeCounter () + MENU_FRAME_RATE; return TRUE; // continue } static int OnTextEntryEvent (WIDGET_TEXTENTRY *widget) { // Going to edit the text TEXTENTRY_STATE tes; UNICODE revert_buf[256]; // position cursor at the end of text widget->cursor_pos = utf8StringCount (widget->value); widget->state = WTE_EDITING; redraw_menu (); // make a backup copy for revert on cancel utf8StringCopy (revert_buf, sizeof (revert_buf), widget->value); // text entry setup tes.Initialized = FALSE; tes.MenuRepeatDelay = 0; tes.NextTime = GetTimeCounter () + MENU_FRAME_RATE; tes.BaseStr = widget->value; tes.MaxSize = widget->maxlen; tes.CursorPos = widget->cursor_pos; tes.CbParam = widget; tes.ChangeCallback = OnTextEntryChange; tes.FrameCallback = OnTextEntryFrame; SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_SELECT); if (!DoTextEntry (&tes)) { // editing failed (canceled) -- revert the changes utf8StringCopy (widget->value, widget->maxlen, revert_buf); } else { if (widget->onChange) { (*(widget->onChange))(widget); } } widget->state = WTE_NORMAL; redraw_menu (); return TRUE; // event handled } static void rebind_control (WIDGET_CONTROLENTRY *widget) { int template = choices[20].selected; int control = widget->controlindex; int index = widget->highlighted; FlushInput (); DrawLabelAsWindow (&labels[3]); RebindInputState (template, control, index); populate_editkeys (template); FlushInput (); } static void clear_control (WIDGET_CONTROLENTRY *widget) { int template = choices[20].selected; int control = widget->controlindex; int index = widget->highlighted; RemoveInputState (template, control, index); populate_editkeys (template); } static stringbank *bank = NULL; static FRAME setup_frame = NULL; static void init_widgets (void) { const char *buffer[100], *str, *title; int count, i, index; if (bank == NULL) { bank = StringBank_Create (); } if (setup_frame == NULL) { setup_frame = CaptureDrawable (LoadGraphic (MENUBKG_PMAP_ANIM)); } count = GetStringTableCount (SetupTab); if (count < 3) { log_add (log_Fatal, "PANIC: Setup string table too short to even hold all indices!"); exit (EXIT_FAILURE); } /* Menus */ title = StringBank_AddOrFindString (bank, GetStringAddress (SetAbsStringTableIndex (SetupTab, 0))); if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, 1)), '\n', 100, buffer, bank) != MENU_COUNT) { /* TODO: Ignore extras instead of dying. */ log_add (log_Fatal, "PANIC: Incorrect number of Menu Subtitles"); exit (EXIT_FAILURE); } for (i = 0; i < MENU_COUNT; i++) { menus[i].tag = WIDGET_TYPE_MENU_SCREEN; menus[i].parent = NULL; menus[i].handleEvent = Widget_HandleEventMenuScreen; menus[i].receiveFocus = Widget_ReceiveFocusMenuScreen; menus[i].draw = Widget_DrawMenuScreen; menus[i].height = Widget_HeightFullScreen; menus[i].width = Widget_WidthFullScreen; menus[i].title = title; menus[i].subtitle = buffer[i]; menus[i].bgStamp.origin.x = 0; menus[i].bgStamp.origin.y = 0; menus[i].bgStamp.frame = SetAbsFrameIndex (setup_frame, menu_bgs[i]); menus[i].num_children = menu_sizes[i]; menus[i].child = menu_widgets[i]; menus[i].highlighted = 0; } /* Options */ if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, 2)), '\n', 100, buffer, bank) != CHOICE_COUNT) { log_add (log_Fatal, "PANIC: Incorrect number of Choice Options"); exit (EXIT_FAILURE); } for (i = 0; i < CHOICE_COUNT; i++) { choices[i].tag = WIDGET_TYPE_CHOICE; choices[i].parent = NULL; choices[i].handleEvent = Widget_HandleEventChoice; choices[i].receiveFocus = Widget_ReceiveFocusChoice; choices[i].draw = Widget_DrawChoice; choices[i].height = Widget_HeightChoice; choices[i].width = Widget_WidthFullScreen; choices[i].category = buffer[i]; choices[i].numopts = 0; choices[i].options = NULL; choices[i].selected = 0; choices[i].highlighted = 0; choices[i].maxcolumns = choice_widths[i]; choices[i].onChange = NULL; } /* Fill in the options now */ index = 3; /* Index into string table */ for (i = 0; i < CHOICE_COUNT; i++) { int j, optcount; if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading choices"); exit (EXIT_FAILURE); } str = GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)); optcount = SplitString (str, '\n', 100, buffer, bank); choices[i].numopts = optcount; choices[i].options = HMalloc (optcount * sizeof (CHOICE_OPTION)); for (j = 0; j < optcount; j++) { choices[i].options[j].optname = buffer[j]; choices[i].options[j].tooltip[0] = ""; choices[i].options[j].tooltip[1] = ""; choices[i].options[j].tooltip[2] = ""; } for (j = 0; j < optcount; j++) { int k, tipcount; if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading choices"); exit (EXIT_FAILURE); } str = GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)); tipcount = SplitString (str, '\n', 100, buffer, bank); if (tipcount > 3) { tipcount = 3; } for (k = 0; k < tipcount; k++) { choices[i].options[j].tooltip[k] = buffer[k]; } } } /* The first choice is resolution, and is handled specially */ choices[0].numopts = RES_OPTS; /* Choices 18-20 are also special, being the names of the key configurations */ for (i = 0; i < 6; i++) { choices[18].options[i].optname = input_templates[i].name; choices[19].options[i].optname = input_templates[i].name; choices[20].options[i].optname = input_templates[i].name; } /* Choice 20 has a special onChange handler, too. */ choices[20].onChange = change_template; /* Sliders */ if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading sliders"); exit (EXIT_FAILURE); } if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)), '\n', 100, buffer, bank) != SLIDER_COUNT) { /* TODO: Ignore extras instead of dying. */ log_add (log_Fatal, "PANIC: Incorrect number of Slider Options"); exit (EXIT_FAILURE); } for (i = 0; i < SLIDER_COUNT; i++) { sliders[i].tag = WIDGET_TYPE_SLIDER; sliders[i].parent = NULL; sliders[i].handleEvent = Widget_HandleEventSlider; sliders[i].receiveFocus = Widget_ReceiveFocusSimple; sliders[i].draw = Widget_DrawSlider; sliders[i].height = Widget_HeightOneLine; sliders[i].width = Widget_WidthFullScreen; sliders[i].draw_value = Widget_Slider_DrawValue; sliders[i].min = 0; sliders[i].max = 100; sliders[i].step = 5; sliders[i].value = 75; sliders[i].category = buffer[i]; sliders[i].tooltip[0] = ""; sliders[i].tooltip[1] = ""; sliders[i].tooltip[2] = ""; } for (i = 0; i < SLIDER_COUNT; i++) { int j, tipcount; if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading sliders"); exit (EXIT_FAILURE); } str = GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)); tipcount = SplitString (str, '\n', 100, buffer, bank); if (tipcount > 3) { tipcount = 3; } for (j = 0; j < tipcount; j++) { sliders[i].tooltip[j] = buffer[j]; } } /* Buttons */ if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading buttons"); exit (EXIT_FAILURE); } if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)), '\n', 100, buffer, bank) != BUTTON_COUNT) { /* TODO: Ignore extras instead of dying. */ log_add (log_Fatal, "PANIC: Incorrect number of Button Options"); exit (EXIT_FAILURE); } for (i = 0; i < BUTTON_COUNT; i++) { buttons[i].tag = WIDGET_TYPE_BUTTON; buttons[i].parent = NULL; buttons[i].handleEvent = button_handlers[i]; buttons[i].receiveFocus = Widget_ReceiveFocusSimple; buttons[i].draw = Widget_DrawButton; buttons[i].height = Widget_HeightOneLine; buttons[i].width = Widget_WidthFullScreen; buttons[i].name = buffer[i]; buttons[i].tooltip[0] = ""; buttons[i].tooltip[1] = ""; buttons[i].tooltip[2] = ""; } for (i = 0; i < BUTTON_COUNT; i++) { int j, tipcount; if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading buttons"); exit (EXIT_FAILURE); } str = GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)); tipcount = SplitString (str, '\n', 100, buffer, bank); if (tipcount > 3) { tipcount = 3; } for (j = 0; j < tipcount; j++) { buttons[i].tooltip[j] = buffer[j]; } } /* Labels */ if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading labels"); exit (EXIT_FAILURE); } if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)), '\n', 100, buffer, bank) != LABEL_COUNT) { /* TODO: Ignore extras instead of dying. */ log_add (log_Fatal, "PANIC: Incorrect number of Label Options"); exit (EXIT_FAILURE); } for (i = 0; i < LABEL_COUNT; i++) { labels[i].tag = WIDGET_TYPE_LABEL; labels[i].parent = NULL; labels[i].handleEvent = Widget_HandleEventIgnoreAll; labels[i].receiveFocus = Widget_ReceiveFocusRefuseFocus; labels[i].draw = Widget_DrawLabel; labels[i].height = Widget_HeightLabel; labels[i].width = Widget_WidthFullScreen; labels[i].line_count = 0; labels[i].lines = NULL; } for (i = 0; i < LABEL_COUNT; i++) { int j, linecount; if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading labels"); exit (EXIT_FAILURE); } str = GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)); linecount = SplitString (str, '\n', 100, buffer, bank); labels[i].line_count = linecount; labels[i].lines = (const char **)HMalloc(linecount * sizeof(const char *)); for (j = 0; j < linecount; j++) { labels[i].lines[j] = buffer[j]; } } /* Text Entry boxes */ if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading text entries"); exit (EXIT_FAILURE); } if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)), '\n', 100, buffer, bank) != TEXTENTRY_COUNT) { log_add (log_Fatal, "PANIC: Incorrect number of Text Entries"); exit (EXIT_FAILURE); } for (i = 0; i < TEXTENTRY_COUNT; i++) { textentries[i].tag = WIDGET_TYPE_TEXTENTRY; textentries[i].parent = NULL; textentries[i].handleEvent = Widget_HandleEventTextEntry; textentries[i].receiveFocus = Widget_ReceiveFocusSimple; textentries[i].draw = Widget_DrawTextEntry; textentries[i].height = Widget_HeightOneLine; textentries[i].width = Widget_WidthFullScreen; textentries[i].handleEventSelect = OnTextEntryEvent; textentries[i].category = buffer[i]; textentries[i].value[0] = 0; textentries[i].maxlen = WIDGET_TEXTENTRY_WIDTH-1; textentries[i].state = WTE_NORMAL; textentries[i].cursor_pos = 0; } if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading text entries"); exit (EXIT_FAILURE); } if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)), '\n', 100, buffer, bank) != TEXTENTRY_COUNT) { /* TODO: Ignore extras instead of dying. */ log_add (log_Fatal, "PANIC: Incorrect number of Text Entries"); exit (EXIT_FAILURE); } for (i = 0; i < TEXTENTRY_COUNT; i++) { strncpy (textentries[i].value, buffer[i], textentries[i].maxlen); textentries[i].value[textentries[i].maxlen] = 0; } textentries[0].onChange = rename_template; /* Control Entry boxes */ if (index >= count) { log_add (log_Fatal, "PANIC: String table cut short while reading control entries"); exit (EXIT_FAILURE); } if (SplitString (GetStringAddress (SetAbsStringTableIndex (SetupTab, index++)), '\n', 100, buffer, bank) != CONTROLENTRY_COUNT) { log_add (log_Fatal, "PANIC: Incorrect number of Control Entries"); exit (EXIT_FAILURE); } for (i = 0; i < CONTROLENTRY_COUNT; i++) { controlentries[i].tag = WIDGET_TYPE_CONTROLENTRY; controlentries[i].parent = NULL; controlentries[i].handleEvent = Widget_HandleEventControlEntry; controlentries[i].receiveFocus = Widget_ReceiveFocusControlEntry; controlentries[i].draw = Widget_DrawControlEntry; controlentries[i].height = Widget_HeightOneLine; controlentries[i].width = Widget_WidthFullScreen; controlentries[i].category = buffer[i]; controlentries[i].highlighted = 0; controlentries[i].controlname[0][0] = 0; controlentries[i].controlname[1][0] = 0; controlentries[i].controlindex = i; controlentries[i].onChange = rebind_control; controlentries[i].onDelete = clear_control; } /* Check for garbage at the end */ if (index < count) { log_add (log_Warning, "WARNING: Setup strings had %d garbage entries at the end.", count - index); } } static void clean_up_widgets (void) { int i; for (i = 0; i < CHOICE_COUNT; i++) { if (choices[i].options) { HFree (choices[i].options); } } for (i = 0; i < LABEL_COUNT; i++) { if (labels[i].lines) { HFree (labels[i].lines); } } /* Clear out the master tables */ if (SetupTab) { DestroyStringTable (ReleaseStringTable (SetupTab)); SetupTab = 0; } if (bank) { StringBank_Free (bank); bank = NULL; } if (setup_frame) { DestroyDrawable (ReleaseDrawable (setup_frame)); setup_frame = NULL; } } void SetupMenu (void) { SETUP_MENU_STATE s; s.InputFunc = DoSetupMenu; s.initialized = FALSE; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); SetupTab = CaptureStringTable (LoadStringTable (SETUP_MENU_STRTAB)); if (SetupTab) { init_widgets (); } else { log_add (log_Fatal, "PANIC: Could not find strings for the setup menu!"); exit (EXIT_FAILURE); } done = FALSE; DoInput ((PVOID)&s, TRUE); GLOBAL (CurrentActivity) &= ~CHECK_ABORT; PropagateResults (); if (SetupTab) { clean_up_widgets (); } } void GetGlobalOptions (GLOBALOPTS *opts) { if (GfxFlags & TFB_GFXFLAGS_SCALE_BILINEAR) { opts->scaler = OPTVAL_BILINEAR_SCALE; } else if (GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPT) { opts->scaler = OPTVAL_BIADAPT_SCALE; } else if (GfxFlags & TFB_GFXFLAGS_SCALE_BIADAPTADV) { opts->scaler = OPTVAL_BIADV_SCALE; } else if (GfxFlags & TFB_GFXFLAGS_SCALE_TRISCAN) { opts->scaler = OPTVAL_TRISCAN_SCALE; } else if (GfxFlags & TFB_GFXFLAGS_SCALE_HQXX) { opts->scaler = OPTVAL_HQXX_SCALE; } else { opts->scaler = OPTVAL_NO_SCALE; } opts->fullscreen = (GfxFlags & TFB_GFXFLAGS_FULLSCREEN) ? OPTVAL_ENABLED : OPTVAL_DISABLED; opts->subtitles = optSubtitles ? OPTVAL_ENABLED : OPTVAL_DISABLED; opts->scanlines = (GfxFlags & TFB_GFXFLAGS_SCANLINES) ? OPTVAL_ENABLED : OPTVAL_DISABLED; opts->menu = (optWhichMenu == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC; opts->text = (optWhichFonts == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC; opts->cscan = (optWhichCoarseScan == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC; opts->scroll = (optSmoothScroll == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC; opts->intro = (optWhichIntro == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC; opts->shield = (optWhichShield == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC; opts->fps = (GfxFlags & TFB_GFXFLAGS_SHOWFPS) ? OPTVAL_ENABLED : OPTVAL_DISABLED; opts->meleezoom = (optMeleeScale == TFB_SCALE_TRILINEAR) ? OPTVAL_3DO : OPTVAL_PC; opts->stereo = optStereoSFX ? OPTVAL_ENABLED : OPTVAL_DISABLED; /* These values are read in, but won't change during a run. */ opts->music = (optWhichMusic == OPT_3DO) ? OPTVAL_3DO : OPTVAL_PC; switch (snddriver) { case audio_DRIVER_OPENAL: opts->adriver = OPTVAL_OPENAL; break; case audio_DRIVER_MIXSDL: opts->adriver = OPTVAL_MIXSDL; break; default: opts->adriver = OPTVAL_SILENCE; break; } if (soundflags & audio_QUALITY_HIGH) { opts->aquality = OPTVAL_HIGH; } else if (soundflags & audio_QUALITY_LOW) { opts->aquality = OPTVAL_LOW; } else { opts->aquality = OPTVAL_MEDIUM; } /* Work out resolution. On the way, try to guess a good default * for config.alwaysgl, then overwrite it if it was set previously. */ opts->driver = OPTVAL_PURE_IF_POSSIBLE; switch (ScreenWidthActual) { case 320: if (GraphicsDriver == TFB_GFXDRIVER_SDL_PURE) { opts->res = OPTVAL_320_240; } else { if (ScreenHeightActual != 240) { opts->res = OPTVAL_CUSTOM; } else { opts->res = OPTVAL_320_240; opts->driver = OPTVAL_ALWAYS_GL; } } break; case 640: if (GraphicsDriver == TFB_GFXDRIVER_SDL_PURE) { opts->res = OPTVAL_640_480; } else { if (ScreenHeightActual != 480) { opts->res = OPTVAL_CUSTOM; } else { opts->res = OPTVAL_640_480; opts->driver = OPTVAL_ALWAYS_GL; } } break; case 800: if (ScreenHeightActual != 600) { opts->res = OPTVAL_CUSTOM; } else { opts->res = OPTVAL_800_600; } break; case 1024: if (ScreenHeightActual != 768) { opts->res = OPTVAL_CUSTOM; } else { opts->res = OPTVAL_1024_768; } break; default: opts->res = OPTVAL_CUSTOM; break; } if (res_HasKey ("config.alwaysgl")) { if (res_GetBoolean ("config.alwaysgl")) { opts->driver = OPTVAL_ALWAYS_GL; } else { opts->driver = OPTVAL_PURE_IF_POSSIBLE; } } opts->player1 = PlayerOne; opts->player2 = PlayerTwo; opts->musicvol = (((int)(musicVolumeScale * 100.0f) + 2) / 5) * 5; opts->sfxvol = (((int)(sfxVolumeScale * 100.0f) + 2) / 5) * 5; opts->speechvol = (((int)(speechVolumeScale * 100.0f) + 2) / 5) * 5; } void SetGlobalOptions (GLOBALOPTS *opts) { int NewGfxFlags = GfxFlags; int NewWidth = ScreenWidthActual; int NewHeight = ScreenHeightActual; int NewDriver = GraphicsDriver; NewGfxFlags &= ~TFB_GFXFLAGS_SCALE_ANY; switch (opts->res) { case OPTVAL_320_240: NewWidth = 320; NewHeight = 240; #ifdef HAVE_OPENGL NewDriver = (opts->driver == OPTVAL_ALWAYS_GL ? TFB_GFXDRIVER_SDL_OPENGL : TFB_GFXDRIVER_SDL_PURE); #else NewDriver = TFB_GFXDRIVER_SDL_PURE; #endif break; case OPTVAL_640_480: NewWidth = 640; NewHeight = 480; #ifdef HAVE_OPENGL NewDriver = (opts->driver == OPTVAL_ALWAYS_GL ? TFB_GFXDRIVER_SDL_OPENGL : TFB_GFXDRIVER_SDL_PURE); #else NewDriver = TFB_GFXDRIVER_SDL_PURE; #endif break; case OPTVAL_800_600: NewWidth = 800; NewHeight = 600; NewDriver = TFB_GFXDRIVER_SDL_OPENGL; break; case OPTVAL_1024_768: NewWidth = 1024; NewHeight = 768; NewDriver = TFB_GFXDRIVER_SDL_OPENGL; break; default: /* Don't mess with the custom value */ break; } res_PutInteger ("config.reswidth", NewWidth); res_PutInteger ("config.resheight", NewHeight); res_PutBoolean ("config.alwaysgl", opts->driver == OPTVAL_ALWAYS_GL); res_PutBoolean ("config.usegl", NewDriver == TFB_GFXDRIVER_SDL_OPENGL); switch (opts->scaler) { case OPTVAL_BILINEAR_SCALE: NewGfxFlags |= TFB_GFXFLAGS_SCALE_BILINEAR; res_PutString ("config.scaler", "bilinear"); break; case OPTVAL_BIADAPT_SCALE: NewGfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPT; res_PutString ("config.scaler", "biadapt"); break; case OPTVAL_BIADV_SCALE: NewGfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPTADV; res_PutString ("config.scaler", "biadv"); break; case OPTVAL_TRISCAN_SCALE: NewGfxFlags |= TFB_GFXFLAGS_SCALE_TRISCAN; res_PutString ("config.scaler", "triscan"); break; case OPTVAL_HQXX_SCALE: NewGfxFlags |= TFB_GFXFLAGS_SCALE_HQXX; res_PutString ("config.scaler", "hq"); break; default: /* OPTVAL_NO_SCALE has no equivalent in gfxflags. */ res_PutString ("config.scaler", "no"); break; } if (opts->scanlines) { NewGfxFlags |= TFB_GFXFLAGS_SCANLINES; } else { NewGfxFlags &= ~TFB_GFXFLAGS_SCANLINES; } if (opts->fullscreen) NewGfxFlags |= TFB_GFXFLAGS_FULLSCREEN; else NewGfxFlags &= ~TFB_GFXFLAGS_FULLSCREEN; res_PutBoolean ("config.scanlines", opts->scanlines); res_PutBoolean ("config.fullscreen", opts->fullscreen); if ((NewWidth != ScreenWidthActual) || (NewHeight != ScreenHeightActual) || (NewDriver != GraphicsDriver) || (NewGfxFlags != GfxFlags)) { FlushGraphics (); TFB_DrawScreen_ReinitVideo (NewDriver, NewGfxFlags, NewWidth, NewHeight); FlushGraphics (); } optSubtitles = (opts->subtitles == OPTVAL_ENABLED) ? TRUE : FALSE; // optWhichMusic = (opts->music == OPTVAL_3DO) ? OPT_3DO : OPT_PC; optWhichMenu = (opts->menu == OPTVAL_3DO) ? OPT_3DO : OPT_PC; optWhichFonts = (opts->text == OPTVAL_3DO) ? OPT_3DO : OPT_PC; optWhichCoarseScan = (opts->cscan == OPTVAL_3DO) ? OPT_3DO : OPT_PC; optSmoothScroll = (opts->scroll == OPTVAL_3DO) ? OPT_3DO : OPT_PC; optWhichShield = (opts->shield == OPTVAL_3DO) ? OPT_3DO : OPT_PC; optMeleeScale = (opts->meleezoom == OPTVAL_3DO) ? TFB_SCALE_TRILINEAR : TFB_SCALE_STEP; optWhichIntro = (opts->intro == OPTVAL_3DO) ? OPT_3DO : OPT_PC; PlayerOne = opts->player1; PlayerTwo = opts->player2; res_PutBoolean ("config.subtitles", opts->subtitles == OPTVAL_ENABLED); res_PutBoolean ("config.textmenu", opts->menu == OPTVAL_PC); res_PutBoolean ("config.textgradients", opts->text == OPTVAL_PC); res_PutBoolean ("config.iconicscan", opts->cscan == OPTVAL_3DO); res_PutBoolean ("config.smoothscroll", opts->scroll == OPTVAL_3DO); res_PutBoolean ("config.3domusic", opts->music == OPTVAL_3DO); res_PutBoolean ("config.3domovies", opts->intro == OPTVAL_3DO); res_PutBoolean ("config.showfps", opts->fps == OPTVAL_ENABLED); res_PutBoolean ("config.smoothmelee", opts->meleezoom == OPTVAL_3DO); res_PutBoolean ("config.positionalsfx", opts->stereo == OPTVAL_ENABLED); res_PutBoolean ("config.pulseshield", opts->shield == OPTVAL_3DO); res_PutInteger ("config.player1control", opts->player1); res_PutInteger ("config.player2control", opts->player2); switch (opts->adriver) { case OPTVAL_SILENCE: res_PutString ("config.audiodriver", "none"); break; case OPTVAL_MIXSDL: res_PutString ("config.audiodriver", "mixsdl"); break; case OPTVAL_OPENAL: res_PutString ("config.audiodriver", "openal"); default: /* Shouldn't happen; leave config untouched */ break; } switch (opts->aquality) { case OPTVAL_LOW: res_PutString ("config.audioquality", "low"); break; case OPTVAL_MEDIUM: res_PutString ("config.audioquality", "medium"); break; case OPTVAL_HIGH: res_PutString ("config.audioquality", "high"); break; default: /* Shouldn't happen; leave config untouched */ break; } res_PutInteger ("config.musicvol", opts->musicvol); res_PutInteger ("config.sfxvol", opts->sfxvol); res_PutInteger ("config.speechvol", opts->speechvol); musicVolumeScale = opts->musicvol / 100.0f; sfxVolumeScale = opts->sfxvol / 100.0f; speechVolumeScale = opts->speechvol / 100.0f; // update actual volumes SetMusicVolume (musicVolume); SetSpeechVolume (speechVolumeScale); res_PutString ("config.keys.1.name", input_templates[0].name); res_PutString ("config.keys.2.name", input_templates[1].name); res_PutString ("config.keys.3.name", input_templates[2].name); res_PutString ("config.keys.4.name", input_templates[3].name); res_PutString ("config.keys.5.name", input_templates[4].name); res_PutString ("config.keys.6.name", input_templates[5].name); res_SaveFilename (configDir, "uqm.cfg", "config."); SaveKeyConfiguration (configDir, "keys.cfg"); } uqm-0.6.2/sc2/src/sc2code/cnctdlg.c0000600000175000017500000003615010543202101015362 0ustar joeyjoey//Copyright Michael Martin, 2006 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef NETPLAY #include "cnctdlg.h" #include "controls.h" #include "colors.h" #include "gamestr.h" #include "setup.h" #include "resinst.h" #include "nameref.h" #include "libs/graphics/widgets.h" #include "netplay/netoptions.h" #define MCD_WIDTH 260 #define MCD_HEIGHT 110 #define MENU_FRAME_RATE (ONE_SECOND / 20) typedef struct connect_dialog_state { BOOLEAN (*InputFunc) (struct connect_dialog_state *pInputState); COUNT MenuRepeatDelay; DWORD NextTime; BOOLEAN Initialized; int which_side; int confirmed; } CONNECT_DIALOG_STATE; static void DrawConnectDialog (void); typedef CONNECT_DIALOG_STATE *PCONNECT_DIALOG_STATE; static WIDGET_MENU_SCREEN menu; static WIDGET_BUTTON buttons[3]; static WIDGET_SLIDER slider; static WIDGET_TEXTENTRY texts[2]; static WIDGET *menu_widgets[] = { (WIDGET *)&buttons[1], (WIDGET *)&texts[0], (WIDGET *)&buttons[0], (WIDGET *)&slider, (WIDGET *)&texts[1], (WIDGET *)&buttons[2] }; static BOOLEAN done; /* This kind of sucks, but the Button callbacks need access to the * CONNECT_DIALOG_STATE, so we need a pointer to it */ static PCONNECT_DIALOG_STATE current_state; static FONT PlayerFont; static int do_connect (WIDGET *self, int event); static int do_listen (WIDGET *self, int event); static int do_cancel (WIDGET *self, int event); static void MCD_DrawMenuScreen (WIDGET *_self, int x, int y) { int widget_index, widget_y; WIDGET_MENU_SCREEN *self = (WIDGET_MENU_SCREEN *)_self; widget_y = y + 8; for (widget_index = 0; widget_index < self->num_children; widget_index++) { WIDGET *c = self->child[widget_index]; (*c->draw)(c, x, widget_y); widget_y += (*c->height)(c) + 8; } } static void MCD_DrawButton (WIDGET *_self, int x, int y) { WIDGET_BUTTON *self = (WIDGET_BUTTON *)_self; COLOR oldtext; COLOR inactive, selected; FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; selected = MENU_HIGHLIGHT_COLOR; inactive = MENU_TEXT_COLOR; t.baseline.x = 160; t.baseline.y = y; t.align = ALIGN_CENTER; t.CharCount = ~0; t.pStr = self->name; if (widget_focus == _self) { oldtext = SetContextForeGroundColor (selected); } else { oldtext = SetContextForeGroundColor (inactive); } font_DrawText (&t); SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); (void) x; } static void MCD_DrawSlider (WIDGET *_self, int x, int y) { WIDGET_SLIDER *self = (WIDGET_SLIDER *)_self; COLOR oldtext; COLOR default_color, selected; FONT oldfont = SetContextFont (PlayerFont); FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; RECT r; int tick = (MCD_WIDTH) / 8; default_color = MENU_TEXT_COLOR; selected = MENU_HIGHLIGHT_COLOR; t.baseline.x = x; t.baseline.y = y; t.align = ALIGN_LEFT; t.CharCount = ~0; t.pStr = self->category; if (widget_focus == _self) { oldtext = SetContextForeGroundColor (selected); } else { oldtext = SetContextForeGroundColor (default_color); } font_DrawText (&t); r.corner.x = t.baseline.x + 3 * tick; r.corner.y = t.baseline.y - 4; r.extent.height = 2; r.extent.width = 3 * tick; DrawFilledRectangle (&r); r.extent.width = 3; r.extent.height = 8; r.corner.y = t.baseline.y - 7; r.corner.x = t.baseline.x + 3 * tick + (3 * tick * (self->value - self->min) / (self->max - self->min)) - 1; DrawFilledRectangle (&r); (*self->draw_value)(self, t.baseline.x + 7 * tick, t.baseline.y); SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); } void MCD_DrawTextEntry (WIDGET *_self, int x, int y) { WIDGET_TEXTENTRY *self = (WIDGET_TEXTENTRY *)_self; COLOR oldtext; COLOR inactive, default_color, selected; FONT oldfont = SetContextFont (PlayerFont); FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; default_color = MENU_TEXT_COLOR; selected = MENU_HIGHLIGHT_COLOR; inactive = MENU_TEXT_COLOR; BatchGraphics (); t.baseline.x = x; t.baseline.y = y; t.align = ALIGN_LEFT; t.CharCount = ~0; t.pStr = self->category; if (widget_focus == _self) { oldtext = SetContextForeGroundColor (selected); } else { oldtext = SetContextForeGroundColor (default_color); } font_DrawText (&t); /* Force string termination */ self->value[WIDGET_TEXTENTRY_WIDTH-1] = 0; t.baseline.y = y; t.CharCount = utf8StringCount (self->value); t.pStr = self->value; if (!(self->state & WTE_EDITING)) { // normal or selected state t.baseline.x = 160; t.align = ALIGN_CENTER; if (widget_focus == _self) { oldtext = SetContextForeGroundColor (selected); } else { oldtext = SetContextForeGroundColor (inactive); } font_DrawText (&t); } else { // editing state COUNT i; RECT text_r; BYTE char_deltas[WIDGET_TEXTENTRY_WIDTH]; PBYTE pchar_deltas; RECT r; SIZE leading; t.baseline.x = x + 90; t.align = ALIGN_LEFT; // calc background box dimensions // XXX: this may need some tuning, especially if a // different font is used. The font 'leading' values // are not what they should be. #define BOX_VERT_OFFSET 2 GetContextFontLeading (&leading); r.corner.x = t.baseline.x - 1; r.corner.y = t.baseline.y - leading + BOX_VERT_OFFSET; r.extent.width = MCD_WIDTH - r.corner.x - 10; r.extent.height = leading + 2; TextRect (&t, &text_r, char_deltas); #if 0 // XXX: this should potentially be used in ChangeCallback if ((text_r.extent.width + 2) >= r.extent.width) { // the text does not fit the input box size and so // will not fit when displayed later UnbatchGraphics (); // disallow the change return (FALSE); } #endif oldtext = SetContextForeGroundColor (selected); DrawFilledRectangle (&r); // calculate the cursor position and draw it pchar_deltas = char_deltas; for (i = self->cursor_pos; i > 0; --i) r.corner.x += (SIZE)*pchar_deltas++; if (self->cursor_pos < t.CharCount) /* cursor mid-line */ --r.corner.x; if (self->state & WTE_BLOCKCUR) { // Use block cursor for keyboardless systems if (self->cursor_pos == t.CharCount) { // cursor at end-line -- use insertion point r.extent.width = 1; } else if (self->cursor_pos + 1 == t.CharCount) { // extra pixel for last char margin r.extent.width = (SIZE)*pchar_deltas + 2; } else { // normal mid-line char r.extent.width = (SIZE)*pchar_deltas + 1; } } else { // Insertion point cursor r.extent.width = 1; } // position cursor within input field rect ++r.corner.x; ++r.corner.y; r.extent.height -= 2; SetContextForeGroundColor (MENU_CURSOR_COLOR); DrawFilledRectangle (&r); SetContextForeGroundColor (inactive); font_DrawText (&t); } UnbatchGraphics (); SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); } /* Text entry stuff, mostly C&Ped from setupmenu.c. Could use some * refactoring, as redraw_menu () is the only real change. */ static BOOLEAN OnTextEntryChange (PTEXTENTRY_STATE pTES) { WIDGET_TEXTENTRY *widget = (WIDGET_TEXTENTRY *) pTES->CbParam; widget->cursor_pos = pTES->CursorPos; if (pTES->JoystickMode) widget->state |= WTE_BLOCKCUR; else widget->state &= ~WTE_BLOCKCUR; // XXX TODO: Here, we can examine the text entered so far // to make sure it fits on the screen, for example, // and return FALSE to disallow the last change return TRUE; // allow change } static BOOLEAN OnTextEntryFrame (PTEXTENTRY_STATE pTES) { WIDGET_TEXTENTRY *widget = (WIDGET_TEXTENTRY *) pTES->CbParam; DrawConnectDialog (); SleepThreadUntil (pTES->NextTime); pTES->NextTime = GetTimeCounter () + MENU_FRAME_RATE; return TRUE; // continue } static int OnTextEntryEvent (WIDGET_TEXTENTRY *widget) { // Going to edit the text TEXTENTRY_STATE tes; UNICODE revert_buf[256]; // position cursor at the end of text widget->cursor_pos = utf8StringCount (widget->value); widget->state = WTE_EDITING; DrawConnectDialog (); // make a backup copy for revert on cancel utf8StringCopy (revert_buf, sizeof (revert_buf), widget->value); // text entry setup tes.Initialized = FALSE; tes.MenuRepeatDelay = 0; tes.NextTime = GetTimeCounter () + MENU_FRAME_RATE; tes.BaseStr = widget->value; tes.MaxSize = widget->maxlen; tes.CursorPos = widget->cursor_pos; tes.CbParam = widget; tes.ChangeCallback = OnTextEntryChange; tes.FrameCallback = OnTextEntryFrame; // SetMenuSounds (0, MENU_SOUND_SELECT); if (!DoTextEntry (&tes)) { // editing failed (canceled) -- revert the changes utf8StringCopy (widget->value, widget->maxlen, revert_buf); } else { if (widget->onChange) { (*(widget->onChange))(widget); } } widget->state = WTE_NORMAL; DrawConnectDialog (); return TRUE; // event handled } /* Button response routines */ static int do_connect (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { /* These assignments are safe exactly because texts[] is file-scope) */ netplayOptions.peer[current_state->which_side].host = texts[0].value; netplayOptions.peer[current_state->which_side].port = texts[1].value; netplayOptions.peer[current_state->which_side].isServer = FALSE; current_state->confirmed = TRUE; netplayOptions.inputDelay = slider.value; done = TRUE; } (void)self; return FALSE; } static int do_listen (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { /* These assignments are safe exactly because texts[] is file-scope) */ netplayOptions.peer[current_state->which_side].port = texts[1].value; netplayOptions.peer[current_state->which_side].isServer = TRUE; netplayOptions.inputDelay = slider.value; current_state->confirmed = TRUE; done = TRUE; } (void)self; return FALSE; } static int do_cancel (WIDGET *self, int event) { if (event == WIDGET_EVENT_SELECT) { current_state->confirmed = FALSE; done = TRUE; } (void)self; return FALSE; } static void CreateWidgets (void) { int i; done = false; for (i = 0; i < 3; i++) { buttons[i].tag = WIDGET_TYPE_BUTTON; buttons[i].parent = NULL; buttons[i].receiveFocus = Widget_ReceiveFocusSimple; buttons[i].draw = MCD_DrawButton; buttons[i].height = Widget_HeightOneLine; buttons[i].width = Widget_WidthFullScreen; } buttons[0].name = GAME_STRING (NETMELEE_STRING_BASE + 19); // "Connect to remote host" buttons[1].name = GAME_STRING (NETMELEE_STRING_BASE + 20); // "Wait for incoming connection" buttons[2].name = GAME_STRING (NETMELEE_STRING_BASE + 21); // "Cancel" buttons[0].handleEvent = do_connect; buttons[1].handleEvent = do_listen; buttons[2].handleEvent = do_cancel; menu.tag = WIDGET_TYPE_MENU_SCREEN; menu.parent = NULL; menu.receiveFocus = Widget_ReceiveFocusMenuScreen; menu.draw = MCD_DrawMenuScreen; menu.height = Widget_HeightFullScreen; menu.width = Widget_WidthFullScreen; menu.num_children = 6; menu.child = menu_widgets; menu.handleEvent = Widget_HandleEventMenuScreen; slider.tag = WIDGET_TYPE_SLIDER; slider.parent = NULL; slider.handleEvent = Widget_HandleEventSlider; slider.receiveFocus = Widget_ReceiveFocusSimple; slider.draw = MCD_DrawSlider; slider.height = Widget_HeightOneLine; slider.width = Widget_WidthFullScreen; slider.draw_value = Widget_Slider_DrawValue; slider.min = 0; slider.max = 9; slider.step = 1; slider.value = netplayOptions.inputDelay; slider.category = GAME_STRING (NETMELEE_STRING_BASE + 24); // "Net Delay" for (i = 0; i < 2; i++) { texts[i].tag = WIDGET_TYPE_TEXTENTRY; texts[i].parent = NULL; texts[i].handleEvent = Widget_HandleEventTextEntry; texts[i].receiveFocus = Widget_ReceiveFocusSimple; texts[i].draw = MCD_DrawTextEntry; texts[i].height = Widget_HeightOneLine; texts[i].width = Widget_WidthFullScreen; texts[i].handleEventSelect = OnTextEntryEvent; texts[i].maxlen = WIDGET_TEXTENTRY_WIDTH-1; texts[i].state = WTE_NORMAL; texts[i].cursor_pos = 0; } texts[0].category = GAME_STRING (NETMELEE_STRING_BASE + 22); // "Host" texts[1].category = GAME_STRING (NETMELEE_STRING_BASE + 23); // "Port" /* We sometimes assign to these internals; cannot strncpy over self! */ if (texts[0].value != netplayOptions.peer[current_state->which_side].host) { strncpy (texts[0].value, netplayOptions.peer[current_state->which_side].host, texts[0].maxlen); } if (texts[1].value != netplayOptions.peer[current_state->which_side].port) { strncpy (texts[1].value, netplayOptions.peer[current_state->which_side].port, texts[1].maxlen); } texts[0].value[texts[0].maxlen]=0; texts[1].value[texts[1].maxlen]=0; menu.receiveFocus ((WIDGET *)&menu, WIDGET_EVENT_DOWN); } static void DrawConnectDialog (void) { RECT r; r.extent.width = MCD_WIDTH; r.extent.height = MCD_HEIGHT; r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; LockMutex (GraphicsLock); DrawShadowedBox (&r, SHADOWBOX_BACKGROUND_COLOR, SHADOWBOX_DARK_COLOR, SHADOWBOX_MEDIUM_COLOR); menu.draw ((WIDGET *)&menu, r.corner.x + 10, r.corner.y + 10); UnlockMutex (GraphicsLock); } static BOOLEAN DoMeleeConnectDialog (PCONNECT_DIALOG_STATE state) { BOOLEAN changed; if (!state->Initialized) { state->Initialized = TRUE; SetDefaultMenuRepeatDelay (); state->NextTime = GetTimeCounter (); /* Prepare widgets, draw stuff, etc. */ CreateWidgets (); DrawConnectDialog (); } changed = TRUE; if (PulsedInputState.menu[KEY_MENU_UP]) { Widget_Event (WIDGET_EVENT_UP); } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { Widget_Event (WIDGET_EVENT_DOWN); } else if (PulsedInputState.menu[KEY_MENU_LEFT]) { Widget_Event (WIDGET_EVENT_LEFT); } else if (PulsedInputState.menu[KEY_MENU_RIGHT]) { Widget_Event (WIDGET_EVENT_RIGHT); } else if (PulsedInputState.menu[KEY_MENU_SELECT]) { Widget_Event (WIDGET_EVENT_SELECT); } else if (PulsedInputState.menu[KEY_MENU_CANCEL]) { Widget_Event (WIDGET_EVENT_CANCEL); } else if (PulsedInputState.menu[KEY_MENU_DELETE]) { Widget_Event (WIDGET_EVENT_DELETE); } else { changed = FALSE; } if (changed) { DrawConnectDialog (); } SleepThreadUntil (state->NextTime + MENU_FRAME_RATE); state->NextTime = GetTimeCounter (); return !((GLOBAL (CurrentActivity) & CHECK_ABORT) || done); } BOOLEAN MeleeConnectDialog (int side) { CONNECT_DIALOG_STATE state; PlayerFont = CaptureFont ((FONT_REF)LoadFont (PLAYER_FONT)); state.Initialized = FALSE; state.which_side = side; state.InputFunc = DoMeleeConnectDialog; state.confirmed = TRUE; current_state = &state; DoInput ((PVOID)&state, TRUE); current_state = NULL; DestroyFont (ReleaseFont (PlayerFont)); return state.confirmed; } #endif /* NETPLAY */ uqm-0.6.2/sc2/src/sc2code/state.c0000600000175000017500000001731410543202101015065 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "state.h" #include "encount.h" #include "libs/misc.h" #include "libs/log.h" #ifdef HAVE_UNISTD_H #include #endif // in-memory file i/o struct GAME_STATE_FILE { const char *symname; DWORD size_hint; int open_count; BYTE *data; DWORD used; DWORD size; DWORD ptr; }; #define STATE_FILE_ITRAILER 0, 0, 0, 0, 0 #define NUM_STATE_FILES 3 static GAME_STATE_FILE state_files[NUM_STATE_FILES] = { {"STARINFO", STAR_BUFSIZE, STATE_FILE_ITRAILER}, {"RANDGRPINFO", RAND_BUFSIZE, STATE_FILE_ITRAILER}, {"DEFGRPINFO", DEF_BUFSIZE, STATE_FILE_ITRAILER} }; GAME_STATE_FILE * OpenStateFile (int stateFile, const char *mode) { GAME_STATE_FILE *fp; if (stateFile < 0 || stateFile >= NUM_STATE_FILES) return NULL; fp = &state_files[stateFile]; fp->open_count++; if (fp->open_count > 1) log_add (log_Warning, "WARNING: " "State file %s open count is %d after open()", fp->symname, fp->open_count); if (!fp->data) { fp->data = HMalloc (fp->size_hint); if (!fp->data) return NULL; fp->size = fp->size_hint; } // we allow reading and writing for any open mode // but the mode determines what happens to the file contents if (mode[0] == 'w') { // blow the file away fp->used = 0; #ifdef DEBUG // paint buffer for tracking writes memset (fp->data, 0xCC, fp->size); #endif } else if (mode[0] == 'r') { // nothing } else { log_add (log_Warning, "WARNING: " "State file %s opened with unsupported mode '%s'", fp->symname, mode); } fp->ptr = 0; return fp; } void CloseStateFile (GAME_STATE_FILE *fp) { fp->ptr = 0; fp->open_count--; if (fp->open_count < 0) log_add (log_Warning, "WARNING: " "State file %s open count is %d after close()", fp->symname, fp->open_count); // Erm, Ok, it's closed! Honest! } void DeleteStateFile (int stateFile) { GAME_STATE_FILE *fp; if (stateFile < 0 || stateFile >= NUM_STATE_FILES) return; fp = &state_files[stateFile]; if (fp->open_count != 0) log_add (log_Warning, "WARNING: " "State file %s open count is %d during delete()", fp->symname, fp->open_count); fp->used = 0; fp->ptr = 0; } DWORD LengthStateFile (GAME_STATE_FILE *fp) { return fp->used; } int ReadStateFile (PVOID lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp) { DWORD bytes = size * count; if (fp->ptr >= fp->size) { // EOF return 0; } else if (fp->ptr + bytes > fp->size) { // dont have that much data bytes = fp->size - fp->ptr; bytes -= bytes % size; } if (bytes > 0) { memcpy (lpBuf, fp->data + fp->ptr, bytes); fp->ptr += bytes; } return (bytes / size); } int WriteStateFile (PVOID lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp) { DWORD bytes = size * count; if (fp->ptr + bytes > fp->size) { // dont have that much space available DWORD newsize = fp->ptr + bytes; // grab more space in advance if (newsize < fp->size * 3 / 2) newsize = fp->size * 3 / 2; fp->data = HRealloc (fp->data, newsize); if (!fp->data) return 0; fp->size = newsize; if (newsize > fp->size_hint) fp->size_hint = newsize; } if (bytes > 0) { memcpy (fp->data + fp->ptr, lpBuf, bytes); fp->ptr += bytes; if (fp->ptr > fp->used) fp->used = fp->ptr; } return (bytes / size); } int SeekStateFile (GAME_STATE_FILE *fp, long offset, int whence) { if (whence == SEEK_CUR) offset += fp->ptr; else if (whence == SEEK_END) offset += fp->used; if (offset < 0) { fp->ptr = 0; return 0; } fp->ptr = offset; return 1; } void InitPlanetInfo (void) { GAME_STATE_FILE *fp; fp = OpenStateFile (STARINFO_FILE, "wb"); if (fp) { STAR_DESCPTR pSD; // Set record offsets for all stars to 0 (not present) pSD = &star_array[0]; do { swrite_32 (fp, 0); ++pSD; } while (pSD->star_pt.x <= MAX_X_UNIVERSE && pSD->star_pt.y <= MAX_Y_UNIVERSE); CloseStateFile (fp); } } void UninitPlanetInfo (void) { DeleteStateFile (STARINFO_FILE); } #define OFFSET_SIZE (sizeof (DWORD)) #define SCAN_RECORD_SIZE (sizeof (DWORD) * NUM_SCAN_TYPES) void GetPlanetInfo (void) { PVOID fp; pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] = 0; pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[MINERAL_SCAN] = 0; pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] = 0; fp = OpenStateFile (STARINFO_FILE, "rb"); if (fp) { COUNT star_index, planet_index, moon_index; DWORD offset; star_index = (COUNT)(CurStarDescPtr - star_array); planet_index = (COUNT)(pSolarSysState->pBaseDesc->pPrevDesc - pSolarSysState->PlanetDesc); if (pSolarSysState->pOrbitalDesc->pPrevDesc == pSolarSysState->SunDesc) moon_index = 0; else moon_index = (COUNT)(pSolarSysState->pOrbitalDesc - pSolarSysState->MoonDesc + 1); SeekStateFile (fp, star_index * OFFSET_SIZE, SEEK_SET); sread_32 (fp, &offset); if (offset) { COUNT i; // Skip scan records for all preceeding planets to the one we need for (i = 0; i < planet_index; ++i) offset += (pSolarSysState->PlanetDesc[i].NumPlanets + 1) * SCAN_RECORD_SIZE; // Skip scan records for all preceeding moons to the one we need offset += moon_index * SCAN_RECORD_SIZE; SeekStateFile (fp, offset, SEEK_SET); sread_a32 (fp, pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask, NUM_SCAN_TYPES); } CloseStateFile (fp); } } void PutPlanetInfo (void) { PVOID fp; fp = OpenStateFile (STARINFO_FILE, "r+b"); if (fp) { COUNT i; COUNT star_index, planet_index, moon_index; DWORD offset; star_index = (COUNT)(CurStarDescPtr - star_array); planet_index = (COUNT)(pSolarSysState->pBaseDesc->pPrevDesc - pSolarSysState->PlanetDesc); if (pSolarSysState->pOrbitalDesc->pPrevDesc == pSolarSysState->SunDesc) moon_index = 0; else moon_index = (COUNT)(pSolarSysState->pOrbitalDesc - pSolarSysState->MoonDesc + 1); SeekStateFile (fp, star_index * OFFSET_SIZE, SEEK_SET); sread_32 (fp, &offset); if (offset == 0) { // Scan record not present yet -- init it DWORD ScanRetrieveMask[NUM_SCAN_TYPES] = { 0, 0, 0, }; offset = LengthStateFile (fp); // Write the record offset SeekStateFile (fp, star_index * OFFSET_SIZE, SEEK_SET); swrite_32 (fp, offset); // Init scan records for all planets and moons in the system SeekStateFile (fp, offset, SEEK_SET); for (i = 0; i < pSolarSysState->SunDesc[0].NumPlanets; ++i) { COUNT j; swrite_a32 (fp, ScanRetrieveMask, NUM_SCAN_TYPES); // init moons for (j = 0; j < pSolarSysState->PlanetDesc[i].NumPlanets; ++j) swrite_a32 (fp, ScanRetrieveMask, NUM_SCAN_TYPES); } } // Skip scan records for all preceeding planets to the one we need for (i = 0; i < planet_index; ++i) offset += (pSolarSysState->PlanetDesc[i].NumPlanets + 1) * SCAN_RECORD_SIZE; // Skip scan records for all preceeding moons to the one we need offset += moon_index * SCAN_RECORD_SIZE; SeekStateFile (fp, offset, SEEK_SET); swrite_a32 (fp, pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask, NUM_SCAN_TYPES); CloseStateFile (fp); } } uqm-0.6.2/sc2/src/sc2code/setup.h0000600000175000017500000000332010543202103015104 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SETUP_H #define _SETUP_H #include "displist.h" #include "globdata.h" #include "libs/sndlib.h" #include "libs/gfxlib.h" #include "libs/threadlib.h" extern MEM_HANDLE hResIndex; extern FRAME Screen; extern FRAME ActivityFrame; extern FRAME StatusFrame; extern FRAME FlagStatFrame; extern FRAME MiscDataFrame; extern FRAME FontGradFrame; extern CONTEXT OffScreenContext; extern CONTEXT ScreenContext; extern CONTEXT SpaceContext; extern CONTEXT StatusContext; extern CONTEXT TaskContext; extern SIZE screen_width, screen_height; extern FONT StarConFont; extern FONT MicroFont; extern FONT TinyFont; extern Mutex GraphicsLock; extern CondVar RenderingCond; extern QUEUE race_q[]; extern ACTIVITY LastActivity; extern BYTE PlayerControl[]; extern SIZE cur_player; extern BOOLEAN InitContexts (void); extern void UninitPlayerInput (void); extern BOOLEAN InitGameKernel (void); extern int initIO (void); extern void uninitIO (void); extern void SetPlayerInput (void); #endif /* _SETUP_H */ uqm-0.6.2/sc2/src/sc2code/velocity.c0000600000175000017500000001055110543202101015577 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "velocity.h" #include "units.h" #include "libs/compiler.h" #define VELOCITY_REMAINDER(v) ((v) & (VELOCITY_SCALE - 1)) void GetCurrentVelocityComponents (VELOCITYPTR velocityptr, PSIZE pdx, PSIZE pdy) { *pdx = WORLD_TO_VELOCITY (velocityptr->vector.width) + (velocityptr->fract.width - (SIZE)HIBYTE (velocityptr->incr.width)); *pdy = WORLD_TO_VELOCITY (velocityptr->vector.height) + (velocityptr->fract.height - (SIZE)HIBYTE (velocityptr->incr.height)); } void GetNextVelocityComponents (VELOCITYPTR velocityptr, PSIZE pdx, PSIZE pdy, COUNT num_frames) { COUNT e; e = (COUNT)((COUNT)velocityptr->error.width + ((COUNT)velocityptr->fract.width * num_frames)); *pdx = (velocityptr->vector.width * num_frames) + ((SIZE)((SBYTE)LOBYTE (velocityptr->incr.width)) * (e >> VELOCITY_SHIFT)); velocityptr->error.width = VELOCITY_REMAINDER (e); e = (COUNT)((COUNT)velocityptr->error.height + ((COUNT)velocityptr->fract.height * num_frames)); *pdy = (velocityptr->vector.height * num_frames) + ((SIZE)((SBYTE)LOBYTE (velocityptr->incr.height)) * (e >> VELOCITY_SHIFT)); velocityptr->error.height = VELOCITY_REMAINDER (e); } void SetVelocityVector (VELOCITYPTR velocityptr, SIZE magnitude, COUNT facing) { COUNT angle; SIZE dx, dy; angle = velocityptr->TravelAngle = FACING_TO_ANGLE (NORMALIZE_FACING (facing)); magnitude = WORLD_TO_VELOCITY (magnitude); dx = COSINE (angle, magnitude); dy = SINE (angle, magnitude); if (dx >= 0) { velocityptr->vector.width = VELOCITY_TO_WORLD (dx); velocityptr->incr.width = MAKE_WORD ((BYTE)1, (BYTE)0); } else { dx = -dx; velocityptr->vector.width = -VELOCITY_TO_WORLD (dx); velocityptr->incr.width = MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dx) << 1)); } if (dy >= 0) { velocityptr->vector.height = VELOCITY_TO_WORLD (dy); velocityptr->incr.height = MAKE_WORD ((BYTE)1, (BYTE)0); } else { dy = -dy; velocityptr->vector.height = -VELOCITY_TO_WORLD (dy); velocityptr->incr.height = MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dy) << 1)); } velocityptr->fract.width = VELOCITY_REMAINDER (dx); velocityptr->fract.height = VELOCITY_REMAINDER (dy); velocityptr->error.width = velocityptr->error.height = 0; } void SetVelocityComponents (VELOCITYPTR velocityptr, SIZE dx, SIZE dy) { COUNT angle; if ((angle = ARCTAN (dx, dy)) == FULL_CIRCLE) { ZeroVelocityComponents (velocityptr); } else { if (dx >= 0) { velocityptr->vector.width = VELOCITY_TO_WORLD (dx); velocityptr->incr.width = MAKE_WORD ((BYTE)1, (BYTE)0); } else { dx = -dx; velocityptr->vector.width = -VELOCITY_TO_WORLD (dx); velocityptr->incr.width = MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dx) << 1)); } if (dy >= 0) { velocityptr->vector.height = VELOCITY_TO_WORLD (dy); velocityptr->incr.height = MAKE_WORD ((BYTE)1, (BYTE)0); } else { dy = -dy; velocityptr->vector.height = -VELOCITY_TO_WORLD (dy); velocityptr->incr.height = MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dy) << 1)); } velocityptr->fract.width = VELOCITY_REMAINDER (dx); velocityptr->fract.height = VELOCITY_REMAINDER (dy); velocityptr->error.width = velocityptr->error.height = 0; } velocityptr->TravelAngle = angle; } void DeltaVelocityComponents (VELOCITYPTR velocityptr, SIZE dx, SIZE dy) { dx += WORLD_TO_VELOCITY (velocityptr->vector.width) + (velocityptr->fract.width - (SIZE)HIBYTE (velocityptr->incr.width)); dy += WORLD_TO_VELOCITY (velocityptr->vector.height) + (velocityptr->fract.height - (SIZE)HIBYTE (velocityptr->incr.height)); SetVelocityComponents (velocityptr, dx, dy); } uqm-0.6.2/sc2/src/sc2code/fmv.c0000600000175000017500000001076010543202103014535 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "fmv.h" #include "controls.h" #include "hyper.h" #include "options.h" #include "master.h" #include "resinst.h" #include "nameref.h" #include "settings.h" #include "setup.h" #include "vidlib.h" #include "libs/graphics/gfx_common.h" #include "libs/inplib.h" void DoShipSpin (COUNT index, MUSIC_REF hMusic) { #ifdef WANT_SHIP_SPINS char buf[30]; BYTE clut_buf[1]; RECT old_r, r; SetGraphicUseOtherExtra (1); LoadIntoExtraScreen (0); clut_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 4)); FlushColorXForms (); if (hMusic) StopMusic (); FreeHyperData (); sprintf (buf, "ship%02d", index); DoFMV (buf, "spin", FALSE); GetContextClipRect (&old_r); r.corner.x = r.corner.y = 0; r.extent.width = SCREEN_WIDTH; r.extent.height = SCREEN_HEIGHT; SetContextClipRect (&r); DrawFromExtraScreen (0); SetGraphicUseOtherExtra (0); SetContextClipRect (&old_r); if (hMusic) PlayMusic (hMusic, TRUE, 1); clut_buf[0] = FadeAllToColor; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 4)); FlushColorXForms (); #else (void) index; /* Satisfy compiler */ (void) hMusic; /* Satisfy compiler */ #endif /* WANT_SHIP_SPINS */ } void SplashScreen (void (* DoProcessing)(DWORD TimeOut)) { BYTE xform_buf[1]; STAMP s; DWORD TimeOut; BOOLEAN InputState; xform_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ( (COLORMAPPTR) xform_buf, ONE_SECOND / 120)); LockMutex (GraphicsLock); SetContext (ScreenContext); s.origin.x = s.origin.y = 0; s.frame = CaptureDrawable (LoadGraphic (TITLE_ANIM)); DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); UnlockMutex (GraphicsLock); xform_buf[0] = FadeAllToColor; TimeOut = XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2); if (DoProcessing) DoProcessing (TimeOut); if (GLOBAL (CurrentActivity) & CHECK_ABORT) { return; } /* There was a forcible setting of CHECK_ABORT here. I cannot * find any purpose for this that DoRestart doesn't handle * better (forcing all other threads but this one to quit out, * I believe), and have thus removed it. It was interfering * with the proper operation of the quit operation. * --Michael */ TimeOut += ONE_SECOND * 3; while (!(InputState = AnyButtonPress (FALSE)) && (GetTimeCounter () <= TimeOut) && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) { TaskSwitch (); } if (GLOBAL (CurrentActivity) & CHECK_ABORT) { return; } GLOBAL (CurrentActivity) &= ~CHECK_ABORT; /* You can't try to quit during a fade to black, because if * you try, the confirmation window will fade to black too. * Fixing this will require a rewrite of our whole rendering * engine. -- Michael */ xform_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2)); } void Introduction (void) { BYTE xform_buf[1]; /* by default we do 3DO cinematics; or PC slides when 3DO files are * not present */ if (optWhichIntro == OPT_PC || !DoFMV ("slides/intro/intro.duk", NULL, TRUE)) ShowPresentation ( CaptureStringTable ( LoadStringTable (INTROPRES_STRTAB))); xform_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2)); } void Victory (void) { BYTE xform_buf[1]; xform_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)xform_buf, ONE_SECOND / 2)); /* by default we do 3DO cinematics; or PC slides when 3DO files are * not present */ if (optWhichIntro == OPT_PC || !DoFMV ("slides/ending/victory.duk", NULL, TRUE)) ShowPresentation ( CaptureStringTable ( LoadStringTable (FINALPRES_STRTAB))); xform_buf[0] = FadeAllToBlack; XFormColorMap ((COLORMAPPTR)xform_buf, 0); } void Logo (void) { DoFMV ("logo", NULL, FALSE); } uqm-0.6.2/sc2/src/sc2code/ipdisp.c0000600000175000017500000005411610543202103015240 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "collide.h" #include "globdata.h" #include "init.h" #include "races.h" #include "encount.h" #include "libs/mathlib.h" void NotifyOthers (COUNT which_race, BYTE target_loc) { HSTARSHIP hStarShip, hNextShip; for (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); hStarShip; hStarShip = hNextShip) { SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); hNextShip = _GetSuccLink (StarShipPtr); if (GET_RACE_ID (StarShipPtr) == which_race) { BYTE task; task = GET_GROUP_MISSION (StarShipPtr) | IGNORE_FLAGSHIP; if (target_loc == 0) { task &= ~IGNORE_FLAGSHIP; SET_ORBIT_LOC (StarShipPtr, GET_GROUP_DEST (StarShipPtr)); /* task = FLEE | IGNORE_FLAGSHIP; */ } else if ((target_loc = GET_GROUP_DEST (StarShipPtr)) == 0) { target_loc = GET_ORBIT_LOC (StarShipPtr); SET_ORBIT_LOC (StarShipPtr, NORMALIZE_FACING (TFB_Random ())); #ifdef OLD target_loc = (BYTE)(( (COUNT)TFB_Random () % pSolarSysState->SunDesc[0].NumPlanets) + 1); #endif /* OLD */ if (!(task & REFORM_GROUP)) { if ((task & ~IGNORE_FLAGSHIP) != EXPLORE) StarShipPtr->ShipInfo.group_counter = 0; else StarShipPtr->ShipInfo.group_counter = ((COUNT) TFB_Random () % MAX_REVOLUTIONS) << FACING_SHIFT; } } SET_GROUP_MISSION (StarShipPtr, task); SET_GROUP_DEST (StarShipPtr, target_loc); } UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } } static void ip_group_preprocess (PELEMENT ElementPtr) { #define TRACK_WAIT 5 BYTE task; BYTE target_loc, group_loc, flagship_loc; SIZE radius; POINT dest_pt; SIZE vdx, vdy; ELEMENTPTR EPtr; SHIP_FRAGMENTPTR StarShipPtr; EPtr = (ELEMENTPTR)ElementPtr; EPtr->state_flags &= ~(DISAPPEARING | NONSOLID); /* "I'm not quite dead." */ ++EPtr->life_span; /* so that it will 'die' * again next time. */ GetElementStarShip (EPtr, &StarShipPtr); group_loc = GET_GROUP_LOC (StarShipPtr); /* save old location */ DisplayArray[EPtr->PrimIndex].Object.Point = StarShipPtr->ShipInfo.loc; if (group_loc != 0) radius = MAX_ZOOM_RADIUS; else radius = pSolarSysState->SunDesc[0].radius; dest_pt.x = (SIS_SCREEN_WIDTH >> 1) + (SIZE)((long)StarShipPtr->ShipInfo.loc.x * (DISPLAY_FACTOR >> 1) / radius); dest_pt.y = (SIS_SCREEN_HEIGHT >> 1) + (SIZE)((long)StarShipPtr->ShipInfo.loc.y * (DISPLAY_FACTOR >> 1) / radius); EPtr->current.location.x = DISPLAY_TO_WORLD (dest_pt.x) + (COORD)(LOG_SPACE_WIDTH >> 1) - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); EPtr->current.location.y = DISPLAY_TO_WORLD (dest_pt.y) + (COORD)(LOG_SPACE_HEIGHT >> 1) - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); InitIntersectStartPoint (EPtr); if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) flagship_loc = 0; else flagship_loc = (BYTE)(pSolarSysState->pBaseDesc->pPrevDesc - pSolarSysState->PlanetDesc + 1); task = GET_GROUP_MISSION (StarShipPtr); if (pSolarSysState->MenuState.CurState) goto ExitIPProcess; if ((task & REFORM_GROUP) && --StarShipPtr->ShipInfo.group_counter == 0) { task &= ~REFORM_GROUP; SET_GROUP_MISSION (StarShipPtr, task); if ((task & ~IGNORE_FLAGSHIP) != EXPLORE) StarShipPtr->ShipInfo.group_counter = 0; else StarShipPtr->ShipInfo.group_counter = ((COUNT)TFB_Random () % MAX_REVOLUTIONS) << FACING_SHIFT; } if (!(task & REFORM_GROUP)) { if ((task & ~(IGNORE_FLAGSHIP | REFORM_GROUP)) != FLEE) { if (EPtr->state_flags & BAD_GUY) EPtr->state_flags &= ~GOOD_GUY; else EPtr->state_flags |= BAD_GUY; } else if (!(task & IGNORE_FLAGSHIP) && !(EPtr->state_flags & (GOOD_GUY | BAD_GUY))) { // fleeing yehat ship collisions after menu fix EPtr->state_flags |= BAD_GUY; } } target_loc = GET_GROUP_DEST (StarShipPtr); if (!(task & (IGNORE_FLAGSHIP | REFORM_GROUP))) { if (target_loc == 0 && task != FLEE) { /* if intercepting flagship */ target_loc = flagship_loc; if (EPtr->thrust_wait > TRACK_WAIT) { EPtr->thrust_wait = 0; ZeroVelocityComponents (&EPtr->velocity); } } else if (group_loc == flagship_loc) { long detect_dist; detect_dist = 1200; if (group_loc != 0) /* if in planetary views */ { detect_dist *= (MAX_ZOOM_RADIUS / MIN_ZOOM_RADIUS); if (GET_RACE_ID (StarShipPtr) == URQUAN_PROBE_SHIP) detect_dist <<= 1; } vdx = GLOBAL (ip_location.x) - StarShipPtr->ShipInfo.loc.x; vdy = GLOBAL (ip_location.y) - StarShipPtr->ShipInfo.loc.y; if ((long)vdx * vdx + (long)vdy * vdy < (long)detect_dist * detect_dist) { EPtr->thrust_wait = 0; ZeroVelocityComponents (&EPtr->velocity); NotifyOthers (GET_RACE_ID (StarShipPtr), 0); task = GET_GROUP_MISSION (StarShipPtr); if ((target_loc = GET_GROUP_DEST (StarShipPtr)) == 0) target_loc = flagship_loc; } } } GetCurrentVelocityComponents (&EPtr->velocity, &vdx, &vdy); task &= ~IGNORE_FLAGSHIP; if (task <= ON_STATION) #ifdef NEVER if (task <= FLEE || (task == ON_STATION && GET_GROUP_DEST (StarShipPtr) == 0)) #endif /* NEVER */ { BOOLEAN Transition; SIZE dx, dy; SIZE delta_x, delta_y; COUNT angle; Transition = FALSE; if (task == FLEE) { dest_pt.x = StarShipPtr->ShipInfo.loc.x << 1; dest_pt.y = StarShipPtr->ShipInfo.loc.y << 1; } else if (((task != ON_STATION || GET_GROUP_DEST (StarShipPtr) == 0) && group_loc == target_loc) || (task == ON_STATION && GET_GROUP_DEST (StarShipPtr) && group_loc == 0)) { if (GET_GROUP_DEST (StarShipPtr) == 0) dest_pt = GLOBAL (ip_location); else { COUNT orbit_dist; POINT org; if (task != ON_STATION) { orbit_dist = ORBIT_RADIUS; org.x = org.y = 0; } else { orbit_dist = STATION_RADIUS; XFormIPLoc ( &pSolarSysState->PlanetDesc[ target_loc - 1 ].image.origin, &org, FALSE ); } angle = FACING_TO_ANGLE (GET_ORBIT_LOC (StarShipPtr) + 1); dest_pt.x = org.x + COSINE (angle, orbit_dist); dest_pt.y = org.y + SINE (angle, orbit_dist); if (StarShipPtr->ShipInfo.loc.x == dest_pt.x && StarShipPtr->ShipInfo.loc.y == dest_pt.y) { BYTE next_loc; SET_ORBIT_LOC (StarShipPtr, NORMALIZE_FACING (ANGLE_TO_FACING (angle))); angle += FACING_TO_ANGLE (1); dest_pt.x = org.x + COSINE (angle, orbit_dist); dest_pt.y = org.y + SINE (angle, orbit_dist); EPtr->thrust_wait = (BYTE)~0; if (StarShipPtr->ShipInfo.group_counter) --StarShipPtr->ShipInfo.group_counter; else if (task == EXPLORE && (next_loc = (BYTE)(((COUNT)TFB_Random () % pSolarSysState->SunDesc[0].NumPlanets) + 1)) != target_loc) { EPtr->thrust_wait = 0; SET_GROUP_DEST (StarShipPtr, target_loc = next_loc); } } } } else if (group_loc == 0) { if (GET_GROUP_DEST (StarShipPtr) == 0) dest_pt = pSolarSysState->SunDesc[0].location; else XFormIPLoc (&pSolarSysState->PlanetDesc[ target_loc - 1].image.origin, &dest_pt, FALSE); } else { if (task == ON_STATION) target_loc = 0; dest_pt.x = StarShipPtr->ShipInfo.loc.x << 1; dest_pt.y = StarShipPtr->ShipInfo.loc.y << 1; } delta_x = dest_pt.x - StarShipPtr->ShipInfo.loc.x; delta_y = dest_pt.y - StarShipPtr->ShipInfo.loc.y; angle = ARCTAN (delta_x, delta_y); if (EPtr->thrust_wait && EPtr->thrust_wait != (BYTE)~0) --EPtr->thrust_wait; else if ((vdx == 0 && vdy == 0) || angle != GetVelocityTravelAngle (&EPtr->velocity)) { SIZE speed; if (EPtr->thrust_wait && GET_GROUP_DEST (StarShipPtr) != 0) { #define ORBIT_SPEED 60 speed = ORBIT_SPEED; if (task == ON_STATION) speed >>= 1; } else { SIZE RaceIPSpeed[] = { RACE_IP_SPEED }; speed = RaceIPSpeed[GET_RACE_ID (StarShipPtr)]; EPtr->thrust_wait = TRACK_WAIT; } SetVelocityComponents (&EPtr->velocity, vdx = COSINE (angle, speed), vdy = SINE (angle, speed)); } dx = vdx, dy = vdy; if (group_loc == target_loc) { if (target_loc == 0) { if (task == FLEE) goto CheckGetAway; } else if (target_loc == GET_GROUP_DEST (StarShipPtr)) { PartialRevolution: if ((long)((COUNT)(dx * dx) + (COUNT)(dy * dy)) >= (long)delta_x * delta_x + (long)delta_y * delta_y) { StarShipPtr->ShipInfo.loc = dest_pt; vdx = vdy = 0; ZeroVelocityComponents (&EPtr->velocity); } } } else { if (group_loc == 0) { if (pSolarSysState->SunDesc[0].radius < MAX_ZOOM_RADIUS) { dx >>= 1; dy >>= 1; if (pSolarSysState->SunDesc[0].radius == MIN_ZOOM_RADIUS) { dx >>= 1; dy >>= 1; } } if (task == ON_STATION && GET_GROUP_DEST (StarShipPtr)) goto PartialRevolution; else if ((long)((COUNT)(dx * dx) + (COUNT)(dy * dy)) >= (long)delta_x * delta_x + (long)delta_y * delta_y) Transition = TRUE; } else { CheckGetAway: dest_pt.x = (SIS_SCREEN_WIDTH >> 1) + (SIZE)((long)StarShipPtr->ShipInfo.loc.x * (DISPLAY_FACTOR >> 1) / MAX_ZOOM_RADIUS); dest_pt.y = (SIS_SCREEN_HEIGHT >> 1) + (SIZE)((long)StarShipPtr->ShipInfo.loc.y * (DISPLAY_FACTOR >> 1) / MAX_ZOOM_RADIUS); if (dest_pt.x < 0 || dest_pt.x >= SIS_SCREEN_WIDTH || dest_pt.y < 0 || dest_pt.y >= SIS_SCREEN_HEIGHT) Transition = TRUE; } if (Transition) { /* no collisions during transition */ EPtr->state_flags |= NONSOLID; vdx = vdy = 0; ZeroVelocityComponents (&EPtr->velocity); if (group_loc != 0) { PPLANET_DESC pCurDesc; pCurDesc = &pSolarSysState->PlanetDesc[group_loc - 1]; XFormIPLoc ( &pCurDesc->image.origin, &StarShipPtr->ShipInfo.loc, FALSE ); SET_GROUP_LOC (StarShipPtr, group_loc = 0); } else if (target_loc == 0) { EPtr->life_span = 0; EPtr->state_flags |= DISAPPEARING | NONSOLID; StarShipPtr->ShipInfo.crew_level = 0; return; } else { if (target_loc == GET_GROUP_DEST (StarShipPtr)) { SET_ORBIT_LOC (StarShipPtr, NORMALIZE_FACING ( ANGLE_TO_FACING (angle + HALF_CIRCLE) )); StarShipPtr->ShipInfo.group_counter = ((COUNT)TFB_Random () % MAX_REVOLUTIONS) << FACING_SHIFT; } StarShipPtr->ShipInfo.loc.x = -(SIZE)((long)COSINE ( angle, SIS_SCREEN_WIDTH * 9 / 16 ) * MAX_ZOOM_RADIUS / (DISPLAY_FACTOR >> 1)); StarShipPtr->ShipInfo.loc.y = -(SIZE)((long)SINE ( angle, SIS_SCREEN_WIDTH * 9 / 16 ) * MAX_ZOOM_RADIUS / (DISPLAY_FACTOR >> 1)); SET_GROUP_LOC (StarShipPtr, group_loc = target_loc); } } } } if (group_loc != 0) radius = MAX_ZOOM_RADIUS; else { radius = pSolarSysState->SunDesc[0].radius; if (radius < MAX_ZOOM_RADIUS) { vdx >>= 1; vdy >>= 1; if (radius == MIN_ZOOM_RADIUS) { vdx >>= 1; vdy >>= 1; } } } StarShipPtr->ShipInfo.loc.x += vdx; StarShipPtr->ShipInfo.loc.y += vdy; dest_pt.x = (SIS_SCREEN_WIDTH >> 1) + (SIZE)((long)StarShipPtr->ShipInfo.loc.x * (DISPLAY_FACTOR >> 1) / radius); dest_pt.y = (SIS_SCREEN_HEIGHT >> 1) + (SIZE)((long)StarShipPtr->ShipInfo.loc.y * (DISPLAY_FACTOR >> 1) / radius); ExitIPProcess: EPtr->next.location.x = DISPLAY_TO_WORLD (dest_pt.x) + (COORD)(LOG_SPACE_WIDTH >> 1) - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); EPtr->next.location.y = DISPLAY_TO_WORLD (dest_pt.y) + (COORD)(LOG_SPACE_HEIGHT >> 1) - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); if (group_loc != flagship_loc || ((task & REFORM_GROUP) && (StarShipPtr->ShipInfo.group_counter & 1))) { SetPrimType (&DisplayArray[EPtr->PrimIndex], NO_PRIM); EPtr->state_flags |= NONSOLID; } else { SetPrimType (&DisplayArray[EPtr->PrimIndex], STAMP_PRIM); if (task & REFORM_GROUP) EPtr->state_flags |= NONSOLID; } EPtr->state_flags |= CHANGING; } static void flag_ship_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if ((GLOBAL (CurrentActivity) & START_ENCOUNTER) || pSolarSysState->MenuState.CurState || (ElementPtr1->state_flags & GOOD_GUY)) return; if (!(ElementPtr1->state_flags & COLLISION)) /* not processed yet */ ElementPtr0->state_flags |= COLLISION | NONSOLID; else { ElementPtr1->state_flags &= ~COLLISION; GLOBAL (CurrentActivity) |= START_ENCOUNTER; } (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } static void ip_group_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { SHIP_FRAGMENTPTR StarShipPtr; if ((GLOBAL (CurrentActivity) & START_ENCOUNTER) || pSolarSysState->MenuState.CurState || (ElementPtr0->state_flags & GOOD_GUY)) { ElementPtr0->state_flags &= ~BAD_GUY; return; } GetElementStarShip (ElementPtr0, &StarShipPtr); if (ElementPtr0->state_flags & ElementPtr1->state_flags & BAD_GUY) { if ((ElementPtr0->state_flags & COLLISION) || (ElementPtr1->current.location.x == ElementPtr1->next.location.x && ElementPtr1->current.location.y == ElementPtr1->next.location.y)) ElementPtr0->state_flags &= ~COLLISION; else { ElementPtr1->state_flags |= COLLISION; StarShipPtr->ShipInfo.loc = DisplayArray[ElementPtr0->PrimIndex].Object.Point; ElementPtr0->next.location = ElementPtr0->current.location; InitIntersectEndPoint (ElementPtr0); } } else { EncounterGroup = GET_GROUP_ID (StarShipPtr); if (GET_RACE_ID (StarShipPtr) == URQUAN_PROBE_SHIP) { SET_GROUP_MISSION (StarShipPtr, FLEE | IGNORE_FLAGSHIP); SET_GROUP_DEST (StarShipPtr, 0); } else { SET_GROUP_MISSION (StarShipPtr, GET_GROUP_MISSION (StarShipPtr) | REFORM_GROUP); StarShipPtr->ShipInfo.group_counter = 100; NotifyOthers (GET_RACE_ID (StarShipPtr), (BYTE)~0); } if (!(ElementPtr1->state_flags & COLLISION)) /* not processed yet */ ElementPtr0->state_flags |= COLLISION | NONSOLID; else { ElementPtr1->state_flags &= ~COLLISION; GLOBAL (CurrentActivity) |= START_ENCOUNTER; } } (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } static void spawn_ip_group (SHIP_FRAGMENTPTR StarShipPtr) { HELEMENT hIPSHIPElement; hIPSHIPElement = AllocElement (); if (hIPSHIPElement) { BYTE task; ELEMENTPTR IPSHIPElementPtr; LockElement (hIPSHIPElement, &IPSHIPElementPtr); IPSHIPElementPtr->turn_wait = GET_GROUP_ID (StarShipPtr); IPSHIPElementPtr->mass_points = 1; IPSHIPElementPtr->hit_points = 1; IPSHIPElementPtr->state_flags = CHANGING | FINITE_LIFE | IGNORE_VELOCITY; task = GET_GROUP_MISSION (StarShipPtr); if (!(task & IGNORE_FLAGSHIP)) IPSHIPElementPtr->state_flags |= BAD_GUY; else { IPSHIPElementPtr->state_flags |= GOOD_GUY; if (GET_RACE_ID (StarShipPtr) == YEHAT_SHIP && GET_GAME_STATE (YEHAT_CIVIL_WAR)) { SET_GROUP_MISSION (StarShipPtr, FLEE | (task & REFORM_GROUP)); SET_GROUP_DEST (StarShipPtr, 0); } } SetPrimType (&DisplayArray[IPSHIPElementPtr->PrimIndex], STAMP_PRIM); IPSHIPElementPtr->current.image.farray = &StarShipPtr->ShipInfo.melee_icon; IPSHIPElementPtr->current.image.frame = SetAbsFrameIndex (StarShipPtr->ShipInfo.melee_icon, 1); /* preprocessing has a side effect * we wish to avoid. So death_func * is used instead, but will achieve * same result without the side * effect (InitIntersectFrame) */ IPSHIPElementPtr->death_func = ip_group_preprocess; IPSHIPElementPtr->collision_func = ip_group_collision; { SIZE radius; POINT pt; if (GET_GROUP_LOC (StarShipPtr) != 0) radius = MAX_ZOOM_RADIUS; else radius = pSolarSysState->SunDesc[0].radius; pt.x = (SIS_SCREEN_WIDTH >> 1) + (SIZE)((long)StarShipPtr->ShipInfo.loc.x * DISPLAY_FACTOR / radius); pt.y = (SIS_SCREEN_HEIGHT >> 1) + (SIZE)((long)StarShipPtr->ShipInfo.loc.y * (DISPLAY_FACTOR >> 1) / radius); IPSHIPElementPtr->current.location.x = DISPLAY_TO_WORLD (pt.x) + (COORD)(LOG_SPACE_WIDTH >> 1) - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); IPSHIPElementPtr->current.location.y = DISPLAY_TO_WORLD (pt.y) + (COORD)(LOG_SPACE_HEIGHT >> 1) - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); } SetElementStarShip (IPSHIPElementPtr, StarShipPtr); SetUpElement (IPSHIPElementPtr); IPSHIPElementPtr->IntersectControl.IntersectStamp.frame = DecFrameIndex (stars_in_space); UnlockElement (hIPSHIPElement); PutElement (hIPSHIPElement); } } #define FLIP_WAIT 42 static void flag_ship_preprocess (PELEMENT ElementPtr) { if (--ElementPtr->thrust_wait == 0) /* juggle list after flagship */ { HELEMENT hSuccElement; if ((hSuccElement = GetSuccElement (ElementPtr)) && hSuccElement != GetTailElement ()) { HELEMENT hPredElement; ELEMENTPTR TailPtr; LockElement (GetTailElement (), &TailPtr); hPredElement = _GetPredLink (TailPtr); UnlockElement (GetTailElement ()); RemoveElement (hSuccElement); PutElement (hSuccElement); } ElementPtr->thrust_wait = FLIP_WAIT; } if (pSolarSysState->MenuState.CurState == 0) { BYTE flagship_loc, ec; SIZE vdx, vdy, radius; POINT pt; GetCurrentVelocityComponents (&GLOBAL (velocity), &vdx, &vdy); if (pSolarSysState->pBaseDesc == pSolarSysState->MoonDesc) { flagship_loc = (BYTE)(pSolarSysState->pBaseDesc->pPrevDesc - pSolarSysState->PlanetDesc + 2); radius = MAX_ZOOM_RADIUS; } else { flagship_loc = 1; radius = pSolarSysState->SunDesc[0].radius; if (radius < MAX_ZOOM_RADIUS) { vdx >>= 1; vdy >>= 1; if (radius == MIN_ZOOM_RADIUS) { vdx >>= 1; vdy >>= 1; } } } pt.x = (SIS_SCREEN_WIDTH >> 1) + (SIZE)((long)GLOBAL (ip_location.x) * (DISPLAY_FACTOR >> 1) / radius); pt.y = (SIS_SCREEN_HEIGHT >> 1) + (SIZE)((long)GLOBAL (ip_location.y) * (DISPLAY_FACTOR >> 1) / radius); ElementPtr->current.location.x = DISPLAY_TO_WORLD (pt.x) + (COORD)(LOG_SPACE_WIDTH >> 1) - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); ElementPtr->current.location.y = DISPLAY_TO_WORLD (pt.y) + (COORD)(LOG_SPACE_HEIGHT >> 1) - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); InitIntersectStartPoint (ElementPtr); GLOBAL (ip_location.x) += vdx; GLOBAL (ip_location.y) += vdy; pt.x = (SIS_SCREEN_WIDTH >> 1) + (SIZE)((long)GLOBAL (ip_location.x) * (DISPLAY_FACTOR >> 1) / radius); pt.y = (SIS_SCREEN_HEIGHT >> 1) + (SIZE)((long)GLOBAL (ip_location.y) * (DISPLAY_FACTOR >> 1) / radius); ElementPtr->next.location.x = DISPLAY_TO_WORLD (pt.x) + (COORD)(LOG_SPACE_WIDTH >> 1) - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); ElementPtr->next.location.y = DISPLAY_TO_WORLD (pt.y) + (COORD)(LOG_SPACE_HEIGHT >> 1) - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); GLOBAL (ShipStamp.origin) = pt; ElementPtr->next.image.frame = GLOBAL (ShipStamp.frame); if (ElementPtr->mass_points == flagship_loc) { if (ElementPtr->state_flags & NONSOLID) ElementPtr->state_flags &= ~NONSOLID; } else /* no collisions during transition */ { ElementPtr->state_flags |= NONSOLID; ElementPtr->mass_points = flagship_loc; } if ((ec = GET_GAME_STATE (ESCAPE_COUNTER)) && !(GLOBAL (CurrentActivity) & START_ENCOUNTER)) { ElementPtr->state_flags |= NONSOLID; --ec; SET_GAME_STATE (ESCAPE_COUNTER, ec); } ElementPtr->state_flags |= CHANGING; } } static void spawn_flag_ship (void) { HELEMENT hFlagShipElement; hFlagShipElement = AllocElement (); if (hFlagShipElement) { ELEMENTPTR FlagShipElementPtr; LockElement (hFlagShipElement, &FlagShipElementPtr); FlagShipElementPtr->hit_points = 1; if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) FlagShipElementPtr->mass_points = 1; else FlagShipElementPtr->mass_points = (BYTE)(pSolarSysState->pBaseDesc->pPrevDesc - pSolarSysState->PlanetDesc + 2); FlagShipElementPtr->state_flags = APPEARING | GOOD_GUY | IGNORE_VELOCITY; if (GET_GAME_STATE (ESCAPE_COUNTER)) FlagShipElementPtr->state_flags |= NONSOLID; FlagShipElementPtr->life_span = NORMAL_LIFE; FlagShipElementPtr->thrust_wait = FLIP_WAIT; SetPrimType (&DisplayArray[FlagShipElementPtr->PrimIndex], STAMP_PRIM); FlagShipElementPtr->current.image.farray = &GLOBAL (ShipStamp.frame); FlagShipElementPtr->current.image.frame = GLOBAL (ShipStamp.frame); FlagShipElementPtr->preprocess_func = flag_ship_preprocess; FlagShipElementPtr->collision_func = flag_ship_collision; FlagShipElementPtr->current.location.x = DISPLAY_TO_WORLD (GLOBAL (ShipStamp.origin.x)) + (COORD)(LOG_SPACE_WIDTH >> 1) - (LOG_SPACE_WIDTH >> (MAX_REDUCTION + 1)); FlagShipElementPtr->current.location.y = DISPLAY_TO_WORLD (GLOBAL (ShipStamp.origin.y)) + (COORD)(LOG_SPACE_HEIGHT >> 1) - (LOG_SPACE_HEIGHT >> (MAX_REDUCTION + 1)); UnlockElement (hFlagShipElement); PutElement (hFlagShipElement); } } void DoMissions (void) { HSTARSHIP hStarShip, hNextShip; spawn_flag_ship (); if (EncounterRace >= 0) { NotifyOthers (EncounterRace, 0); EncounterRace = -1; } for (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); hStarShip; hStarShip = hNextShip) { SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); hNextShip = _GetSuccLink (StarShipPtr); if (StarShipPtr->ShipInfo.crew_level) spawn_ip_group (StarShipPtr); UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } } uqm-0.6.2/sc2/src/sc2code/status.c0000600000175000017500000003564010543202103015274 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "colors.h" #include "globdata.h" #include "races.h" #include "setup.h" #include "options.h" #include #include static void CaptainsWindow (CAPTAIN_STUFFPTR CSPtr, COORD y, ELEMENT_FLAGS delta_status_flags, ELEMENT_FLAGS cur_status_flags, COUNT Pass) { STAMP Stamp; Stamp.origin.x = CAPTAIN_XOFFS; Stamp.origin.y = y + CAPTAIN_YOFFS; if (delta_status_flags & LEFT) { Stamp.frame = CSPtr->turn; if (!(delta_status_flags & RIGHT)) { Stamp.frame = SetRelFrameIndex (Stamp.frame, 3); if (Pass == 2) { if (cur_status_flags & LEFT) Stamp.frame = IncFrameIndex (Stamp.frame); else Stamp.frame = DecFrameIndex (Stamp.frame); } } else if (cur_status_flags & RIGHT) { if (Pass == 1) Stamp.frame = SetRelFrameIndex (Stamp.frame, 3); else Stamp.frame = IncFrameIndex (Stamp.frame); DrawStamp (&Stamp); Stamp.frame = DecFrameIndex (Stamp.frame); } else { if (Pass == 1) Stamp.frame = IncFrameIndex (Stamp.frame); else Stamp.frame = SetRelFrameIndex (Stamp.frame, 3); DrawStamp (&Stamp); Stamp.frame = IncFrameIndex (Stamp.frame); } DrawStamp (&Stamp); } else if (delta_status_flags & RIGHT) { Stamp.frame = CSPtr->turn; Stamp.frame = IncFrameIndex (Stamp.frame); if (Pass == 2) { if (cur_status_flags & RIGHT) Stamp.frame = DecFrameIndex (Stamp.frame); else Stamp.frame = IncFrameIndex (Stamp.frame); } DrawStamp (&Stamp); } if (delta_status_flags & THRUST) { Stamp.frame = CSPtr->thrust; if (Pass == 1) Stamp.frame = IncFrameIndex (Stamp.frame); else if (cur_status_flags & THRUST) Stamp.frame = SetRelFrameIndex (Stamp.frame, 2); DrawStamp (&Stamp); } if (delta_status_flags & WEAPON) { Stamp.frame = CSPtr->weapon; if (Pass == 1) Stamp.frame = IncFrameIndex (Stamp.frame); else if (cur_status_flags & WEAPON) Stamp.frame = SetRelFrameIndex (Stamp.frame, 2); DrawStamp (&Stamp); } if (delta_status_flags & SPECIAL) { Stamp.frame = CSPtr->special; if (Pass == 1) Stamp.frame = IncFrameIndex (Stamp.frame); else if (cur_status_flags & SPECIAL) Stamp.frame = SetRelFrameIndex (Stamp.frame, 2); DrawStamp (&Stamp); } } void DrawBattleCrewAmount (STARSHIPPTR StarShipPtr) { #define MAX_CREW_DIGITS 3 RECT r; TEXT t; UNICODE buf[40]; t.baseline.x = BATTLE_CREW_X + 2; if (optWhichMenu == OPT_PC) t.baseline.x -= 8; t.baseline.y = BATTLE_CREW_Y + ((StarShipPtr->RaceDescPtr->ship_info.ship_flags & GOOD_GUY) ? GOOD_GUY_YOFFS : BAD_GUY_YOFFS); t.align = ALIGN_LEFT; t.pStr = buf; t.CharCount = (COUNT)~0; r.corner.x = t.baseline.x; r.corner.y = t.baseline.y - 5; r.extent.width = 6 * MAX_CREW_DIGITS + 6; r.extent.height = 5; sprintf (buf, "%u", StarShipPtr->RaceDescPtr->ship_info.crew_level); SetContextFont (StarConFont); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); DrawFilledRectangle (&r); SetContextForeGroundColor (BLACK_COLOR); font_DrawText (&t); } void DrawCaptainsWindow (STARSHIPPTR StarShipPtr) { COORD y, y_offs; RECT r; STAMP s; FRAME Frame; RACE_DESCPTR RDPtr; RDPtr = StarShipPtr->RaceDescPtr; Frame = RDPtr->ship_data.captain_control.background; if (Frame) { Frame = SetAbsFrameIndex (Frame, 0); RDPtr->ship_data.captain_control.background = Frame; Frame = SetRelFrameIndex (Frame, 1); RDPtr->ship_data.captain_control.turn = Frame; Frame = SetRelFrameIndex (Frame, 5); RDPtr->ship_data.captain_control.thrust = Frame; Frame = SetRelFrameIndex (Frame, 3); RDPtr->ship_data.captain_control.weapon = Frame; Frame = SetRelFrameIndex (Frame, 3); RDPtr->ship_data.captain_control.special = Frame; } BatchGraphics (); y_offs = CAPTAIN_YOFFS + ((RDPtr->ship_info.ship_flags & GOOD_GUY) ? GOOD_GUY_YOFFS : BAD_GUY_YOFFS); r.corner.x = CAPTAIN_XOFFS - 2; r.corner.y = y_offs - 4; r.extent.width = STATUS_WIDTH - CAPTAIN_XOFFS; r.extent.height = SHIP_STATUS_HEIGHT - CAPTAIN_YOFFS + 2; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); DrawFilledRectangle (&r); y = y_offs - CAPTAIN_YOFFS; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); r.corner.x = 1; r.corner.y = SHIP_INFO_HEIGHT + y; r.extent.width = 1; r.extent.height = (SHIP_STATUS_HEIGHT - SHIP_INFO_HEIGHT - 2); DrawFilledRectangle (&r); r.corner.x = 0; ++r.extent.height; DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); r.corner.x = STATUS_WIDTH - 1; r.corner.y = SHIP_INFO_HEIGHT + y; r.extent.width = 1; r.extent.height = SHIP_STATUS_HEIGHT - SHIP_INFO_HEIGHT; DrawFilledRectangle (&r); r.corner.x = STATUS_WIDTH - 2; DrawFilledRectangle (&r); r.corner.x = 1; r.extent.width = STATUS_WIDTH - 2; r.corner.y = (SHIP_STATUS_HEIGHT - 2) + y; r.extent.height = 1; DrawFilledRectangle (&r); r.corner.x = 0; ++r.extent.width; ++r.corner.y; DrawFilledRectangle (&r); { SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); r.corner.x = 59; r.corner.y = y_offs; r.extent.width = 1; r.extent.height = 30; DrawFilledRectangle (&r); r.corner.x = 3; r.corner.y += 30; r.extent.width = 57; r.extent.height = 1; DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); r.corner.x = 3; r.extent.width = 57; r.corner.y = y_offs - 1; r.extent.height = 1; DrawFilledRectangle (&r); r.corner.x = 3; r.extent.width = 1; r.corner.y = y_offs; r.extent.height = 30; DrawFilledRectangle (&r); s.frame = RDPtr->ship_data.captain_control.background; s.origin.x = CAPTAIN_XOFFS; s.origin.y = y_offs; DrawStamp (&s); } if (StarShipPtr->captains_name_index == 0) { if (RDPtr->ship_info.ship_flags & GOOD_GUY) { // SIS TEXT t; t.baseline.x = STATUS_WIDTH >> 1; t.baseline.y = y_offs + 6; t.align = ALIGN_CENTER; t.pStr = GLOBAL_SIS (CommanderName); t.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02)); SetContextFont (TinyFont); font_DrawText (&t); } } if (RDPtr->ship_info.max_crew > MAX_CREW_SIZE || RDPtr->ship_info.ship_flags & PLAYER_CAPTAIN) { // All crew doesn't fit in the graphics; print a number. // Always print a number for the SIS in the full game. DrawBattleCrewAmount (StarShipPtr); } UnbatchGraphics (); } BOOLEAN DeltaEnergy (ELEMENTPTR ElementPtr, SIZE energy_delta) { BOOLEAN retval; STARSHIPPTR StarShipPtr; SHIP_INFOPTR ShipInfoPtr; retval = TRUE; GetElementStarShip (ElementPtr, &StarShipPtr); ShipInfoPtr = &StarShipPtr->RaceDescPtr->ship_info; if (energy_delta >= 0) { if ((BYTE)(ShipInfoPtr->energy_level + (BYTE)energy_delta) > ShipInfoPtr->max_energy) energy_delta = ShipInfoPtr->max_energy - ShipInfoPtr->energy_level; } else { if ((BYTE)-energy_delta > ShipInfoPtr->energy_level) { retval = FALSE; } } if (!retval) StarShipPtr->cur_status_flags |= LOW_ON_ENERGY; else { StarShipPtr->cur_status_flags &= ~LOW_ON_ENERGY; StarShipPtr->energy_counter = StarShipPtr->RaceDescPtr->characteristics.energy_wait; DeltaStatistics (StarShipPtr, 0, energy_delta); } return (retval); } BOOLEAN DeltaCrew (ELEMENTPTR ElementPtr, SIZE crew_delta) { BOOLEAN retval; STARSHIPPTR StarShipPtr; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE && (ElementPtr->state_flags & BAD_GUY)) return (TRUE); /* Samatra can't be crew-modified */ retval = TRUE; GetElementStarShip (ElementPtr, &StarShipPtr); if (crew_delta > 0) { SHIP_INFOPTR ShipInfoPtr; ShipInfoPtr = &StarShipPtr->RaceDescPtr->ship_info; ElementPtr->crew_level += crew_delta; if (ElementPtr->crew_level > ShipInfoPtr->max_crew) { crew_delta = ShipInfoPtr->max_crew - ShipInfoPtr->crew_level; ElementPtr->crew_level = ShipInfoPtr->max_crew; } } else if (crew_delta < 0) { if (ElementPtr->crew_level > (COUNT)-crew_delta) ElementPtr->crew_level += crew_delta; else { crew_delta = -(SIZE)ElementPtr->crew_level; ElementPtr->crew_level = 0; retval = FALSE; } } DeltaStatistics (StarShipPtr, crew_delta, 0); return (retval); } void PreProcessStatus (PELEMENT ShipPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->captains_name_index || (StarShipPtr->RaceDescPtr->ship_info.ship_flags & GOOD_GUY)) { ELEMENT_FLAGS old_status_flags, cur_status_flags; CAPTAIN_STUFFPTR CSPtr; cur_status_flags = StarShipPtr->cur_status_flags; old_status_flags = StarShipPtr->old_status_flags; old_status_flags ^= cur_status_flags; CSPtr = &StarShipPtr->RaceDescPtr->ship_data.captain_control; old_status_flags &= (LEFT | RIGHT | THRUST | WEAPON | SPECIAL); if (old_status_flags) { CaptainsWindow (CSPtr, (StarShipPtr->RaceDescPtr->ship_info.ship_flags & GOOD_GUY) ? GOOD_GUY_YOFFS : BAD_GUY_YOFFS, old_status_flags, cur_status_flags, 1); } } } void PostProcessStatus (PELEMENT ShipPtr) { STARSHIPPTR StarShipPtr; GetElementStarShip (ShipPtr, &StarShipPtr); if (StarShipPtr->captains_name_index || (StarShipPtr->RaceDescPtr->ship_info.ship_flags & GOOD_GUY)) { COORD y; ELEMENT_FLAGS cur_status_flags, old_status_flags; cur_status_flags = StarShipPtr->cur_status_flags; y = (StarShipPtr->RaceDescPtr->ship_info.ship_flags & GOOD_GUY) ? GOOD_GUY_YOFFS : BAD_GUY_YOFFS; if (ShipPtr->crew_level == 0) { StarShipPtr->cur_status_flags &= ~(LEFT | RIGHT | THRUST | WEAPON | SPECIAL); if (StarShipPtr->RaceDescPtr->ship_info.crew_level == 0) { #define CAPTAIN_WIDTH 55 #define CAPTAIN_HEIGHT 30 BYTE i; COLOR c; RECT r; i = (BYTE)(NUM_EXPLOSION_FRAMES * 3 - 1) - ShipPtr->life_span; if (i <= 4) { static const COLOR flash_tab0[] = { BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x19, 0x19), 0x24), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F), }; c = flash_tab0[i]; r.corner.x = CAPTAIN_XOFFS; r.corner.y = y + CAPTAIN_YOFFS; r.extent.width = CAPTAIN_WIDTH; r.extent.height = CAPTAIN_HEIGHT; } else { SetContextForeGroundColor (BLACK_COLOR); i -= 5; if (i <= 14) { static const COLOR flash_tab1[] = { BUILD_COLOR (MAKE_RGB15 (0x1E, 0x1F, 0x12), 0x70), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x71), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x18, 0x00), 0x79), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7C), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7D), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7E), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7F), BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A), BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C), BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D), }; c = flash_tab1[i]; r.corner.x = CAPTAIN_XOFFS + i; r.corner.y = y + CAPTAIN_YOFFS + i; r.extent.width = CAPTAIN_WIDTH - (i << 1); r.extent.height = CAPTAIN_HEIGHT - (i << 1); if (r.extent.height == 2) ++r.extent.height; DrawRectangle (&r); ++r.corner.x; ++r.corner.y; r.extent.width -= 2; r.extent.height -= 2; } else if ((i -= 15) <= 4) { r.corner.y = y + (CAPTAIN_YOFFS + 15); r.extent.width = i + 1; r.extent.height = 1; switch (i) { case 0: r.corner.x = CAPTAIN_XOFFS + 15; i = CAPTAIN_WIDTH - ((15 + 1) << 1); c = BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C); break; case 1: r.corner.x = CAPTAIN_XOFFS + 16; i = CAPTAIN_WIDTH - ((17 + 1) << 1); c = BUILD_COLOR (MAKE_RGB15 (0x07, 0x00, 0x00), 0x2F); break; case 2: r.corner.x = CAPTAIN_XOFFS + 18; i = CAPTAIN_WIDTH - ((20 + 1) << 1); c = BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A); break; case 3: r.corner.x = CAPTAIN_XOFFS + 21; i = CAPTAIN_WIDTH - ((24 + 1) << 1); c = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x29); break; case 4: r.corner.x = CAPTAIN_XOFFS + 25; i = 1; r.extent.width = 2; c = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x50, 0x05), 0x28); break; default: // Should not happen. c = 0; // Keeping compiler quiet. break; } DrawFilledRectangle (&r); r.corner.x += i + r.extent.width; DrawFilledRectangle (&r); r.corner.x -= i; r.extent.width = i; } else { if ((i -= 5) > 2) c = BLACK_COLOR; else { static const COLOR flash_tab2[] = { BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D), BUILD_COLOR (MAKE_RGB15 (0x0B, 0x00, 0x00), 0x2E), }; c = flash_tab2[i]; } r.corner.x = CAPTAIN_XOFFS + (CAPTAIN_WIDTH >> 1); r.corner.y = y + CAPTAIN_YOFFS + ((CAPTAIN_HEIGHT + 1) >> 1); r.extent.width = 1; r.extent.height = 1; } } SetContextForeGroundColor (c); DrawFilledRectangle (&r); } } old_status_flags = StarShipPtr->old_status_flags; old_status_flags = (old_status_flags ^ cur_status_flags) & (LEFT | RIGHT | THRUST | WEAPON | SPECIAL | LOW_ON_ENERGY); if (old_status_flags) { if (old_status_flags & LOW_ON_ENERGY) { if (!(cur_status_flags & LOW_ON_ENERGY)) DrawCrewFuelString (y, 1); else DrawCrewFuelString (y, -1); } old_status_flags &= (LEFT | RIGHT | THRUST | WEAPON | SPECIAL); if (old_status_flags) { CaptainsWindow ( &StarShipPtr->RaceDescPtr->ship_data.captain_control, y, old_status_flags, cur_status_flags, 2); } } StarShipPtr->old_status_flags = cur_status_flags; } } uqm-0.6.2/sc2/src/sc2code/encount.h0000600000175000017500000001141110543202103015417 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ENCOUNT_H #define _ENCOUNT_H #include "displist.h" #include "libs/gfxlib.h" #include "planets/planets.h" #include "races.h" typedef QUEUE_HANDLE HENCOUNTER; #define MAX_HYPER_SHIPS 7 #define ONE_SHOT_ENCOUNTER (1 << 7) #define ENCOUNTER_REFORMING (1 << 6) typedef struct { POINT star_pt; BYTE Type, Index; SHIP_INFO ShipList[MAX_HYPER_SHIPS]; } EXTENDED_STAR_DESC; typedef EXTENDED_STAR_DESC *PEXTENDED_STAR_DESC; typedef struct { HENCOUNTER pred, succ; HELEMENT hElement; SIZE transition_state; POINT origin; COUNT radius; EXTENDED_STAR_DESC SD; SDWORD log_x, log_y; } ENCOUNTER; typedef ENCOUNTER *PENCOUNTER; #define AllocEncounter() AllocLink (&GLOBAL (encounter_q)) #define PutEncounter(h) PutQueue (&GLOBAL (encounter_q), h) #define InsertEncounter(h,i) InsertQueue (&GLOBAL (encounter_q), h, i) #define GetHeadEncounter() GetHeadLink (&GLOBAL (encounter_q)) #define GetTailEncounter() GetTailLink (&GLOBAL (encounter_q)) #define LockEncounter(h,eptr) *(eptr) = (ENCOUNTERPTR)LockLink (&GLOBAL (encounter_q), h) #define UnlockEncounter(h) UnlockLink (&GLOBAL (encounter_q), h) #define RemoveEncounter(h) RemoveQueue (&GLOBAL (encounter_q), h) #define FreeEncounter(h) FreeLink (&GLOBAL (encounter_q), h) #define GetPredEncounter(l) _GetPredLink (l) #define GetSuccEncounter(l) _GetSuccLink (l) #define ENCOUNTERPTR PENCOUNTER enum { SOL_DEFINED = 1, SHOFIXTI_DEFINED, MAIDENS_DEFINED, START_COLONY_DEFINED, SPATHI_DEFINED, ZOQFOT_DEFINED, MELNORME0_DEFINED, MELNORME1_DEFINED, MELNORME2_DEFINED, MELNORME3_DEFINED, MELNORME4_DEFINED, MELNORME5_DEFINED, MELNORME6_DEFINED, MELNORME7_DEFINED, MELNORME8_DEFINED, TALKING_PET_DEFINED, CHMMR_DEFINED, SYREEN_DEFINED, BURVIXESE_DEFINED, SLYLANDRO_DEFINED, DRUUGE_DEFINED, BOMB_DEFINED, AQUA_HELIX_DEFINED, SUN_DEVICE_DEFINED, TAALO_PROTECTOR_DEFINED, SHIP_VAULT_DEFINED, URQUAN_WRECK_DEFINED, VUX_BEAST_DEFINED, SAMATRA_DEFINED, ZOQ_SCOUT_DEFINED, MYCON_DEFINED, EGG_CASE0_DEFINED, EGG_CASE1_DEFINED, EGG_CASE2_DEFINED, PKUNK_DEFINED, UTWIG_DEFINED, SUPOX_DEFINED, YEHAT_DEFINED, VUX_DEFINED, ORZ_DEFINED, THRADD_DEFINED, RAINBOW_DEFINED, ILWRATH_DEFINED, ANDROSYNTH_DEFINED, MYCON_TRAP_DEFINED }; #define UMGAH_DEFINED TALKING_PET_DEFINED #define TEXT_X_OFFS 1 #define TEXT_Y_OFFS 1 #define SIS_TEXT_WIDTH (SIS_SCREEN_WIDTH - (TEXT_X_OFFS << 1)) extern STAR_DESCPTR CurStarDescPtr; extern STAR_DESCPTR star_array; #define NUM_SOLAR_SYSTEMS 502 extern STAR_DESCPTR FindStar (STAR_DESCPTR pLastStar, PPOINT puniverse, SIZE xbounds, SIZE ybounds); extern void GetClusterName (STAR_DESCPTR pSD, UNICODE buf[]); enum { HAIL = 0, ATTACK }; extern void EncounterBattle (void); extern void BuildBattle (COUNT which_player); extern COUNT InitEncounter (void); extern COUNT UninitEncounter (void); extern COUNT InitCommunication (RESOURCE which_comm); extern void RaceCommunication (void); extern void GenerateSOL (BYTE control); extern void GenerateShofixti (BYTE control); extern void GenerateColony (BYTE control); extern void GenerateSpathi (BYTE control); extern void GenerateZoqFotPik (BYTE control); extern void GenerateMelnorme (BYTE control); extern void GenerateTalkingPet (BYTE control); extern void GenerateChmmr (BYTE control); extern void GenerateSyreen (BYTE control); extern void GenerateBurvixes (BYTE control); extern void GenerateSlylandro (BYTE control); extern void GenerateDruuge (BYTE control); extern void GenerateUtwig (BYTE control); extern void GenerateThradd (BYTE control); extern void GenerateMycon (BYTE control); extern void GenerateOrz (BYTE control); extern void GenerateShipVault (BYTE control); extern void GenerateUrquanWreck (BYTE control); extern void GenerateVUX (BYTE control); extern void GenerateSamatra (BYTE control); extern void GenerateYehat (BYTE control); extern void GeneratePkunk (BYTE control); extern void GenerateSupox (BYTE control); extern void GenerateRainbow (BYTE control); extern void GenerateIlwrath (BYTE control); extern SIZE EncounterRace; extern BYTE EncounterGroup; #endif /* _ENCOUNT_H */ uqm-0.6.2/sc2/src/sc2code/libs/0000755000175000017500000000000010552600274014551 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/vidlib.h0000600000175000017500000000263210543202055016161 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _VIDLIB_H #define _VIDLIB_H #include "compiler.h" typedef enum { NO_FMV = 0, HARDWARE_FMV, SOFTWARE_FMV } VIDEO_TYPE; #define MODES_UNDEFINED ((BYTE)~0) typedef DWORD VIDEO_REF; extern BOOLEAN InitVideo (BOOLEAN UseCDROM); extern void UninitVideo (void); extern BYTE SetVideoMode (BYTE new_mode); extern BYTE GetVideoMode (void); extern VIDEO_REF LoadVideoFile (const char *pStr); extern BOOLEAN DestroyVideo (VIDEO_REF VideoRef); extern VIDEO_TYPE VidPlay (VIDEO_REF VidRef, const char *loopname, BOOLEAN uninit); extern void VidStop (void); extern VIDEO_REF VidPlaying (void); extern void VidDoInput (void); #endif /* _VIDLIB_H */ uqm-0.6.2/sc2/src/sc2code/libs/strings/0000755000175000017500000000000010552600274016242 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/strings/strintrn.h0000600000175000017500000000327310543202042020262 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINTRN_H #define _STRINTRN_H #include #include #include "strlib.h" #include "memlib.h" #include "reslib.h" typedef struct string_table { unsigned short StringCount; unsigned short flags; DWORD StringOffsets[1]; } STRING_TABLE_DESC; typedef STRING_TABLE_DESC *PSTRING_TABLE_DESC; #define HAS_SOUND_CLIPS (1 << 0) #define HAS_TIMESTAMP (1 << 1) #define STRING_TABLEPTR PSTRING_TABLE_DESC #define AllocStringTable(s) AllocResourceData((s),MEM_SOUND) #define LockStringTable(h,ps) LockResourceData((MEM_HANDLE)LOWORD(h),ps) #define UnlockStringTable(h) UnlockResourceData ((MEM_HANDLE)LOWORD(h)) #define FreeStringTable(h) FreeResourceData ((MEM_HANDLE)LOWORD(h)) #define STRING_INDEX(S) ((COUNT)HIWORD (S)) #define BUILD_STRING(h,i) ((STRING_TABLE)MAKE_DWORD(h,i)) #define BUILD_STRING_TABLE(h) (STRING_TABLE)(h) extern MEM_HANDLE _GetStringData (uio_Stream *fp, DWORD length); #endif /* _STRINTRN_H */ uqm-0.6.2/sc2/src/sc2code/libs/strings/sresins.c0000600000175000017500000000216110543202042020053 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "strintrn.h" BOOLEAN InstallStringTableResType (COUNT string_type) { return (InstallResTypeVectors (string_type, _GetStringData, FreeResourceData)); } STRING_TABLE LoadStringTableInstance (DWORD res) { MEM_HANDLE hData; hData = res_GetResource (res); if (hData) { res_DetachResource (res); } return (BUILD_STRING_TABLE (hData)); } uqm-0.6.2/sc2/src/sc2code/libs/strings/unicode.c0000644000175000017500000002700410550602510020030 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "port.h" #include #include #include #include #include "strlib.h" #include "libs/log.h" // Resynchronise (skip everything starting with 0x10xxxxxx): static inline void resyncUTF8(const unsigned char **ptr) { while ((**ptr & 0xc0) == 0x80) *ptr++; } // Get one character from a UTF-8 encoded string. // *ptr will point to the start of the next character. // Returns 0 if the encoding is bad. This can be distinguished from the // '\0' character by checking whether **ptr == '\0' before calling this // function. wchar_t getCharFromString(const unsigned char **ptr) { wchar_t result; if (**ptr < 0x80) { // 0xxxxxxx, regular ASCII result = **ptr; (*ptr)++; return result; } if ((**ptr & 0xe0) == 0xc0) { // 110xxxxx; 10xxxxxx must follow // Value between 0x00000080 and 0x000007ff (inclusive) result = **ptr & 0x1f; (*ptr)++; if ((**ptr & 0xc0) != 0x80) goto err; result = (result << 6) | ((**ptr) & 0x3f); (*ptr)++; if (result < 0x00000080) { // invalid encoding - must reject goto err; } return result; } if ((**ptr & 0xf0) == 0xe0) { // 1110xxxx; 10xxxxxx 10xxxxxx must follow // Value between 0x00000800 and 0x0000ffff (inclusive) result = **ptr & 0x0f; (*ptr)++; if ((**ptr & 0xc0) != 0x80) goto err; result = (result << 6) | ((**ptr) & 0x3f); (*ptr)++; if ((**ptr & 0xc0) != 0x80) goto err; result = (result << 6) | ((**ptr) & 0x3f); (*ptr)++; if (result < 0x00000800) { // invalid encoding - must reject goto err; } return result; } if ((**ptr & 0xf8) == 0xf0) { // 11110xxx; 10xxxxxx 10xxxxxx 10xxxxxx must follow // Value between 0x00010000 and 0x0010ffff (inclusive) result = **ptr & 0x07; (*ptr)++; if ((**ptr & 0xc0) != 0x80) goto err; result = (result << 6) | ((**ptr) & 0x3f); (*ptr)++; if ((**ptr & 0xc0) != 0x80) goto err; result = (result << 6) | ((**ptr) & 0x3f); (*ptr)++; if ((**ptr & 0xc0) != 0x80) goto err; result = (result << 6) | ((**ptr) & 0x3f); (*ptr)++; if (result < 0x00010000) { // invalid encoding - must reject goto err; } return result; } err: log_add(log_Warning, "Warning: Invalid UTF8 sequence."); // Resynchronise (skip everything starting with 0x10xxxxxx): resyncUTF8(ptr); return 0; } wchar_t getCharFromStringN(const unsigned char **ptr, const unsigned char *end) { size_t numBytes; if (*ptr == end) goto err; if (**ptr < 0x80) { numBytes = 1; } else if ((**ptr & 0xe0) == 0xc0) { numBytes = 2; } else if ((**ptr & 0xf0) == 0xe0) { numBytes = 3; } else if ((**ptr & 0xf8) == 0xf0) { numBytes = 4; } else goto err; if (*ptr + numBytes > end) goto err; return getCharFromString(ptr); err: *ptr = end; return 0; } // Get one line from a string. // A line is terminated with either CRLF (DOS/Windows), // LF (Unix, MacOS X), or CR (old MacOS). // The end of the string is reached when **startNext == '\0'. // NULL is returned if the string is not valid UTF8. In this case // *end points to the first invalid character (or the character before if // it was a LF), and *startNext to the start of the next (possibly invalid // too) character. unsigned char * getLineFromString(const unsigned char *start, const unsigned char **end, const unsigned char **startNext) { const unsigned char *ptr = start; const unsigned char *lastPtr; wchar_t ch; // Search for the first newline. for (;;) { if (*ptr == '\0') { *end = ptr; *startNext = ptr; return (unsigned char *) start; } lastPtr = ptr; ch = getCharFromString(&ptr); if (ch == '\0') { // Bad string *end = lastPtr; *startNext = ptr; return NULL; } if (ch == '\n') { *end = lastPtr; if (*ptr == '\0'){ // LF at the end of the string. *startNext = ptr; return (unsigned char *) start; } ch = getCharFromString(&ptr); if (ch == '\0') { // Bad string return NULL; } if (ch == '\r') { // LFCR *startNext = ptr; } else { // LF *startNext = *end; } return (unsigned char *) start; } else if (ch == '\r') { *end = lastPtr; *startNext = ptr; return (unsigned char *) start; } // else: a normal character } } size_t utf8StringCount(const unsigned char *start) { size_t count = 0; wchar_t ch; for (;;) { ch = getCharFromString(&start); if (ch == '\0') return count; count++; } } size_t utf8StringCountN(const unsigned char *start, const unsigned char *end) { size_t count = 0; wchar_t ch; for (;;) { ch = getCharFromStringN(&start, end); if (ch == '\0') return count; count++; } } // Locates a wide char (ch) in a UTF-8 string (pStr) // returns the char positions when found // -1 when not found int utf8StringPos (const unsigned char *pStr, wchar_t ch) { int pos; for (pos = 0; *pStr != '\0'; ++pos) { if (getCharFromString (&pStr) == ch) return pos; } if (ch == '\0' && *pStr == '\0') return pos; return -1; } // Safe version of strcpy(), somewhat analogous to strncpy() // except it guarantees a 0-term when size > 0 // when size == 0, returns NULL unsigned char * utf8StringCopy (unsigned char *dst, size_t size, const unsigned char *src) { if (size == 0) return 0; strncpy (dst, src, size); dst[size - 1] = '\0'; return dst; } // TODO: this is not implemented with respect to collating order int utf8StringCompare (const unsigned char *str1, const unsigned char *str2) { #if 0 // wchar_t comparing version wchar_t ch1; wchar_t ch2; for (;;) { int cmp; ch1 = getCharFromString(&str1); ch2 = getCharFromString(&str2); if (ch1 == '\0' || ch2 == '\0') break; cmp = utf8CompareChar (ch1, ch2); if (cmp != 0) return cmp; } if (ch1 != '\0') { // ch2 == '\0' // str2 ends, str1 continues return 1; } if (ch2 != '\0') { // ch1 == '\0' // str1 ends, str2 continues return -1; } // ch1 == '\0' && ch2 == '\0'. // Strings match completely. return 0; #else // this will do for now return strcmp (str1, str2); #endif } unsigned char * skipUTF8Chars(const unsigned char *ptr, size_t num) { wchar_t ch; const unsigned char *oldPtr; while (num--) { oldPtr = ptr; ch = getCharFromString(&ptr); if (ch == '\0') return (unsigned char *) oldPtr; } return (unsigned char *) ptr; } // Decodes a UTF-8 string (start) into a wide char string (wstr) // returns number of chars decoded and stored, not counting 0-term // any chars that do not fit are truncated // wide string term 0 is always appended, unless the destination // buffer is 0 chars long size_t getWideFromStringN(wchar_t *wstr, size_t maxcount, const unsigned char *start, const unsigned char *end) { wchar_t *next; if (maxcount == 0) return 0; // always leave room for 0-term --maxcount; for (next = wstr; maxcount > 0; ++next, --maxcount) { *next = getCharFromStringN(&start, end); if (*next == 0) break; } *next = 0; // term return next - wstr; } // See getStringFromWideN() for functionality // the only difference is that the source string (start) length is // calculated by searching for 0-term size_t getWideFromString(wchar_t *wstr, size_t maxcount, const unsigned char *start) { wchar_t *next; if (maxcount == 0) return 0; // always leave room for 0-term --maxcount; for (next = wstr; maxcount > 0; ++next, --maxcount) { *next = getCharFromString(&start); if (*next == 0) break; } *next = 0; // term return next - wstr; } // Encode one wide character into UTF-8 // returns number of bytes used in the buffer, // 0 : invalid or unsupported char // <0 : negative of bytes needed if buffer too small // string term '\0' is *not* appended or counted int getStringFromChar(unsigned char *ptr, size_t size, wchar_t ch) { int i; static const struct range_def { wchar_t lim; int marker; int mask; } ranges[] = { {0x0000007f, 0x00, 0x7f}, {0x000007ff, 0xc0, 0x1f}, {0x0000ffff, 0xe0, 0x0f}, {0x001fffff, 0xf0, 0x07}, {0x03ffffff, 0xf8, 0x03}, {0x7fffffff, 0xfc, 0x01}, {0x00000000, 0x00, 0x00} // term }; const struct range_def *def; // lookup the range for (i = 0, def = ranges; ch > def->lim && def->mask != 0; ++i, ++def) ; if (def->mask == 0) { // invalid or unsupported char log_add(log_Warning, "Warning: Invalid or unsupported wide char (%lu)", (unsigned long)ch); return 0; } if ((size_t)i + 1 > size) return -(i + 1); // unrolled for speed switch (i) { case 5: ptr[5] = (ch & 0x3f) | 0x80; ch >>= 6; case 4: ptr[4] = (ch & 0x3f) | 0x80; ch >>= 6; case 3: ptr[3] = (ch & 0x3f) | 0x80; ch >>= 6; case 2: ptr[2] = (ch & 0x3f) | 0x80; ch >>= 6; case 1: ptr[1] = (ch & 0x3f) | 0x80; ch >>= 6; case 0: ptr[0] = (ch & def->mask) | def->marker; } return i + 1; } // Encode a wide char string (wstr) into a UTF-8 string (ptr) // returns number of bytes used in the buffer (includes 0-term) // any chars that do not fit are truncated // string term '\0' is always appended, unless the destination // buffer is 0 bytes long size_t getStringFromWideN(unsigned char *ptr, size_t size, const wchar_t *wstr, size_t count) { unsigned char *next; int used; if (size == 0) return 0; // always leave room for 0-term --size; for (next = ptr; size > 0 && count > 0; size -= used, next += used, --count, ++wstr) { used = getStringFromChar(next, size, *wstr); if (used < 0) break; // not enough room if (used == 0) { // bad char? *next = '?'; used = 1; } } *next = '\0'; // term return next - ptr + 1; } // See getStringFromWideN() for functionality // the only difference is that the source string (wstr) length is // calculated by searching for 0-term size_t getStringFromWide(unsigned char *ptr, size_t size, const wchar_t *wstr) { const wchar_t *end; for (end = wstr; *end != 0; ++end) ; return getStringFromWideN(ptr, size, wstr, (end - wstr)); } int isWideGraphChar(wchar_t ch) { // this is not technically sufficient, but close enough for us // we'll consider all non-control (CO and C1) chars in 'graph' class // except for the "Private Use Area" (0xE000 - 0xF8FF) // TODO: The private use area is really only glommed by OS X, // and even there, not all of it. (Delete and Backspace both // end up producing characters there -- see bug #942 for the // gory details.) return (ch > 0xa0 && (ch < 0xE000 || ch > 0xF8FF)) || (ch > 0x20 && ch < 0x7f); } int isWidePrintChar(wchar_t ch) { // this is not technically sufficient, but close enough for us // chars in 'print' class are 'graph' + 'space' classes // the only space we currently have defined is 0x20 return (ch == 0x20) || isWideGraphChar(ch); } wchar_t toWideUpper(wchar_t ch) { // this is a very basic Latin-1 implementation // just to get things going return (ch < 0x100) ? toupper(ch) : ch; } wchar_t toWideLower(wchar_t ch) { // this is a very basic Latin-1 implementation // just to get things going return (ch < 0x100) ? tolower(ch) : ch; } uqm-0.6.2/sc2/src/sc2code/libs/strings/strings.c0000600000175000017500000001542310543202042020063 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "strintrn.h" BOOLEAN DestroyStringTable (STRING_TABLE StringTable) { return (FreeStringTable (StringTable)); } STRING CaptureStringTable (STRING_TABLE StringTable) { if (StringTable != 0) { COUNT StringTableIndex; STRING_TABLEPTR StringTablePtr; LockStringTable (StringTable, &StringTablePtr); StringTableIndex = GetStringTableIndex (StringTable); return (BUILD_STRING (StringTable, StringTableIndex)); } return ((STRING)NULL_PTR); } STRING_TABLE ReleaseStringTable (STRING String) { STRING_TABLE StringTable; StringTable = GetStringTable (String); if (StringTable != 0) UnlockStringTable (StringTable); return (StringTable); } STRING_TABLE GetStringTable (STRING String) { return ((STRING_TABLE)LOWORD (String)); } COUNT GetStringTableCount (STRING String) { COUNT StringCount; STRING_TABLE StringTable; StringTable = GetStringTable (String); if (StringTable == 0) StringCount = 0; else { STRING_TABLEPTR StringTablePtr; LockStringTable (StringTable, &StringTablePtr); StringCount = StringTablePtr->StringCount; UnlockStringTable (StringTable); } return (StringCount); } COUNT GetStringTableIndex (STRING String) { return (STRING_INDEX (String)); } STRING SetAbsStringTableIndex (STRING String, COUNT StringTableIndex) { STRING_TABLE StringTable; StringTable = GetStringTable (String); if (StringTable == 0) String = 0; else { STRING_TABLEPTR StringTablePtr; LockStringTable (StringTable, &StringTablePtr); StringTableIndex = StringTableIndex % StringTablePtr->StringCount; UnlockStringTable (StringTable); String = BUILD_STRING (StringTable, StringTableIndex); } return (String); } STRING SetRelStringTableIndex (STRING String, SIZE StringTableOffs) { STRING_TABLE StringTable; StringTable = GetStringTable (String); if (StringTable == 0) String = 0; else { STRING_TABLEPTR StringTablePtr; COUNT StringTableIndex; LockStringTable (StringTable, &StringTablePtr); while (StringTableOffs < 0) StringTableOffs += StringTablePtr->StringCount; StringTableIndex = (STRING_INDEX (String) + StringTableOffs) % StringTablePtr->StringCount; UnlockStringTable (StringTable); String = BUILD_STRING (StringTable, StringTableIndex); } return (String); } COUNT GetStringLength (STRING String) { COUNT StringLength; STRING_TABLE StringTable; StringTable = GetStringTable (String); if (StringTable == 0) StringLength = 0; else { COUNT StringIndex; STRING_TABLEPTR StringTablePtr; StringIndex = STRING_INDEX (String); LockStringTable (StringTable, &StringTablePtr); { STRINGPTR start; STRINGPTR end; start = (STRINGPTR) ((BYTE *) StringTablePtr + StringTablePtr->StringOffsets[StringIndex]); end = (STRINGPTR) ((BYTE *) StringTablePtr + StringTablePtr->StringOffsets[StringIndex + 1]); StringLength = utf8StringCountN(start, end); } #if 0 StringLength = (COUNT)( StringTablePtr->StringOffsets[StringIndex + 1] - StringTablePtr->StringOffsets[StringIndex]); #endif UnlockStringTable (StringTable); } return (StringLength); } COUNT GetStringLengthBin (STRING String) { COUNT StringLength; STRING_TABLE StringTable; StringTable = GetStringTable (String); if (StringTable == 0) StringLength = 0; else { COUNT StringIndex; STRING_TABLEPTR StringTablePtr; StringIndex = STRING_INDEX (String); LockStringTable (StringTable, &StringTablePtr); StringLength = (COUNT)( StringTablePtr->StringOffsets[StringIndex + 1] - StringTablePtr->StringOffsets[StringIndex]); UnlockStringTable (StringTable); } return (StringLength); } STRINGPTR GetStringSoundClip (STRING String) { STRINGPTR StringAddr; STRING_TABLE StringTable; StringTable = GetStringTable (String); if (StringTable == 0) StringAddr = 0; else { COUNT StringIndex; STRING_TABLEPTR StringTablePtr; StringIndex = STRING_INDEX (String); LockStringTable (StringTable, &StringTablePtr); if (!(StringTablePtr->flags & HAS_SOUND_CLIPS) || ((StringIndex += StringTablePtr->StringCount + 1), StringTablePtr->StringOffsets[StringIndex + 1] == StringTablePtr->StringOffsets[StringIndex])) StringAddr = 0; else { StringAddr = (STRINGPTR) ((BYTE *) StringTablePtr + StringTablePtr->StringOffsets[StringIndex]); } UnlockStringTable (StringTable); } return (StringAddr); } STRINGPTR GetStringTimeStamp (STRING String) { STRINGPTR StringAddr; STRING_TABLE StringTable; StringTable = GetStringTable (String); if (StringTable == 0) StringAddr = 0; else { COUNT StringIndex; STRING_TABLEPTR StringTablePtr; int offset; StringIndex = STRING_INDEX (String); LockStringTable (StringTable, &StringTablePtr); offset = (StringTablePtr->flags & HAS_SOUND_CLIPS) ? 1 : 0; if (!(StringTablePtr->flags & HAS_TIMESTAMP) || ((StringIndex += (StringTablePtr->StringCount + 1) << offset), StringTablePtr->StringOffsets[StringIndex + 1] == StringTablePtr->StringOffsets[StringIndex])) StringAddr = 0; else { StringAddr = (STRINGPTR) ((BYTE *) StringTablePtr + StringTablePtr->StringOffsets[StringIndex]); } UnlockStringTable (StringTable); } return (StringAddr); } STRINGPTR GetStringAddress (STRING String) { STRINGPTR StringAddr; STRING_TABLE StringTable; StringTable = GetStringTable (String); if (StringTable == 0) StringAddr = 0; else { COUNT StringIndex; STRING_TABLEPTR StringTablePtr; StringIndex = STRING_INDEX (String); LockStringTable (StringTable, &StringTablePtr); StringAddr = (STRINGPTR) ((BYTE *) StringTablePtr + StringTablePtr->StringOffsets[StringIndex]); UnlockStringTable (StringTable); } return (StringAddr); } BOOLEAN GetStringContents (STRING String, STRINGPTR StringBuf, BOOLEAN AppendSpace) { STRINGPTR StringAddr; COUNT StringLength; if ((StringAddr = GetStringAddress (String)) != 0 && (StringLength = GetStringLengthBin (String)) != 0) { memcpy (StringBuf, StringAddr, StringLength); if (AppendSpace) StringBuf[StringLength++] = ' '; StringBuf[StringLength] = '\0'; return (TRUE); } *StringBuf = '\0'; return (FALSE); } uqm-0.6.2/sc2/src/sc2code/libs/strings/getstr.c0000600000175000017500000002036410543202042017702 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "options.h" #include "strintrn.h" #include "libs/graphics/gfx_common.h" #include "libs/reslib.h" #include "libs/log.h" static void dword_convert (PDWORD dword_array, COUNT num_dwords) { PBYTE p = (PBYTE)dword_array; do { *dword_array++ = MAKE_DWORD ( MAKE_WORD (p[3], p[2]), MAKE_WORD (p[1], p[0]) ); p += 4; } while (--num_dwords); } MEM_HANDLE _GetStringData (uio_Stream *fp, DWORD length) { MEM_HANDLE hData; { char *s; if (_cur_resfile_name && (s = strrchr (_cur_resfile_name, '.')) && stricmp (s, ".txt") == 0) { #define MAX_STRINGS 2048 #define POOL_SIZE 4096 int n, path_len, num_data_sets; DWORD opos, slen[MAX_STRINGS], StringOffs, tot_string_size, clen[MAX_STRINGS], ClipOffs, tot_clip_size, tslen[MAX_STRINGS], TSOffs, tot_ts_size; char CurrentLine[1024], clip_path[1024], *strdata, *clipdata, *ts_data; uio_Stream *timestamp_fp = NULL; if ((strdata = HMalloc (tot_string_size = POOL_SIZE)) == 0) return (0); if ((clipdata = HMalloc (tot_clip_size = POOL_SIZE)) == 0) { HFree (strdata); return (0); } ts_data = NULL; { char *s1, *s2; if (((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0) && (s2 = strrchr (_cur_resfile_name, '\\')) == 0) n = 0; else { if (s2 > s1) s1 = s2; n = s1 - _cur_resfile_name + 1; strncpy (clip_path, _cur_resfile_name, n); } clip_path[n] = '\0'; path_len = strlen (clip_path); } { // try to open the timestamp file char ts_file_name[1024]; strcpy (ts_file_name, _cur_resfile_name); s = strrchr (ts_file_name, '.'); s += 2; *s++ = 's'; *s = '\0'; if ((timestamp_fp = uio_fopen (contentDir, ts_file_name, "rb"))) { log_add (log_Info, "Found timestamp file: %s", ts_file_name); if ((ts_data = HMalloc (tot_ts_size = POOL_SIZE)) == 0) return (0); } } opos = uio_ftell (fp); n = -1; StringOffs = ClipOffs = TSOffs = 0; while (uio_fgets (CurrentLine, sizeof (CurrentLine), fp) && n < MAX_STRINGS - 1) { int l; if (CurrentLine[0] == '#') { char CopyLine[1024]; strcpy (CopyLine, CurrentLine); s = strtok (&CopyLine[1], "()"); if (s) { if (n >= 0) { while (slen[n] > 1 && (strdata[StringOffs - 2] == '\n' || strdata[StringOffs - 2] == '\r')) { --slen[n]; --StringOffs; strdata[StringOffs - 1] = '\0'; } } slen[++n] = 0; // now lets check for timestamp data if (timestamp_fp) { char TimeStampLine[1024], *tsptr; BOOLEAN ts_ok = FALSE; uio_fgets (TimeStampLine, sizeof (TimeStampLine), timestamp_fp); if (TimeStampLine[0] == '#') { tslen[n] = 0; if ((tsptr = strstr (TimeStampLine,s)) && (tsptr += strlen(s)) && (++tsptr)) { ts_ok = TRUE; while (! strcspn(tsptr," \t\r\n") && *tsptr) tsptr++; if (*tsptr) { l = strlen (tsptr) + 1; if (TSOffs + l > tot_ts_size && (ts_data = HRealloc (ts_data, tot_ts_size += POOL_SIZE)) == 0) { HFree (strdata); return (0); } strcpy (&ts_data[TSOffs], tsptr); TSOffs += l; tslen[n] = l; } } } if (!ts_ok) { // timestamp data is invalid, remove all of it log_add (log_Warning, "Invalid timestamp data " "for '%s'. Disabling timestamps", s); HFree (ts_data); ts_data = NULL; uio_fclose (timestamp_fp); timestamp_fp = NULL; TSOffs = 0; } } clen[n] = 0; s = strtok (NULL, " \t\r\n)"); if (s) { l = path_len + strlen (s) + 1; if (ClipOffs + l > tot_clip_size && (clipdata = HRealloc (clipdata, tot_clip_size += POOL_SIZE)) == 0) { HFree (strdata); return (0); } strcpy (&clipdata[ClipOffs], clip_path); strcpy (&clipdata[ClipOffs + path_len], s); ClipOffs += l; clen[n] = l; } } } else if (n >= 0) { l = strlen (CurrentLine) + 1; if (StringOffs + l > tot_string_size && (strdata = HRealloc (strdata, tot_string_size += POOL_SIZE)) == 0) { HFree (clipdata); return (0); } if (slen[n]) { --slen[n]; --StringOffs; } s = &strdata[StringOffs]; slen[n] += l; StringOffs += l; strcpy (s, CurrentLine); } if ((int)uio_ftell (fp) - (int)opos >= (int)length) break; } if (n >= 0) { while (slen[n] > 1 && (strdata[StringOffs - 2] == '\n' || strdata[StringOffs - 2] == '\r')) { --slen[n]; --StringOffs; strdata[StringOffs - 1] = '\0'; } } if (timestamp_fp) uio_fclose (timestamp_fp); hData = 0; num_data_sets = (ClipOffs ? 1 : 0) + (TSOffs ? 1 : 0) + 1; if (++n && (hData = AllocStringTable ( (sizeof (STRING_TABLE_DESC) - sizeof (DWORD)) + (sizeof (DWORD) * ((n + 1) * num_data_sets)) + StringOffs + ClipOffs + TSOffs))) { PDWORD lpStringOffs, lpClipOffs, lpTSOffs; STRING_TABLEPTR lpST; LockStringTable (hData, &lpST); lpST->StringCount = n; lpST->flags = 0; if (ClipOffs) lpST->flags |= HAS_SOUND_CLIPS; if (TSOffs) lpST->flags |= HAS_TIMESTAMP; memcpy (&lpST->StringOffsets[(n + 1) * num_data_sets], strdata, StringOffs); memcpy ((BYTE *)&lpST->StringOffsets[(n + 1) * num_data_sets] + StringOffs, clipdata, ClipOffs); if (TSOffs) memcpy ((BYTE *)&lpST->StringOffsets[ (n + 1) * num_data_sets] + StringOffs + ClipOffs, ts_data, TSOffs); TSOffs = ((BYTE *)&lpST->StringOffsets[(n + 1) * num_data_sets] - (BYTE *)lpST) + StringOffs + ClipOffs; ClipOffs = TSOffs - ClipOffs; StringOffs = ClipOffs - StringOffs; lpStringOffs = lpST->StringOffsets; lpClipOffs = &lpST->StringOffsets[lpST->StringCount + 1]; lpTSOffs = &lpST->StringOffsets[(lpST->StringCount + 1) << ((lpST->flags & HAS_SOUND_CLIPS) ? 1 : 0)]; for (n = 0; n < (int)lpST->StringCount; ++n, ++lpStringOffs, ++lpClipOffs, ++lpTSOffs) { *lpStringOffs = StringOffs; StringOffs += slen[n]; if (lpST->flags & HAS_SOUND_CLIPS) { *lpClipOffs = ClipOffs; ClipOffs += clen[n]; } if (lpST->flags & HAS_TIMESTAMP) { *lpTSOffs = TSOffs; TSOffs += tslen[n]; } } *lpStringOffs = StringOffs; if (lpST->flags & HAS_SOUND_CLIPS) *lpClipOffs = ClipOffs; if (lpST->flags & HAS_TIMESTAMP) *lpTSOffs = TSOffs; UnlockStringTable (hData); } HFree (strdata); HFree (clipdata); if (ts_data) HFree (ts_data); return (hData); } } hData = GetResourceData (fp, length, MEM_SOUND); if (hData) { COUNT StringCount; DWORD StringOffs; PDWORD lpStringOffs; STRING_TABLEPTR lpST; LockStringTable (hData, &lpST); length = *(DWORD *)&lpST->StringCount; dword_convert (&length, 1); lpST->StringCount = (unsigned short)length; StringCount = lpST->StringCount; lpST->flags = 0; lpStringOffs = lpST->StringOffsets; dword_convert (lpStringOffs, StringCount + 1); StringOffs = sizeof (STRING_TABLE_DESC) + (sizeof (DWORD) * StringCount); do { StringOffs += *lpStringOffs; *lpStringOffs++ = StringOffs; } while (StringCount--); UnlockStringTable (hData); } return (hData); } uqm-0.6.2/sc2/src/sc2code/libs/strings/Makeinfo0000600000175000017500000000007710543202042017701 0ustar joeyjoeyuqm_CFILES="getstr.c sfileins.c sresins.c strings.c unicode.c" uqm-0.6.2/sc2/src/sc2code/libs/strings/sfileins.c0000600000175000017500000000254210543202042020204 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "port.h" #include "strintrn.h" #include "uio.h" #include "libs/reslib.h" STRING_TABLE LoadStringTableFile (uio_DirHandle *dir, const char *fileName) { uio_Stream *fp; // FIXME: this theoretically needs a mechanism to prevent races if (_cur_resfile_name) // something else is loading resources atm return 0; fp = res_OpenResFile (dir, fileName, "rb"); if (fp) { MEM_HANDLE hData; _cur_resfile_name = fileName; hData = _GetStringData (fp, LengthResFile (fp)); _cur_resfile_name = 0; res_CloseResFile (fp); return (BUILD_STRING_TABLE (hData)); } return (0); } uqm-0.6.2/sc2/src/sc2code/libs/file/0000755000175000017500000000000010552600274015470 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/file/temp.c0000600000175000017500000001130410543202045016562 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Contains code handling temporary files and dirs #include #include #include #ifdef WIN32 # include #endif #include #include #include "filintrn.h" #include "timelib.h" #include "port.h" #include "libs/compiler.h" #include "libs/log.h" #include "misc.h" static char *tempDirName; uio_DirHandle *tempDir; static void removeTempDir (void) { rmdir (tempDirName); } // Try if the null-terminated path 'dir' to a directory is valid // as temp path. // On success, 'buf' will be filled with the path, with a trailing /, // null-terminated, and 0 is returned. // On failure, EINVAL, ENAMETOOLONG, or one of the errors access() can return // is returned, and the contents of buf is unspecified. static int tryTempDir (char *buf, size_t buflen, const char *dir) { size_t len; int haveSlash; if (dir == NULL) return EINVAL; if (dir[0] == '\0') return EINVAL; len = strlen (dir); haveSlash = (dir[len - 1] == '/' #ifdef WIN32 || dir[len - 1] == '\\' #endif ); if ((haveSlash ? len : len + 1) >= buflen) return ENAMETOOLONG; strcpy (buf, dir); #if 0 //def WIN32 { char *bufPtr; for (bufPtr = buf; *bufPtr != '\0'; bufPtr++) { if (*bufPtr == '\\') *bufPtr = '/'; } } #endif if (!haveSlash) { buf[len] = '/'; len++; buf[len] = '\0'; } if (access (buf, R_OK | W_OK) == -1) return errno; return 0; } static void getTempDir (char *buf, size_t buflen) { char cwd[PATH_MAX]; if (tryTempDir (buf, buflen, getenv("TMP")) && tryTempDir (buf, buflen, getenv("TEMP")) && tryTempDir (buf, buflen, "/tmp/") && tryTempDir (buf, buflen, getcwd (cwd, sizeof cwd))) { log_add (log_Fatal, "Fatal Error: Cannot find a suitable location " "to store temporary files."); exit (EXIT_FAILURE); } } // Sets the global var 'tempDir' static int mountTempDir(const char *name) { static uio_AutoMount *autoMount[] = { NULL }; uio_MountHandle *tempHandle; extern uio_Repository *repository; tempHandle = uio_mountDir (repository, "/tmp/", uio_FSTYPE_STDIO, NULL, NULL, name, autoMount, uio_MOUNT_TOP, NULL); if (tempHandle == NULL) { int saveErrno = errno; log_add (log_Fatal, "Fatal error: Couldn't mount temp dir '%s': " "%s", name, strerror (errno)); errno = saveErrno; return -1; } tempDir = uio_openDir (repository, "/tmp", 0); if (tempDir == NULL) { int saveErrno = errno; log_add (log_Fatal, "Fatal error: Could not open temp dir: %s", strerror (errno)); errno = saveErrno; return -1; } return 0; } #define NUM_TEMP_RETRIES 16 // Number of files to try to open before giving up. void initTempDir (void) { size_t len; DWORD num; int i; char *tempPtr; // Pointer to the location in the tempDirName string where the // path to the temp dir ends and the dir starts. tempDirName = HMalloc (PATH_MAX); getTempDir (tempDirName, PATH_MAX - 21); // reserve 8 chars for dirname, 1 for slash, and 12 for filename len = strlen(tempDirName); num = ((DWORD) time (NULL)); // num = GetTimeCounter () % 0xffffffff; tempPtr = tempDirName + len; for (i = 0; i < NUM_TEMP_RETRIES; i++) { sprintf (tempPtr, "%08x", num + i); if (createDirectory (tempDirName, 0700) == -1) continue; // Success, we've got a temp dir. tempDirName = HRealloc (tempDirName, len + 9); atexit (removeTempDir); if (mountTempDir (tempDirName) == -1) exit (EXIT_FAILURE); return; } // Failure, could not make a temporary directory. log_add (log_Fatal, "Fatal error: Cannot get a name for a temporary " "directory."); exit (EXIT_FAILURE); } void unInitTempDir (void) { uio_closeDir(tempDir); // the removing of the dir is handled via atexit } // return the path to a file in the temp dir with the specified filename. // returns a pointer to a static buffer. char * tempFilePath (const char *filename) { static char file[PATH_MAX]; if (snprintf (file, PATH_MAX, "%s/%s", tempDirName, filename) == -1) { log_add (log_Fatal, "Path to temp file too long."); exit (EXIT_FAILURE); } return file; } uqm-0.6.2/sc2/src/sc2code/libs/file/files.c0000600000175000017500000000763210543202045016730 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Contains code handling files #include #include #include #include #include #include "port.h" #include "uio.h" #include "config.h" #include "types.h" #include "filintrn.h" #include "misc.h" #include "libs/log.h" static int copyError(uio_Handle *srcHandle, uio_Handle *dstHandle, uio_DirHandle *unlinkHandle, const char *unlinkPath, uint8 *buf); bool fileExists (const char *name) { return access (name, F_OK) == 0; } bool fileExists2(uio_DirHandle *dir, const char *fileName) { uio_Stream *stream; stream = uio_fopen (dir, fileName, "rb"); if (stream == NULL) return 0; uio_fclose (stream); return 1; } /* * Copy a file with path srcName to a file with name newName. * If the destination already exists, the operation fails. * Links are followed. * Special files (fifos, char devices, block devices, etc) will be * read as long as there is data available and the destination will be * a regular file with that data. * The new file will have the same permissions as the old. * If an error occurs during copying, an attempt will be made to * remove the copy. */ int copyFile (uio_DirHandle *srcDir, const char *srcName, uio_DirHandle *dstDir, const char *newName) { uio_Handle *src, *dst; struct stat sb; #define BUFSIZE 65536 uint8 *buf, *bufPtr; ssize_t numInBuf, numWritten; src = uio_open (srcDir, srcName, O_RDONLY #ifdef WIN32 | O_BINARY #endif , 0); if (src == NULL) return -1; if (uio_fstat (src, &sb) == -1) return copyError (src, NULL, NULL, NULL, NULL); dst = uio_open (dstDir, newName, O_WRONLY | O_CREAT | O_EXCL #ifdef WIN32 | O_BINARY #endif , sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); if (dst == NULL) return copyError (src, NULL, NULL, NULL, NULL); buf = HMalloc(BUFSIZE); // This was originally a statically allocated buffer, // but as this function might be run from a thread with // a small Stack, this is better. while (1) { numInBuf = uio_read (src, buf, BUFSIZE); if (numInBuf == -1) { if (errno == EINTR) continue; return copyError (src, dst, dstDir, newName, buf); } if (numInBuf == 0) break; bufPtr = buf; do { numWritten = uio_write (dst, bufPtr, numInBuf); if (numWritten == -1) { if (errno == EINTR) continue; return copyError (src, dst, dstDir, newName, buf); } numInBuf -= numWritten; bufPtr += numWritten; } while (numInBuf > 0); } HFree (buf); uio_close (src); uio_close (dst); errno = 0; return 0; } /* * Closes srcHandle if it's not -1. * Closes dstHandle if it's not -1. * Removes unlinkpath from the unlinkHandle dir if it's not NULL. * Frees 'buf' if not NULL. * Always returns -1. * errno is what was before the call. */ static int copyError(uio_Handle *srcHandle, uio_Handle *dstHandle, uio_DirHandle *unlinkHandle, const char *unlinkPath, uint8 *buf) { int savedErrno; savedErrno = errno; log_add (log_Debug, "Error while copying: %s", strerror (errno)); if (srcHandle != NULL) uio_close (srcHandle); if (dstHandle != NULL) uio_close (dstHandle); if (unlinkPath != NULL) uio_unlink (unlinkHandle, unlinkPath); if (buf != NULL) HFree(buf); errno = savedErrno; return -1; } uqm-0.6.2/sc2/src/sc2code/libs/file/dirs.c0000644000175000017500000004052510546776500016614 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Contains code handling directories #include #include #include #include #include #include #include "port.h" #include "config.h" #include "filintrn.h" #include "compiler.h" #include "misc.h" #include "libs/log.h" #ifdef WIN32 # include # include #else # include #endif /* Try to find a suitable value for %APPDATA% if it isn't defined on * Windows. */ #define APPDATA_FALLBACK static char *expandPathAbsolute (char *dest, size_t destLen, const char *src, size_t *skipSrc, int what); static char *strrchr2(const char *start, int c, const char *end); int createDirectory(const char *dir, int mode) { return MKDIR(dir, mode); } // make all components of the path if they don't exist already // returns 0 on success, -1 on failure. // on failure, some parts may still have been created. int mkdirhier (const char *path) { char *buf; // buffer char *ptr; // end of the string in buf const char *pathstart; // start of a component of path const char *pathend; // first char past the end of a component of path size_t len; struct stat statbuf; len = strlen (path); buf = alloca (len + 2); // one extra for possibly added '/' ptr = buf; pathstart = path; #ifdef WIN32 if (isDriveLetter(pathstart[0]) && pathstart[1] == ':') { // Driveletter + semicolon on Windows. // Copy as is; don't try to create directories for it. *(ptr++) = *(pathstart++); *(ptr++) = *(pathstart++); ptr[0] = '/'; ptr[1] = '\0'; if (stat (buf, &statbuf) == -1) { log_add (log_Error, "Can't stat \"%s\": %s", buf, strerror (errno)); return -1; } } else if (pathstart[0] == '\\' && pathstart[1] == '\\') { // Windows UNC path. (\\server\share\...) // Copy the server part as is; don't try to create directories for // it, or stat it. Don't create a dir for the share either. *(ptr++) = *(pathstart++); *(ptr++) = *(pathstart++); // Copy the server part while (*pathstart != '\0' && *pathstart != '\\' && *pathstart != '/') *(ptr++) = *(pathstart++); if (*pathstart == '\0') { log_add (log_Error, "Incomplete UNC path \"%s\"", pathstart); return -1; } // Copy the path seperator. *(ptr++) = *(pathstart++); // Copy the share part while (*pathstart != '\0' && *pathstart != '\\' && *pathstart != '/') *(ptr++) = *(pathstart++); ptr[0] = '/'; ptr[1] = '\0'; if (stat (buf, &statbuf) == -1) { log_add (log_Error, "Can't stat \"%s\": %s", buf, strerror (errno)); return -1; } } #endif if (*pathstart == '/') *(ptr++) = *(pathstart++); if (*pathstart == '\0') { // path exists completely, nothing more to do return 0; } // walk through the path as long as the components exist while (1) { pathend = strchr (pathstart, '/'); if (pathend == NULL) pathend = path + len; memcpy(ptr, pathstart, pathend - pathstart); ptr += pathend - pathstart; *ptr = '\0'; if (stat (buf, &statbuf) == -1) { if (errno != ENOENT) { log_add (log_Error, "Can't stat \"%s\": %s", buf, strerror (errno)); return -1; } break; } if (*pathend == '\0') return 0; *ptr = '/'; ptr++; pathstart = pathend + 1; while (*pathstart == '/') pathstart++; // pathstart is the next non-slash character if (*pathstart == '\0') return 0; } // create all components left while (1) { if (createDirectory (buf, 0777) == -1) { log_add (log_Error, "Error: Can't create %s: %s", buf, strerror (errno)); return -1; } if (*pathend == '\0') break; *ptr = '/'; ptr++; pathstart = pathend + 1; while (*pathstart == '/') pathstart++; // pathstart is the next non-slash character if (*pathstart == '\0') break; pathend = strchr (pathstart, '/'); if (pathend == NULL) pathend = path + len; memcpy (ptr, pathstart, pathend - pathstart); ptr += pathend - pathstart; *ptr = '\0'; } return 0; } // Get the user's home dir // returns a pointer to a static buffer from either getenv() or getpwuid(). const char * getHomeDir (void) { #ifdef WIN32 return getenv ("HOME"); #else const char *home; struct passwd *pw; home = getenv ("HOME"); if (home != NULL) return home; pw = getpwuid (getuid ()); if (pw == NULL) return NULL; // NB: pw points to a static buffer. return pw->pw_dir; #endif } // Performs various types of string expansions on a path. // 'what' is an OR'd compination of the folowing flags, which // specify what type of exmansions will be performed. // EP_HOME - Expand '~' for home dirs. // EP_ABSOLUTE - Make relative paths absolute // EP_ENVVARS - Expand environment variables // EP_DOTS - Process ".." and "." // EP_SLASHES - Consider backslashes as path component separators. // They will be replaced by slashes. // EP_SINGLESEP - Replace multiple consecutive path seperators (which POSIX // considers equivalent to a single one) by a single one. // Additionally, there's EP_ALL, which indicates all of the above, // and EP_SYSTEM_ALL, which does the same as EP_ALL, with the exception // of EP_SLASHES, which will only be included if the operating system // accepts backslashes as path terminators. // Returns 0 on success. // Returns -1 on failure, setting errno. int expandPath (char *dest, size_t len, const char *src, int what) { char *destptr, *destend; char *buf, *bufptr, *bufend; const char *srcend; #define CHECKLEN(bufname, n) \ if (bufname##ptr + (n) >= bufname##end) \ { \ errno = ENAMETOOLONG; \ return -1; \ } \ else \ (void) 0 destptr = dest; destend = dest + len; if (what & EP_ENVVARS) { buf = alloca (len); bufptr = buf; bufend = buf + len; while (*src != '\0') { switch (*src) { #ifdef WIN32 case '%': { /* Environment variable substitution in Windows */ const char *end; // end of env var name in src const char *envVar; char *envName; size_t envNameLen, envVarLen; src++; end = strchr (src, '%'); if (end == NULL) { errno = EINVAL; return -1; } envNameLen = end - src; envName = HMalloc (envNameLen + 1); memcpy (envName, src, envNameLen + 1); envName[envNameLen] = '\0'; envVar = getenv (envName); HFree (envName); if (envVar == NULL) { #ifdef APPDATA_FALLBACK if (strncmp (src, "APPDATA", envNameLen) != 0) { // Substitute an empty string src = end + 1; break; } // fallback for when the APPDATA env var is not set // Using SHGetFolderPath or SHGetSpecialFolderPath // is problematic (not everywhere available). log_add (log_Warning, "Warning: %%APPDATA%% is not set. " "Falling back to \"%%USERPROFILE%%\\Application " "Data\""); envVar = getenv ("USERPROFILE"); if (envVar != NULL) { #define APPDATA_STRING "\\Application Data" envVarLen = strlen (envVar); CHECKLEN (buf, envVarLen + sizeof (APPDATA_STRING) - 1); strcpy (bufptr, envVar); bufptr += envVarLen; strcpy (bufptr, APPDATA_STRING); bufptr += sizeof (APPDATA_STRING) - 1; src = end + 1; break; } // fallback to "./userdata" #define APPDATA_FALLBACK_STRING ".\\userdata" log_add (log_Warning, "Warning: %%USERPROFILE%% is not set. " "Falling back to \"%s\" for %%APPDATA%%", APPDATA_FALLBACK_STRING); CHECKLEN (buf, sizeof (APPDATA_FALLBACK_STRING) - 1); strcpy (bufptr, APPDATA_FALLBACK_STRING); bufptr += sizeof (APPDATA_FALLBACK_STRING) - 1; src = end + 1; break; #else /* !defined (APPDATA_FALLBACK) */ // Substitute an empty string src = end + 1; break; #endif /* APPDATA_FALLBACK */ } envVarLen = strlen (envVar); CHECKLEN (buf, envVarLen); strcpy (bufptr, envVar); bufptr += envVarLen; src = end + 1; break; } #endif #ifndef WIN32 case '$': { const char *end; char *envName; size_t envNameLen; const char *envVar; size_t envVarLen; src++; if (*src == '{') { src++; end = strchr(src, '}'); if (end == NULL) { errno = EINVAL; return -1; } envNameLen = end - src; end++; // Skip the '}' } else { end = src; while ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_') end++; envNameLen = end - src; } envName = HMalloc (envNameLen + 1); memcpy (envName, src, envNameLen + 1); envName[envNameLen] = '\0'; envVar = getenv (envName); HFree (envName); if (envVar != NULL) { envVarLen = strlen (envVar); CHECKLEN (buf, envVarLen); memcpy (bufptr, envVar, envVarLen); bufptr += envVarLen; } src = end; break; } #endif default: CHECKLEN(buf, 1); *(bufptr++) = *(src++); break; } // switch } // while *bufptr = '\0'; src = buf; srcend = bufptr; } // if (what & EP_ENVVARS) else srcend = src + strlen (src); if (what & EP_HOME) { if (src[0] == '~') { const char *home; size_t homelen; if (src[1] != '/') { errno = EINVAL; return -1; } home = getHomeDir (); if (home == NULL) { errno = ENOENT; return -1; } homelen = strlen (home); if (what & EP_ABSOLUTE) { size_t skip; destptr = expandPathAbsolute (dest, destend - dest, home, &skip, what); if (destptr == NULL) { // errno is set return -1; } home += skip; what &= ~EP_ABSOLUTE; // The part after the '~' should not be seen // as absolute. } CHECKLEN (dest, homelen); memcpy (destptr, home, homelen); destptr += homelen; src++; /* skip the ~ */ } } if (what & EP_ABSOLUTE) { size_t skip; destptr = expandPathAbsolute (destptr, destend - destptr, src, &skip, what); if (destptr == NULL) { // errno is set return -1; } src += skip; } CHECKLEN (dest, srcend - src); memcpy (destptr, src, srcend - src + 1); // The +1 is for the '\0'. It is already taken into account by // CHECKLEN. if (what & EP_SLASHES) { /* Replacing backslashes in path by slashes. */ destptr = dest; #ifdef WIN32 { // A Windows UNC path should always start with two backslashes // and have a backslash in between the server and share part. size_t skip = skipUNCServerShare (destptr); if (skip != 0) { char *slash = (char *) memchr (destptr + 2, '/', skip - 2); if (slash) *slash = '\\'; destptr += skip; } } #endif while (*destptr != '\0') { if (*destptr == '\\') *destptr = '/'; destptr++; } } if (what & EP_DOTS) { // At this point backslashes are already replaced by slashes if they // are specified to be path seperators. // Note that the path can only get smaller, so no size checks // need to be done. char *pathStart; // Start of the first path component, after any // leading slashes or drive letters. char *startPart; char *endPart; pathStart = dest; #ifdef WIN32 if (isDriveLetter(pathStart[0]) && (pathStart[1] == ':')) { pathStart += 2; } else { // Test for a UNC path. pathStart += skipUNCServerShare(pathStart); } #endif if (pathStart[0] == '/') pathStart++; startPart = pathStart; destptr = pathStart; for (;;) { endPart = strchr(startPart, '/'); if (endPart == NULL) endPart = startPart + strlen(startPart); if (endPart - startPart == 1 && startPart[0] == '.') { // Found "." as path component. Ignore this component. } else if (endPart - startPart == 2 && startPart[0] == '.' && startPart[1] == '.') { // Found ".." as path component. Remove the previous // component, and ignore this one. char *lastSlash; lastSlash = strrchr2(pathStart, '/', destptr - 1); if (lastSlash == NULL) { if (destptr == pathStart) { // We ran out of path components to back out of. errno = EINVAL; return -1; } destptr = pathStart; } else { destptr = lastSlash; if (*endPart == '/') destptr++; } } else { // A normal path component; copy it. // Using memmove as source and destination may overlap. memmove(destptr, startPart, endPart - startPart); destptr += (endPart - startPart); if (*endPart == '/') { *destptr = '/'; destptr++; } } if (*endPart == '\0') break; startPart = endPart + 1; } *destptr = '\0'; } if (what & EP_SINGLESEP) { char *srcptr; srcptr = dest; destptr = dest; while (*srcptr != '\0') { char ch = *srcptr; *(destptr++) = *(srcptr++); if (ch == '/') { while (*srcptr == '/') srcptr++; } } *destptr = '\0'; } return 0; } #ifdef WIN32 // letter is 0 based: 0 = A, 1 = B, ... bool driveLetterExists(int letter) { unsigned long drives; drives = _getdrives (); return ((drives >> letter) & 1) != 0; } #endif // helper for expandPath, expanding an absolute path // returns a pointer to the end of the filled in part of dest. static char * expandPathAbsolute (char *dest, size_t destLen, const char *src, size_t *skipSrc, int what) { const char *orgSrc; if (src[0] == '/' || ((what & EP_SLASHES) && src[0] == '\\')) { // Path is already absolute; nothing to do *skipSrc = 0; return dest; } orgSrc = src; #ifdef WIN32 if (isDriveLetter(src[0]) && (src[1] == ':')) { int letter; if (src[2] == '/' || src[2] == '\\') { // Path is already absolute (of the form "d:/"); nothing to do *skipSrc = 0; return dest; } // Path is of the form "d:path", without a (back)slash after the // semicolon. letter = tolower(src[0]) - 'a'; // _getdcwd() should only be called on drives that exist. // This is weird though, because it means a race condition // in between the existance check and the call to _getdcwd() // cannot be avoided, unless a drive still exists for Windows // when the physical drive is removed. if (!driveLetterExists(letter)) { errno = ENOENT; return NULL; } // Get the working directory for a specific drive. if (_getdcwd (letter + 1, dest, destLen) == NULL) { // errno is set return NULL; } src += 2; } else #endif { // Relative dir if (getcwd (dest, destLen) == NULL) { // errno is set return NULL; } } { size_t tempLen; tempLen = strlen (dest); if (tempLen == 0) { // getcwd() or _getdcwd() returned a 0-length string. errno = ENOENT; return NULL; } dest += tempLen; destLen -= tempLen; } if (dest[-1] != '/' #ifdef WIN32 && dest[-1] != '\\' #endif ) { // Need to add a slash. // There's always space, as we overwrite the '\0' that getcwd() // always returns. dest[0] = '/'; dest++; destLen--; } *skipSrc = (size_t) (src - orgSrc); return dest; } // As strrchr, but starts searching from the indicated end of the string. static char * strrchr2(const char *start, int c, const char *end) { for (;;) { end--; if (end < start) return (char *) NULL; if (*end == c) return (char *) end; } } #ifdef WIN32 // returns 0 if the path is not a valid UNC path. // Does not skip trailing slashes. size_t skipUNCServerShare(const char *inPath) { const char *path = inPath; // Skip the initial two backslashes. if (path[0] != '\\' || path[1] != '\\') return (size_t) 0; path += 2; // Skip the server part. while (*path != '\\' && *path != '/') { if (*path == '\0') return (size_t) 0; path++; } // Skip the seperator. path++; // Skip the share part. while (*path != '\0' && *path != '\\' && *path != '/') path++; return (size_t) (path - inPath); } #endif uqm-0.6.2/sc2/src/sc2code/libs/file/filintrn.h0000600000175000017500000000153110543202046017451 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Contains code handling temporary files and dirs #ifndef _FILEINTRN_H #include "../file.h" #endif /* _FILEINTRN_H */ uqm-0.6.2/sc2/src/sc2code/libs/file/Makeinfo0000600000175000017500000000004310543202045017123 0ustar joeyjoeyuqm_CFILES="dirs.c files.c temp.c" uqm-0.6.2/sc2/src/sc2code/libs/callback.h0000600000175000017500000000004010543202055016433 0ustar joeyjoey#include "callback/callback.h" uqm-0.6.2/sc2/src/sc2code/libs/timelib.h0000600000175000017500000000270710543202055016340 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _TIMLIB_H #define _TIMLIB_H #define TIMELIB SDL #include "libs/compiler.h" /* ONE_SECOND is the LCM of all the fractions of a second the game uses. * Battle is 24 FPS, Landers are 35 FPS, most UI-level things are 15 FPS, * The Interplanetary flight is 30 FPS, Comm ambient animation is 40 FPS, * (also Comm Oscilloscope is 32 FPS, but it does not require a stable * timer and currently runs within the Comm ambient anim paradigm anyway) * Thus, the minimum value for ONE_SECOND is 840. */ #if TIMELIB == SDL # define ONE_SECOND 840 #endif typedef DWORD TimeCount; typedef DWORD TimePeriod; extern void InitTimeSystem (void); extern void UnInitTimeSystem (void); extern TimeCount GetTimeCounter (void); #endif /* _TIMLIB_H */ uqm-0.6.2/sc2/src/sc2code/libs/memory/0000755000175000017500000000000010552600274016061 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/memory/w_memlib.c0000600000175000017500000003144010543202044020003 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include //#include "3d.h" //#include "tool.h" //#include "utils.h" //#include "pcwin.h" #include "compiler.h" #include "libs/threadlib.h" #include "libs/memlib.h" #include "libs/log.h" #include "libs/misc.h" #define GetToolFrame() 1 //#define MEM_DEBUG #ifdef MEM_DEBUG #include #endif #define LEAK_DEBUG #ifdef LEAK_DEBUG BOOLEAN leak_debug; int leak_idx = -1; int leak_size = -1; #endif static Mutex _MemoryLock; //#define MAX_EXTENTS 100000 #define MAX_EXTENTS (MEM_HANDLE) 32766 // Changed to 32766 to get rid of warnings that an expression // 'h <= MAX_EXTENTS' is always true due to limited range of // MEM_HANDLE. /* Keep track of memory allocations. */ typedef struct _szMemoryNode { void *memory; struct _szMemoryNode *next; MEM_HANDLE handle; MEM_SIZE size; int refcount; } szMemoryNode; static szMemoryNode extents[MAX_EXTENTS]; static szMemoryNode *freeListHead = NULL; #if 0 /*****************************************************************************/ /*FUNCTION ** ** SYNOPSIS ** ok = MessageWithRetry(format, parms) ** ** DESCRIPTION ** Presents a windows message box to the user and echoes the ** message with printf(). The users gets to choose OK or CANCEL. ** Returns TRUE if the user says OK. ** ** INPUT ** As for printf(). ** ** OUTPUT ** int ok = TRUE for OK, FALSE for CANCEL. ** ** HISTORY ** 6-Nov-96:AKL Creation. ** ** ASSUMPTIONS **END*/ static int MessageWithRetry(char *fmt, ...) { va_list ap; char buffer[256]; #if 0 int ret; #endif va_start(ap, fmt); vsprintf(buffer, fmt, ap); va_end(ap); log_add (log_User, "%s", buffer); // fflush(stderr); #if 0 if (GetToolFrame ()) { ShowWindow(GetToolFrame (),SW_HIDE); } ret = MessageBox(NULL, buffer, "Message From Programmer Dude", MB_OKCANCEL); /* Return value: 0 => not enough memory for message. Abort game. IDCANCEL => user selected CANCEL. IDOK => user selected OK. */ if (GetToolFrame ()) { ShowWindow(GetToolFrame (),SW_NORMAL); } if ( ret == IDOK ) return TRUE; else #endif return FALSE; } #endif /*****************************************************************************/ /*FUNCTION ** ** SYNOPSIS ** CheckMemory() ** ** DESCRIPTION ** Checks integrity of memory allocation: diagnostic only. ** Either aborts or spits messages to stdout if there's a ** problem. ** ** INPUT ** ** OUTPUT ** ** HISTORY ** 04-Sept-96:AKL Creation. ** ** ASSUMPTIONS ** **END*/ #ifdef MEM_DEBUG void CheckMemory(void) { // Send all reports to STDOUT _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); _CrtCheckMemory(); fflush(stdout); } #endif /*****************************************************************************/ /*FUNCTION ** ** SYNOPSIS ** mem = MallocWithRetry(coreSize, diagnostic) ** ** DESCRIPTION ** Mallocs the required memory. If the malloc fails, the user is prompted ** to shutdown other applications and retry, or kill the game. ** If the game is killed, the diagnostic string is printed. ** ** INPUT ** int coreSize = How much memory to malloc (in bytes). ** char *diagnostic = String identifying the caller. ** ** OUTPUT ** void *mem = Ptr to memory, or NULL if user wants to kill us. ** ** HISTORY ** 06-Nov-96:AKL Creation. ** ** ASSUMPTIONS ** **END*/ void * MallocWithRetry(int bytes, char *diagStr) { while (1) { void *ptr; ptr = malloc (bytes); if (ptr) return (ptr); log_add (log_Fatal, "Malloc failed for %s. #Bytes %d.", diagStr, bytes); fflush (stderr); explode (); #if 0 /* The user gets a chance to close other applications and try again. */ if (!MessageWithRetry ("I'm out of memory! " "Please close other applications and click OK to try again")) { if (MessageWithRetry ("Really OK to stop tfbtool?")) { /* User says "die". */ log_add (log_Error, "Killed by the user (%s).", diagStr); log_showBox (false, false); exit (EXIT_SUCCESS); } } #endif } } MEM_HANDLE mem_allocate (MEM_SIZE coreSize, MEM_FLAGS flags, MEM_PRIORITY priority, MEM_USAGE usage) { szMemoryNode *node; LockMutex (_MemoryLock); #ifdef MEM_DEBUG CheckMemory(); #endif if ((node = freeListHead) == NULL) log_add (log_Error, "mem_allocate: out of extents."); else if ((node->memory = MallocWithRetry (coreSize, "mem_allocate:")) == 0 && coreSize) log_add (log_Error, "mem_allocate: couldn't allocate %ld bytes.", coreSize); else { freeListHead = node->next; node->size = coreSize; node->handle = node - extents + 1; node->refcount = 0; if (flags & MEM_ZEROINIT) memset (node->memory, 0, node->size); #ifdef LEAK_DEBUG if (leak_debug) { log_add (log_Debug, "alloc %d: %p, %lu", (int) node->handle, (void *) node->memory, node->size); // Preferred form: //log_add (log_Debug, "alloc %d: %#8" PRIxPTR ", %lu", // (int) node->handle, (intptr_t) node->memory, node->size); } if (node->handle == leak_idx && node->size == leak_size) node = node; if (node->size == leak_size) node = node; #endif /* LEAK_DEBUG */ UnlockMutex (_MemoryLock); return (node->handle); } UnlockMutex (_MemoryLock); (void) priority; /* Satisfying compiler (unused parameter) */ (void) usage; /* Satisfying compiler (unused parameter) */ return (0); } /*****************************************************************************/ /*FUNCTION ** ** SYNOPSIS ** size = mem_get_size(h) ** ** DESCRIPTION ** Returns the number of bytes in the given memory allocation. ** ** INPUT ** int h = Handle to memory allocation. ** ** OUTPUT ** int size = Number of bytes in allocation or zero on error. ** ** HISTORY ** 09-Jul-96:AKL Creation. Original version in LIBS\MEMORY\DATAINFO.C. ** ** ASSUMPTIONS ** **END*/ MEM_SIZE mem_get_size (MEM_HANDLE h) { LockMutex (_MemoryLock); if (h > 0 && h <= MAX_EXTENTS && extents[h - 1].handle == h) { UnlockMutex (_MemoryLock); return ((int)extents[h - 1].size); } UnlockMutex (_MemoryLock); return (0); } /*****************************************************************************/ /*FUNCTION ** ** SYNOPSIS ** done = mem_init(coreSize, pma, diskName) ** ** DESCRIPTION ** Initialize data that tracks allocation extents. ** ** INPUT ** int coreSize = IGNORED! ** int * pma = IGNORED! ** PSTR diskName = IGNORED! ** ** OUTPUT ** int done = TRUE. ** ** HISTORY ** 09-Jul-96:AKL Creation. Original version in LIBS\MEMORY\INIT.C. ** ** ASSUMPTIONS ** **END*/ MEM_BOOL mem_init (void) { int i; _MemoryLock = CreateMutex ("memory lock", SYNC_CLASS_RESOURCE); LockMutex (_MemoryLock); freeListHead = &extents[0]; for (i=0; i= MAX_EXTENTS) log_add (log_Debug, "LEAK: attempt to release invalid extent %d", h); else if (extents[h].handle == -1) log_add (log_Debug, "LEAK: attempt to release unallocated extent %d",h); else if (extents[h].refcount == 0) { #ifdef LEAK_DEBUG if (leak_debug) { log_add (log_Debug, "free %d: %p", extents[h].handle, (void *) extents[h].memory); // Preferred form: //log_add (log_Debug, "free %d: %#8" PRIxPTR, // extents[h].handle, (intptr_t) extents[h].memory); } #endif if (extents[h].memory) { free (extents[h].memory); extents[h].memory = 0; } extents[h].handle = -1; extents[h].next = freeListHead; freeListHead = &extents[h]; UnlockMutex (_MemoryLock); return TRUE; } UnlockMutex (_MemoryLock); return FALSE; } /*****************************************************************************/ /*FUNCTION ** ** SYNOPSIS ** memp = mem_simple_access(h) ** ** DESCRIPTION ** Obtains access to the given memory allocation. For now, we simply ** return the handle itself, because it is the actual address! ** ** INPUT ** int h = Handle to memory to be accessed. ** ** OUTPUT ** void * memp = Ptr to memory. ** ** HISTORY ** 09-Jul-96:AKL Creation. Original version in LIBS\MEMORY\SIMPLE.C. ** ** ASSUMPTIONS ** **END*/ void * mem_simple_access(MEM_HANDLE h) { LockMutex (_MemoryLock); if (h > 0 && h <= MAX_EXTENTS && extents[h - 1].handle == h) { ++extents[h - 1].refcount; UnlockMutex (_MemoryLock); return (extents[h - 1].memory); } UnlockMutex (_MemoryLock); return (0); } /*****************************************************************************/ /*FUNCTION ** ** SYNOPSIS ** done = mem_simple_unaccess(h) ** ** DESCRIPTION ** Release access to the given memory allocation. For now, we simply ** do nothing! ** ** INPUT ** int h = Handle to memory to be unaccessed. ** ** OUTPUT ** int done = TRUE. ** ** HISTORY ** 09-Jul-96:AKL Creation. Original version in LIBS\MEMORY\SIMPLE.C. ** ** ASSUMPTIONS ** **END*/ MEM_BOOL mem_simple_unaccess(MEM_HANDLE h) { LockMutex (_MemoryLock); if (h > 0 && h <= MAX_EXTENTS && extents[h - 1].handle == h) { if (extents[h - 1].refcount) --extents[h - 1].refcount; UnlockMutex (_MemoryLock); return (1); } UnlockMutex (_MemoryLock); return (0); } static void * _alloc_mem (int size) { void *p; int h; h = mem_allocate (sizeof (MEM_HEADER) + size, 0, 0, 0); p = (void *)mem_simple_access (h); if (p) { ((MEM_HEADER *) p)->handle = h; p = (char *)p + sizeof (MEM_HEADER); } return (p); } void * HMalloc (int size) { void *p; if (size == 0) return (0); if ((p = _alloc_mem(size)) == NULL) { log_add (log_Fatal, "Fatal Error: HMalloc(): out of memory."); fflush (stderr); explode (); } return (p); } void HFree (void *p) { if (p) { MEM_HEADER *hdr; MEM_HANDLE h; hdr = GET_MEM_HEADER(p); h = hdr->handle; mem_simple_unaccess (h); mem_release (h); } } void * HCalloc (int size) { void *p; p = HMalloc (size); if (p) memset (p, 0, size); return (p); } // BUG: HRealloc() is does not behave like realloc(): // From the C standard: "If memory for the new object cannot be allocated, // the old object is not deallocated and its value is unchanged." void * HRealloc (void *p, int size) { void *np; int osize; if ((np = _alloc_mem (size)) && p) { MEM_HEADER *hdr; MEM_HANDLE h; hdr = GET_MEM_HEADER (p); h = hdr->handle; osize = mem_get_size (h) - sizeof (MEM_HEADER); if (size > osize) size = osize; memcpy (np, p, size); HFree (p); } return (np); } uqm-0.6.2/sc2/src/sc2code/libs/memory/Makeinfo0000600000175000017500000000003010543202044017507 0ustar joeyjoeyuqm_CFILES="w_memlib.c" uqm-0.6.2/sc2/src/sc2code/libs/callback/0000755000175000017500000000000010552600274016305 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/callback/callback.h0000600000175000017500000000243610543202047020203 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CALLBACK_H #define _CALLBACK_H #include "types.h" #ifdef CALLBACK_INTERNAL typedef CallbackLink *CallbackID; #else typedef void *CallbackID; // Uniquely identifies a queued callback. #endif #define CallbackID_invalid ((CallbackID ) NULL) typedef void *CallbackArg; typedef void (*CallbackFunction)(CallbackArg arg); void Callback_init(void); CallbackID Callback_add(CallbackFunction callback, CallbackArg arg); bool Callback_remove(CallbackID id); void Callback_process(void); #endif /* _CALLBACK_H */ uqm-0.6.2/sc2/src/sc2code/libs/callback/callback.c0000600000175000017500000001035510543202047020175 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "port.h" #include "types.h" #include #include #include typedef struct CallbackLink CallbackLink; #define CALLBACK_INTERNAL #include "callback.h" struct CallbackLink { CallbackLink *next; CallbackFunction callback; CallbackArg arg; }; static CallbackLink *callbacks; static CallbackLink **callbacksEnd; static CallbackLink *const *callbacksProcessEnd; static inline void CallbackList_lock(void) { // TODO // Necessary for reentrant operation } static inline void CallbackList_unlock(void) { // TODO // Necessary for reentrant operation } #if 0 static inline bool CallbackList_isLocked(void) { // TODO } #endif void Callback_init(void) { callbacks = NULL; callbacksEnd = &callbacks; callbacksProcessEnd = &callbacks; } // Callbacks are guaranteed to be called in the order that they are queued. CallbackID Callback_add(CallbackFunction callback, CallbackArg arg) { CallbackLink *link = malloc(sizeof (CallbackLink)); link->callback = callback; link->arg = arg; link->next = NULL; CallbackList_lock(); *callbacksEnd = link; callbacksEnd = &link->next; CallbackList_unlock(); return (CallbackID) link; } static void CallbackLink_delete(CallbackLink *link) { free(link); } // Pre: CallbackList is locked. static CallbackLink ** CallbackLink_find(CallbackLink *link) { CallbackLink **ptr; //assert(CallbackList_isLocked()); for (ptr = &callbacks; *ptr != NULL; ptr = &(*ptr)->next) { if (*ptr == link) return ptr; } return NULL; } bool Callback_remove(CallbackID id) { CallbackLink *link = (CallbackLink *) id; CallbackLink **linkPtr; CallbackList_lock(); linkPtr = CallbackLink_find(link); if (linkPtr == NULL) { CallbackList_unlock(); return false; } if (callbacksEnd == &(*linkPtr)->next) callbacksEnd = linkPtr; if (callbacksProcessEnd == &(*linkPtr)->next) callbacksProcessEnd = linkPtr; *linkPtr = (*linkPtr)->next; CallbackList_unlock(); CallbackLink_delete(link); return true; } static inline void CallbackLink_doCallback(CallbackLink *link) { (link->callback)(link->arg); } // Call all queued callbacks currently in the queue. Callbacks queued // from inside the called functions will not be processed until the next // call of Callback_process(). // It is allowed to remove callbacks from inside the called functions. // NB: Callback_process() must never be called from more than one thread // at the same time. It's the only sensible way to ensure that the // callbacks are called in the order in which they were queued. // It is however allowed to call Callback_process() from inside the // callback function called by Callback_process() itself. void Callback_process(void) { CallbackLink *link; // We set 'callbacksProcessEnd' to callbacksEnd. Callbacks added // from inside a callback function will be placed after // callbacksProcessEnd, and will hence not be processed this // call of Callback_process(). CallbackList_lock(); callbacksProcessEnd = callbacksEnd; CallbackList_unlock(); for (;;) { CallbackList_lock(); if (callbacksProcessEnd == &callbacks) { CallbackList_unlock(); break; } assert(callbacks != NULL); // If callbacks == NULL, then callbacksProcessEnd == &callbacks link = callbacks; callbacks = link->next; if (callbacksEnd == &link->next) callbacksEnd = &callbacks; if (callbacksProcessEnd == &link->next) callbacksProcessEnd = &callbacks; CallbackList_unlock(); CallbackLink_doCallback(link); CallbackLink_delete(link); } } uqm-0.6.2/sc2/src/sc2code/libs/callback/alarm.c0000600000175000017500000000534710543202047017542 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "alarm.h" #include "libs/heap.h" #include #include Heap *alarmHeap; static inline Alarm * Alarm_alloc(void) { return malloc(sizeof (Alarm)); } static inline void Alarm_free(Alarm *alarm) { free(alarm); } static inline int AlarmTime_compare(const AlarmTime t1, const AlarmTime t2) { if (t1 < t2) return -1; if (t2 > t2) return 1; return 0; } static int Alarm_compare(const Alarm *a1, const Alarm *a2) { return AlarmTime_compare(a1->time, a2->time); } void Alarm_init(void) { assert(alarmHeap == NULL); alarmHeap = Heap_new((HeapValue_Comparator) Alarm_compare, 4, 4, 0.8); } void Alarm_uninit(void) { assert(alarmHeap != NULL); while (Heap_hasMore(alarmHeap)) { Alarm *alarm = (Alarm *) Heap_pop(alarmHeap); Alarm_free(alarm); } Heap_delete(alarmHeap); alarmHeap = NULL; } static inline AlarmTime AlarmTime_nowMS(void) { return SDL_GetTicks(); } Alarm * Alarm_addRelativeMs(Uint32 ms, AlarmCallback callback, AlarmCallbackArg arg) { Alarm *alarm; assert(alarmHeap != NULL); alarm = Alarm_alloc(); alarm->time = AlarmTime_nowMS() + ms; alarm->callback = callback; alarm->arg = arg; Heap_add(alarmHeap, (HeapValue *) alarm); return alarm; } void Alarm_remove(Alarm *alarm) { assert(alarmHeap != NULL); Heap_remove(alarmHeap, (HeapValue *) alarm); Alarm_free(alarm); } // It is safe to call this function again from inside a callback function // that it called. It should not be called from multiple threads at once. void Alarm_process(void) { AlarmTime now; assert(alarmHeap != NULL); now = AlarmTime_nowMS(); while (Heap_hasMore(alarmHeap)) { Alarm *alarm = (Alarm *) Heap_first(alarmHeap); if (now < alarm->time) break; Heap_pop(alarmHeap); alarm->callback(alarm->arg); Alarm_free(alarm); } } Uint32 Alarm_timeBeforeNextMs(void) { Alarm *alarm; if (!Heap_hasMore(alarmHeap)) return UINT32_MAX; alarm = (Alarm *) Heap_first(alarmHeap); return alarmTimeToMsUint32(alarm->time); } uqm-0.6.2/sc2/src/sc2code/libs/callback/alarm.h0000600000175000017500000000275010543202047017542 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _ALARM_H #define _ALARM_H #include "port.h" #include "types.h" #include SDL_INCLUDE(SDL.h) typedef Uint32 AlarmTime; static inline Uint32 alarmTimeToMsUint32(AlarmTime time) { return (Uint32) time; } typedef struct Alarm Alarm; typedef void *AlarmCallbackArg; typedef void (*AlarmCallback)(AlarmCallbackArg *arg); struct Alarm { size_t index; // For the HeapValue 'base struct'. AlarmTime time; AlarmCallback callback; AlarmCallbackArg arg; }; void Alarm_init(void); void Alarm_uninit(void); Alarm *Alarm_addRelativeMs(Uint32 ms, AlarmCallback callback, AlarmCallbackArg arg); void Alarm_remove(Alarm *alarm); void Alarm_process(void); Uint32 Alarm_timeBeforeNextMs(void); #endif /* _ALARM_H */ uqm-0.6.2/sc2/src/sc2code/libs/callback/Makeinfo0000600000175000017500000000004110543202047017740 0ustar joeyjoeyuqm_CFILES="alarm.c callback.c" uqm-0.6.2/sc2/src/sc2code/libs/sound/0000755000175000017500000000000010552600275015702 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/sound/sound.c0000600000175000017500000001034610543202040017156 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sound.h" #include "../compiler.h" #include "../tasklib.h" static Task FadeTask; static SIZE TTotal; static SIZE volume_end; int musicVolume = NORMAL_VOLUME; float musicVolumeScale; float sfxVolumeScale; float speechVolumeScale; TFB_SoundSource soundSource[NUM_SOUNDSOURCES]; void StopSound (void) { int i; for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i) { StopSource (i); } } void CleanSource (int iSource) { #define MAX_STACK_BUFFERS 64 audio_IntVal processed; soundSource[iSource].positional_object = NULL; audio_GetSourcei (soundSource[iSource].handle, audio_BUFFERS_PROCESSED, &processed); if (processed != 0) { audio_Object stack_bufs[MAX_STACK_BUFFERS]; audio_Object *bufs; if (processed > MAX_STACK_BUFFERS) bufs = (audio_Object *) HMalloc ( sizeof (audio_Object) * processed); else bufs = stack_bufs; audio_SourceUnqueueBuffers (soundSource[iSource].handle, processed, bufs); if (processed > MAX_STACK_BUFFERS) HFree (bufs); } // set the source state to 'initial' audio_SourceRewind (soundSource[iSource].handle); } void StopSource (int iSource) { audio_SourceStop (soundSource[iSource].handle); CleanSource (iSource); } BOOLEAN SoundPlaying (void) { int i; for (i = 0; i < NUM_SOUNDSOURCES; ++i) { TFB_SoundSample *sample; sample = soundSource[i].sample; if (sample && sample->decoder) { BOOLEAN result; LockMutex (soundSource[i].stream_mutex); result = PlayingStream (i); UnlockMutex (soundSource[i].stream_mutex); if (result) return TRUE; } else { audio_IntVal state; audio_GetSourcei (soundSource[i].handle, audio_SOURCE_STATE, &state); if (state == audio_PLAYING) return TRUE; } } return FALSE; } // for now just spin in a sleep() loop // perhaps later change to condvar implementation void WaitForSoundEnd (COUNT Channel) { while (Channel == TFBSOUND_WAIT_ALL ? SoundPlaying () : ChannelPlaying (Channel)) { SleepThread (ONE_SECOND / 20); } } // Status: Ignored BOOLEAN InitSound (int argc, char* argv[]) { /* Quell compiler warnings */ (void)argc; (void)argv; return TRUE; } // Status: Ignored void UninitSound (void) { } void SetSFXVolume (float volume) { int i; for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i) { audio_Sourcef (soundSource[i].handle, audio_GAIN, volume); } } void SetSpeechVolume (float volume) { audio_Sourcef (soundSource[SPEECH_SOURCE].handle, audio_GAIN, volume); } static int fade_task (void *data) { SIZE TDelta, volume_beg; DWORD StartTime, CurTime; Task task = (Task) data; volume_beg = musicVolume; StartTime = CurTime = GetTimeCounter (); do { SleepThreadUntil (CurTime + ONE_SECOND / 120); CurTime = GetTimeCounter (); if ((TDelta = (SIZE) (CurTime - StartTime)) > TTotal) TDelta = TTotal; SetMusicVolume ((COUNT) (volume_beg + (SIZE) ((long) (volume_end - volume_beg) * TDelta / TTotal))); } while (TDelta < TTotal); FadeTask = 0; FinishTask (task); return 1; } DWORD FadeMusic (BYTE end_vol, SIZE TimeInterval) { DWORD TimeOut; if (FadeTask) { volume_end = musicVolume; TTotal = 1; do TaskSwitch (); while (FadeTask); TaskSwitch (); } TTotal = TimeInterval; if (TTotal <= 0) TTotal = 1; /* prevent divide by zero and negative fade */ volume_end = end_vol; if (TTotal > 1 && (FadeTask = AssignTask (fade_task, 0, "fade music"))) { TimeOut = GetTimeCounter () + TTotal + 1; } else { SetMusicVolume (end_vol); TimeOut = GetTimeCounter (); } return TimeOut; } uqm-0.6.2/sc2/src/sc2code/libs/sound/music.c0000600000175000017500000001257210543202040017151 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "file.h" #include "options.h" #include "sound.h" #include "libs/reslib.h" #include "libs/log.h" static MUSIC_REF curMusicRef; void PLRPlaySong (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority) { TFB_SoundSample **pmus; LockMusicData (MusicRef, &pmus); if (pmus) { LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); PlayStream ((*pmus), MUSIC_SOURCE, Continuous, speechVolumeScale == 0.0f, true); UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); curMusicRef = MusicRef; } (void) Priority; /* Satisfy compiler because of unused variable */ } void PLRStop (MUSIC_REF MusicRef) { if (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0) { LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); StopStream (MUSIC_SOURCE); UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); UnlockMusicData (curMusicRef); curMusicRef = 0; } } BOOLEAN PLRPlaying (MUSIC_REF MusicRef) { if (curMusicRef && (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0)) { BOOLEAN playing; LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); playing = PlayingStream (MUSIC_SOURCE); UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); return playing; } return FALSE; } void PLRPause (MUSIC_REF MusicRef) { if (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0) { LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); PauseStream (MUSIC_SOURCE); UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); } } void PLRResume (MUSIC_REF MusicRef) { if (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0) { LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); ResumeStream (MUSIC_SOURCE); UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); } } BOOLEAN DestroyMusic (MUSIC_REF MusicRef) { return (FreeMusicData (MusicRef)); } void SetMusicVolume (COUNT Volume) { float f = (Volume / (float)MAX_VOLUME) * musicVolumeScale; musicVolume = Volume; audio_Sourcef (soundSource[MUSIC_SOURCE].handle, audio_GAIN, f); } char* CheckMusicResName (char* fileName) { char otherName[256]; const char* otherExt; char* curExt; if (strlen (fileName) < 4) return fileName; strncpy (otherName, fileName, sizeof (otherName) - 1); otherName[sizeof (otherName) - 1] = '\0'; switch (optWhichMusic) { default: case OPT_3DO: otherExt = "ogg"; break; case OPT_PC: otherExt = "mod"; break; } curExt = otherName + strlen (otherName) - strlen (otherExt); if (strcmp(curExt, otherExt) != 0) { strcpy (curExt, otherExt); if (fileExists2 (contentDir, otherName)) strcpy (fileName, otherName); else log_add (log_Warning, "Requested track '%s' not found.", otherName); } return fileName; } MEM_HANDLE _GetMusicData (uio_Stream *fp, DWORD length) { MEM_HANDLE h; h = 0; if (_cur_resfile_name && (h = AllocMusicData (sizeof (void *)))) { TFB_SoundSample **pmus; LockMusicData (h, &pmus); if (!pmus) { UnlockMusicData (h); mem_release (h); h = 0; } else { char filename[256]; *pmus = (TFB_SoundSample *) HCalloc (sizeof (TFB_SoundSample)); strncpy (filename, _cur_resfile_name, sizeof(filename) - 1); filename[sizeof(filename) - 1] = '\0'; CheckMusicResName (filename); log_add (log_Info, "_GetMusicData(): loading %s", filename); if (((*pmus)->decoder = SoundDecoder_Load (contentDir, filename, 4096, 0, 0)) == 0) { log_add (log_Warning, "_GetMusicData(): couldn't load %s", filename); UnlockMusicData (h); mem_release (h); h = 0; } else { log_add (log_Info, " decoder: %s, rate %d format %x", SoundDecoder_GetName ((*pmus)->decoder), (*pmus)->decoder->frequency, (*pmus)->decoder->format); (*pmus)->num_buffers = 64; (*pmus)->buffer = (audio_Object *) HMalloc (sizeof (audio_Object) * (*pmus)->num_buffers); audio_GenBuffers ((*pmus)->num_buffers, (*pmus)->buffer); } } UnlockMusicData (h); } (void) fp; /* satisfy compiler (unused parameter) */ (void) length; /* satisfy compiler (unused parameter) */ return (h); } BOOLEAN _ReleaseMusicData (MEM_HANDLE handle) { TFB_SoundSample **pmus; LockMusicData (handle, &pmus); if (pmus == 0) return (FALSE); if ((*pmus)->decoder) { TFB_SoundDecoder *decoder = (*pmus)->decoder; LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); if (soundSource[MUSIC_SOURCE].sample == (*pmus)) { StopStream (MUSIC_SOURCE); } UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); (*pmus)->decoder = NULL; SoundDecoder_Free (decoder); audio_DeleteBuffers ((*pmus)->num_buffers, (*pmus)->buffer); HFree ((*pmus)->buffer); if ((*pmus)->buffer_tag) HFree ((*pmus)->buffer_tag); } HFree (*pmus); UnlockMusicData (handle); mem_release (handle); return (TRUE); } uqm-0.6.2/sc2/src/sc2code/libs/sound/trackint.h0000600000175000017500000000271610543202040017654 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TRACKINT_H #define TRACKINT_H typedef struct tfb_soundchain { TFB_SoundDecoder *decoder; // points at the decoder to read from float start_time; int tag_me; uint32 track_num; void *text; TFB_TrackCB callback; struct tfb_soundchain *next; } TFB_SoundChain; typedef struct tfb_soundchaindata { TFB_SoundChain *read_chain_ptr; // points to chain read poistion TFB_SoundChain *play_chain_ptr; // points to chain playing position } TFB_SoundChainData; extern TFB_SoundChain *first_chain; TFB_SoundChain *create_soundchain (TFB_SoundDecoder *decoder, float startTime); void destroy_soundchain (TFB_SoundChain *chain); TFB_SoundChain *get_previous_chain (TFB_SoundChain *first_chain, TFB_SoundChain *current_chain); #endif // TRACKINT_H uqm-0.6.2/sc2/src/sc2code/libs/sound/audiocore.h0000600000175000017500000001147710543202040020013 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Audio Core API (derived from OpenAL) */ #ifndef _AUDIOCORE_H #define _AUDIOCORE_H #include "config.h" #include "types.h" /* Available drivers */ enum { audio_DRIVER_MIXSDL, audio_DRIVER_NOSOUND, audio_DRIVER_OPENAL }; /* Initialization flags */ #define audio_QUALITY_HIGH (1 << 0) #define audio_QUALITY_MEDIUM (1 << 1) #define audio_QUALITY_LOW (1 << 2) /* Interface Types */ typedef intptr_t audio_Object; typedef intptr_t audio_IntVal; typedef const sint32 audio_SourceProp; typedef const sint32 audio_BufferProp; enum { /* Errors */ audio_NO_ERROR = 0, audio_INVALID_NAME, audio_INVALID_ENUM, audio_INVALID_VALUE, audio_INVALID_OPERATION, audio_OUT_OF_MEMORY, audio_DRIVER_FAILURE, /* Source properties */ audio_POSITION, audio_LOOPING, audio_BUFFER, audio_GAIN, audio_SOURCE_STATE, audio_BUFFERS_QUEUED, audio_BUFFERS_PROCESSED, /* Source state information */ audio_INITIAL, audio_STOPPED, audio_PLAYING, audio_PAUSED, /* Sound buffer properties */ audio_FREQUENCY, audio_BITS, audio_CHANNELS, audio_SIZE, audio_FORMAT_MONO16, audio_FORMAT_STEREO16, audio_FORMAT_MONO8, audio_FORMAT_STEREO8, audio_ENUM_SIZE }; extern int snddriver, soundflags; typedef struct { /* General */ void (* Uninitialize) (void); sint32 (* GetError) (void); sint32 driverID; sint32 EnumLookup[audio_ENUM_SIZE]; /* Sources */ void (* GenSources) (uint32 n, audio_Object *psrcobj); void (* DeleteSources) (uint32 n, audio_Object *psrcobj); bool (* IsSource) (audio_Object srcobj); void (* Sourcei) (audio_Object srcobj, audio_SourceProp pname, audio_IntVal value); void (* Sourcef) (audio_Object srcobj, audio_SourceProp pname, float value); void (* Sourcefv) (audio_Object srcobj, audio_SourceProp pname, float *value); void (* GetSourcei) (audio_Object srcobj, audio_SourceProp pname, audio_IntVal *value); void (* GetSourcef) (audio_Object srcobj, audio_SourceProp pname, float *value); void (* SourceRewind) (audio_Object srcobj); void (* SourcePlay) (audio_Object srcobj); void (* SourcePause) (audio_Object srcobj); void (* SourceStop) (audio_Object srcobj); void (* SourceQueueBuffers) (audio_Object srcobj, uint32 n, audio_Object* pbufobj); void (* SourceUnqueueBuffers) (audio_Object srcobj, uint32 n, audio_Object* pbufobj); /* Buffers */ void (* GenBuffers) (uint32 n, audio_Object *pbufobj); void (* DeleteBuffers) (uint32 n, audio_Object *pbufobj); bool (* IsBuffer) (audio_Object bufobj); void (* GetBufferi) (audio_Object bufobj, audio_BufferProp pname, audio_IntVal *value); void (* BufferData) (audio_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq); } audio_Driver; /* Initialization */ sint32 initAudio (sint32 driver, sint32 flags); void unInitAudio (void); /* General */ sint32 audio_GetError (void); /* Sources */ void audio_GenSources (uint32 n, audio_Object *psrcobj); void audio_DeleteSources (uint32 n, audio_Object *psrcobj); bool audio_IsSource (audio_Object srcobj); void audio_Sourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal value); void audio_Sourcef (audio_Object srcobj, audio_SourceProp pname, float value); void audio_Sourcefv (audio_Object srcobj, audio_SourceProp pname, float *value); void audio_GetSourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal *value); void audio_GetSourcef (audio_Object srcobj, audio_SourceProp pname, float *value); void audio_SourceRewind (audio_Object srcobj); void audio_SourcePlay (audio_Object srcobj); void audio_SourcePause (audio_Object srcobj); void audio_SourceStop (audio_Object srcobj); void audio_SourceQueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj); void audio_SourceUnqueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj); /* Buffers */ void audio_GenBuffers (uint32 n, audio_Object *pbufobj); void audio_DeleteBuffers (uint32 n, audio_Object *pbufobj); bool audio_IsBuffer (audio_Object bufobj); void audio_GetBufferi (audio_Object bufobj, audio_BufferProp pname, audio_IntVal *value); void audio_BufferData (audio_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq); #endif /* _AUDIOCORE_H */ uqm-0.6.2/sc2/src/sc2code/libs/sound/stream.c0000600000175000017500000002730110543202040017320 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "sound.h" #include "libs/tasklib.h" #include "libs/log.h" void PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope, bool rewind) { uint32 i, pos = 0; sint32 offset = 0; if (!sample) return; StopStream (source); if (sample->callbacks.OnStartStream && !sample->callbacks.OnStartStream (sample)) return; // callback failed if (sample->buffer_tag) memset (sample->buffer_tag, 0, sample->num_buffers * sizeof (sample->buffer_tag[0])); offset = sample->offset; if (rewind) SoundDecoder_Rewind (sample->decoder); else offset += (sint32)(SoundDecoder_GetTime (sample->decoder) * (float)ONE_SECOND); soundSource[source].sample = sample; soundSource[source].sample->decoder->looping = looping; audio_Sourcei (soundSource[source].handle, audio_LOOPING, false); if (scope) { soundSource[source].sbuffer = HMalloc (PAD_SCOPE_BYTES); } for (i = 0; i < sample->num_buffers; ++i) { uint32 decoded_bytes; decoded_bytes = SoundDecoder_Decode (sample->decoder); #if 0 log_add (log_Debug, "PlayStream(): source:%d filename:%s start:%d position:%d bytes:%d\n", source, sample->decoder->filename, sample->decoder->start_sample, sample->decoder->pos, decoded_bytes); #endif if (decoded_bytes == 0) break; audio_BufferData (sample->buffer[i], sample->decoder->format, sample->decoder->buffer, decoded_bytes, sample->decoder->frequency); audio_SourceQueueBuffers (soundSource[source].handle, 1, &sample->buffer[i]); if (sample->callbacks.OnQueueBuffer) sample->callbacks.OnQueueBuffer (sample, sample->buffer[i]); if (scope) { UBYTE *p; soundSource[source].sbuffer = HRealloc ( soundSource[source].sbuffer, pos + decoded_bytes + PAD_SCOPE_BYTES); p = (UBYTE *)soundSource[source].sbuffer; memcpy (&p[pos], sample->decoder->buffer, decoded_bytes); pos += decoded_bytes; } if (sample->decoder->error) { if (sample->decoder->error != SOUNDDECODER_EOF || !sample->callbacks.OnEndChunk || !sample->callbacks.OnEndChunk (sample, sample->buffer[i])) break; } } soundSource[source].sbuf_size = pos + PAD_SCOPE_BYTES; soundSource[source].sbuf_start = pos; soundSource[source].sbuf_lasttime = GetTimeCounter (); soundSource[source].start_time = (sint32)GetTimeCounter () - offset; soundSource[source].stream_should_be_playing = TRUE; audio_SourcePlay (soundSource[source].handle); } void StopStream (uint32 source) { soundSource[source].stream_should_be_playing = FALSE; soundSource[source].sample = NULL; if (soundSource[source].sbuffer) { void *sbuffer = soundSource[source].sbuffer; soundSource[source].sbuffer = NULL; HFree (sbuffer); } soundSource[source].sbuf_start = 0; soundSource[source].sbuf_size = 0; soundSource[source].sbuf_offset = 0; StopSource (source); } void PauseStream (uint32 source) { soundSource[source].stream_should_be_playing = FALSE; audio_SourcePause (soundSource[source].handle); } void ResumeStream (uint32 source) { soundSource[source].stream_should_be_playing = TRUE; audio_SourcePlay (soundSource[source].handle); } void SeekStream (uint32 source, uint32 pos) { TFB_SoundSample* sample = soundSource[source].sample; bool looping; bool scope; if (!sample) return; looping = sample->decoder->looping; scope = soundSource[source].sbuffer != NULL; StopSource (source); SoundDecoder_Seek (sample->decoder, pos); PlayStream (sample, source, looping, scope, false); } BOOLEAN PlayingStream (uint32 source) { return soundSource[source].stream_should_be_playing; } TFB_SoundTag* TFB_FindTaggedBuffer (TFB_SoundSample* sample, audio_Object buffer) { uint32 buf_num; for (buf_num = 0; buf_num < sample->num_buffers && (!sample->buffer_tag[buf_num].in_use || sample->buffer_tag[buf_num].buf_name != buffer ); buf_num++) ; return buf_num < sample->num_buffers ? &sample->buffer_tag[buf_num] : NULL; } void TFB_TagBuffer (TFB_SoundSample* sample, audio_Object buffer, void* data) { uint32 buf_num; for (buf_num = 0; buf_num < sample->num_buffers && sample->buffer_tag[buf_num].in_use && sample->buffer_tag[buf_num].buf_name != buffer; buf_num++) ; if (buf_num >= sample->num_buffers) return; // no empty slot sample->buffer_tag[buf_num].in_use = 1; sample->buffer_tag[buf_num].buf_name = buffer; sample->buffer_tag[buf_num].data = data; } void TFB_ClearBufferTag (TFB_SoundTag* ptag) { ptag->in_use = 0; ptag->buf_name = 0; } int StreamDecoderTaskFunc (void *data) { Task task = (Task)data; int i; audio_Object last_buffer[NUM_SOUNDSOURCES]; for (i = 0; i < NUM_SOUNDSOURCES; i++) last_buffer[i] = 0; while (!Task_ReadState (task, TASK_EXIT)) { TaskSwitch (); for (i = MUSIC_SOURCE; i < NUM_SOUNDSOURCES; ++i) { audio_IntVal processed, queued; audio_IntVal state; LockMutex (soundSource[i].stream_mutex); if (!soundSource[i].sample || !soundSource[i].sample->decoder || !soundSource[i].stream_should_be_playing || soundSource[i].sample->decoder->error == SOUNDDECODER_ERROR) { UnlockMutex (soundSource[i].stream_mutex); continue; } audio_GetSourcei (soundSource[i].handle, audio_BUFFERS_PROCESSED, &processed); audio_GetSourcei (soundSource[i].handle, audio_BUFFERS_QUEUED, &queued); if (processed == 0) { audio_GetSourcei (soundSource[i].handle, audio_SOURCE_STATE, &state); if (state != audio_PLAYING) { if (queued == 0 && soundSource[i].sample->decoder->error == SOUNDDECODER_EOF) { log_add (log_Info, "StreamDecoderTaskFunc(): " "finished playing %s, source %d", soundSource[i].sample->decoder->filename, i); soundSource[i].stream_should_be_playing = FALSE; if (soundSource[i].sample->callbacks.OnEndStream) soundSource[i].sample->callbacks.OnEndStream ( soundSource[i].sample); } else { log_add (log_Warning, "StreamDecoderTaskFunc(): buffer " "underrun when playing %s, source %d", soundSource[i].sample->decoder->filename, i); audio_SourcePlay (soundSource[i].handle); } } } #if 0 log_add (log_Debug, "StreamDecoderTaskFunc(): source %d, processed %d queued %d", i, processed, queued); #endif while (processed) { uint32 error; audio_Object buffer; uint32 decoded_bytes; audio_GetError (); // clear error state audio_SourceUnqueueBuffers (soundSource[i].handle, 1, &buffer); error = audio_GetError(); if (error != audio_NO_ERROR) { log_add (log_Warning, "StreamDecoderTaskFunc(): OpenAL " "error after alSourceUnqueueBuffers: %x, " "file %s, source %d", error, soundSource[i].sample->decoder->filename, i); break; } if (soundSource[i].sample->callbacks.OnTaggedBuffer) { TFB_SoundTag* tag = TFB_FindTaggedBuffer ( soundSource[i].sample, buffer); if (tag) { soundSource[i].sample->callbacks.OnTaggedBuffer ( soundSource[i].sample, tag); } } { audio_IntVal buf_size; soundSource[i].sbuf_lasttime = GetTimeCounter (); audio_GetBufferi(buffer, audio_SIZE, &buf_size); soundSource[i].sbuf_offset += buf_size; if (soundSource[i].sbuf_offset > soundSource[i].sbuf_size) soundSource[i].sbuf_offset -= soundSource[i].sbuf_size; } //soundSource[i].total_decoded += soundSource[i].sample->decoder->buffer_size; if (soundSource[i].sample->decoder->error) { if (soundSource[i].sample->decoder->error == SOUNDDECODER_EOF) { if (!soundSource[i].sample->callbacks.OnEndChunk || !soundSource[i].sample->callbacks.OnEndChunk ( soundSource[i].sample, last_buffer[i])) { #if 0 log_add (log_Debug, "StreamDecoderTaskFunc(): decoder->error is eof for %s", soundSource[i].sample->decoder->filename); #endif processed--; continue; } } else { #if 0 log_add (log_Debug, "StreamDecoderTaskFunc(): decoder->error is %d for %s", soundSource[i].sample->decoder->error, soundSource[i].sample->decoder->filename); #endif processed--; continue; } } decoded_bytes = SoundDecoder_Decode ( soundSource[i].sample->decoder); if (soundSource[i].sample->decoder->error == SOUNDDECODER_ERROR) { log_add (log_Warning, "StreamDecoderTaskFunc(): " "SoundDecoder_Decode error %d, file %s, " "source %d", soundSource[i].sample->decoder->error, soundSource[i].sample->decoder->filename, i); soundSource[i].stream_should_be_playing = FALSE; processed--; continue; } if (decoded_bytes > 0) { audio_BufferData (buffer, soundSource[i].sample->decoder->format, soundSource[i].sample->decoder->buffer, decoded_bytes, soundSource[i].sample->decoder->frequency); error = audio_GetError(); if (error != audio_NO_ERROR) { log_add (log_Warning, "StreamDecoderTaskFunc(): " "TFBSound error after audio_BufferData: " "%x, file %s, source %d, decoded_bytes %d", error, soundSource[i].sample->decoder->filename, i, decoded_bytes); } else { last_buffer[i] = buffer; audio_SourceQueueBuffers (soundSource[i].handle, 1, &buffer); // do OnQueue callback if (soundSource[i].sample->callbacks.OnQueueBuffer) soundSource[i].sample->callbacks.OnQueueBuffer ( soundSource[i].sample, buffer); if (soundSource[i].sbuffer) { // copies decoded data to oscilloscope buffer uint32 j, remaining_bytes = 0; UBYTE *sbuffer = (UBYTE *) soundSource[i].sbuffer; UBYTE *decoder_buffer = (UBYTE *) soundSource[i]. sample->decoder->buffer; if (soundSource[i].sbuf_start + decoded_bytes > soundSource[i].sbuf_size) { j = soundSource[i].sbuf_size; remaining_bytes = decoded_bytes - (j - soundSource[i].sbuf_start); } else { j = soundSource[i].sbuf_start + decoded_bytes; } if (j - soundSource[i].sbuf_start >= 1) { memcpy (&sbuffer[soundSource[i].sbuf_start], decoder_buffer, j - soundSource[i].sbuf_start); } if (remaining_bytes) { memcpy (sbuffer, &decoder_buffer[ j - soundSource[i].sbuf_start], remaining_bytes); soundSource[i].sbuf_start = remaining_bytes; } else { soundSource[i].sbuf_start += decoded_bytes; } } error = audio_GetError(); if (error != audio_NO_ERROR) { log_add (log_Warning, "StreamDecoderTaskFunc(): " "TFBSound error after " "audio_SourceQueueBuffers: %x, file %s, " "source %d, decoded_bytes %d", error, soundSource[i].sample->decoder->filename, i, decoded_bytes); } } } processed--; } UnlockMutex (soundSource[i].stream_mutex); } } FinishTask (task); return 0; } uqm-0.6.2/sc2/src/sc2code/libs/sound/resinst.c0000600000175000017500000000253410543202040017515 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sndintrn.h" BOOLEAN InstallAudioResTypes (COUNT sound_type, COUNT music_type) { InstallResTypeVectors (sound_type, _GetSoundBankData, _ReleaseSoundBankData); InstallResTypeVectors (music_type, _GetMusicData, _ReleaseMusicData); return (TRUE); } SOUND_REF LoadSoundInstance (DWORD res) { MEM_HANDLE hData; hData = res_GetResource (res); if (hData) res_DetachResource (res); return ((SOUND_REF)hData); } MUSIC_REF LoadMusicInstance (DWORD res) { MEM_HANDLE hData; hData = res_GetResource (res); if (hData) res_DetachResource (res); return ((MUSIC_REF)hData); } uqm-0.6.2/sc2/src/sc2code/libs/sound/fileinst.c0000600000175000017500000000407710543202040017647 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sndintrn.h" #include "options.h" #include "reslib.h" #include SOUND_REF LoadSoundFile (PVOID pStr) { uio_Stream *fp; // FIXME: this theoretically needs a mechanism to prevent races if (_cur_resfile_name) // something else is loading resources atm return 0; fp = res_OpenResFile (contentDir, pStr, "rb"); if (fp) { MEM_HANDLE hData; _cur_resfile_name = pStr; hData = _GetSoundBankData (fp, LengthResFile (fp)); _cur_resfile_name = 0; res_CloseResFile (fp); return ((SOUND_REF)hData); } return (0); } MUSIC_REF LoadMusicFile (PVOID pStr) { uio_Stream *fp; char filename[256]; // FIXME: this theoretically needs a mechanism to prevent races if (_cur_resfile_name) // something else is loading resources atm return 0; strncpy (filename, pStr, sizeof(filename) - 1); filename[sizeof(filename) - 1] = '\0'; CheckMusicResName (filename); // Opening the res file is not technically necessary right now // since _GetMusicData() completely ignores the arguments // But just for the sake of correctness fp = res_OpenResFile (contentDir, filename, "rb"); if (fp) { MEM_HANDLE hData; _cur_resfile_name = filename; hData = _GetMusicData (fp, LengthResFile (fp)); _cur_resfile_name = 0; res_CloseResFile (fp); return ((MUSIC_REF)hData); } return (0); } uqm-0.6.2/sc2/src/sc2code/libs/sound/trackplayer.c0000600000175000017500000006747710543202040020370 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sound.h" #include "libs/sound/trackplayer.h" #include "libs/sound/trackint.h" #include "libs/log.h" #include "comm.h" #include "sis.h" #include "options.h" #include #include #include static int tct; //total number of subtitle tracks static int tcur; //currently playing subtitle track static UNICODE *cur_page = 0; //current page of subtitle track static int no_page_break = 0; static int track_pos_changed = 0; // set whenever ff, frev is enabled static TFB_SoundChain *cur_text_chain = NULL; //current link w/ subbies #define MAX_CLIPS 50 static TFB_SoundSample *sound_sample = NULL; TFB_SoundChain *first_chain = NULL; //first decoder in linked list static TFB_SoundChain *last_chain = NULL; //last decoder in linked list static TFB_SoundChain *last_ts_chain = NULL; //last element in the chain with a subtitle static Mutex track_mutex; //protects tcur and tct void recompute_track_pos (TFB_SoundSample *sample, TFB_SoundChain *first_chain, sint32 offset); bool is_sample_playing(TFB_SoundSample* samp); // stream callbacks static bool OnTrackStart (TFB_SoundSample* sample); static bool OnChunkEnd (TFB_SoundSample* sample, audio_Object buffer); static void OnTrackEnd (TFB_SoundSample* sample); static void OnTrackTag (TFB_SoundSample* sample, TFB_SoundTag* tag); static TFB_SoundCallbacks trackCBs = { OnTrackStart, OnChunkEnd, OnTrackEnd, OnTrackTag, NULL }; //JumpTrack currently aborts the current track. However, it doesn't clear the //data-structures as StopTrack does. this allows for rewind even after the //track has finished playing //Question: Should 'abort' call StopTrack? void JumpTrack (void) { TFB_SoundChainData* scd; uint32 cur_time; sint32 total_length = (sint32)((last_chain->start_time + last_chain->decoder->length) * (float)ONE_SECOND); if (!sound_sample) return; scd = (TFB_SoundChainData*) sound_sample->data; LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PauseStream (SPEECH_SOURCE); cur_time = GetTimeCounter(); soundSource[SPEECH_SOURCE].start_time = (sint32)cur_time - total_length; track_pos_changed = 1; scd->play_chain_ptr = last_chain; recompute_track_pos(sound_sample, first_chain, total_length + 1); UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PlayingTrack(); } //advance to the next track and start playing // we no longer support advancing tracks this way. Instead this should just start playing // a stream. void PlayTrack (void) { TFB_SoundChainData* scd; if (!sound_sample) return; scd = (TFB_SoundChainData*) sound_sample->data; if (scd->read_chain_ptr || sound_sample->decoder) { LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PlayStream (sound_sample, SPEECH_SOURCE, false, speechVolumeScale != 0.0f, !track_pos_changed); track_pos_changed = 0; UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } } // ResumeTrack should resume a paused track, or start a stopped track, and do nothing // for a playing track void ResumeTrack () { TFB_SoundChainData* scd; if (!sound_sample) return; scd = (TFB_SoundChainData*) sound_sample->data; if (scd->read_chain_ptr || sound_sample->decoder) { // Only try to start the track if there is something to play audio_IntVal state; BOOLEAN playing; LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); audio_GetSourcei (soundSource[SPEECH_SOURCE].handle, audio_SOURCE_STATE, &state); playing = PlayingStream (SPEECH_SOURCE); if (!track_pos_changed && !playing && state == audio_PAUSED) { /*adjust start time so the slider doesn't go crazy*/ soundSource[SPEECH_SOURCE].start_time += GetTimeCounter () - soundSource[SPEECH_SOURCE].pause_time; ResumeStream (SPEECH_SOURCE); UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } else if (! playing) { UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PlayTrack (); } else { UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } } } COUNT PlayingTrack () { // this is not a great way to detect whether the track is playing, // but as it should work during fast-forward/rewind, 'PlayingStream' can't be used // if (tct == 0) // return ((COUNT)~0); if (sound_sample && is_sample_playing (sound_sample)) { int last_track; UNICODE *last_page; LockMutex (track_mutex); last_track = tcur; last_page = cur_page; UnlockMutex (track_mutex); if (do_subtitles (last_page)) { return (tcur + 1); } else { COUNT result; LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); result = (PlayingStream (SPEECH_SOURCE) ? (COUNT)(last_track + 1) : 0); UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); return result; } } return (0); } void StopTrack () { LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); StopStream (SPEECH_SOURCE); UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); if (first_chain) { destroy_soundchain (first_chain); first_chain = NULL; last_chain = NULL; last_ts_chain = NULL; } if (sound_sample) { DestroyMutex (track_mutex); audio_DeleteBuffers (sound_sample->num_buffers, sound_sample->buffer); HFree (sound_sample->buffer); HFree (sound_sample->buffer_tag); HFree (sound_sample->data); HFree (sound_sample); sound_sample = NULL; } tct = tcur = 0; cur_page = 0; do_subtitles ((void *)~0); } bool is_sample_playing(TFB_SoundSample* sample) { TFB_SoundChainData* scd = (TFB_SoundChainData*) sample->data; return (scd->read_chain_ptr && scd->play_chain_ptr) || (!scd->read_chain_ptr && sample->decoder); } static void DoTrackTag (TFB_SoundChain *chain) { LockMutex (track_mutex); if (chain->callback) chain->callback (); tcur = chain->track_num; cur_page = (UNICODE *) chain->text; UnlockMutex (track_mutex); } static bool OnTrackStart (TFB_SoundSample* sample) { TFB_SoundChainData* scd = (TFB_SoundChainData*) sample->data; if (!scd->read_chain_ptr && !sample->decoder) return false; if (scd->read_chain_ptr) { sample->decoder = scd->read_chain_ptr->decoder; sample->offset = (sint32) (scd->read_chain_ptr->start_time * (float)ONE_SECOND); } else sample->offset = 0; scd->play_chain_ptr = scd->read_chain_ptr; if (scd->read_chain_ptr && scd->read_chain_ptr->tag_me) DoTrackTag(scd->read_chain_ptr); return true; } static bool OnChunkEnd (TFB_SoundSample* sample, audio_Object buffer) { TFB_SoundChainData* scd = (TFB_SoundChainData*) sample->data; if (!scd->read_chain_ptr || !scd->read_chain_ptr->next) return false; scd->read_chain_ptr = scd->read_chain_ptr->next; sample->decoder = scd->read_chain_ptr->decoder; SoundDecoder_Rewind (sample->decoder); log_add (log_Info, "Switching to stream %s at pos %d", sample->decoder->filename, sample->decoder->start_sample); if (sample->buffer_tag && scd->read_chain_ptr->tag_me) { TFB_TagBuffer (sample, buffer, scd->read_chain_ptr); } return true; } static void OnTrackEnd (TFB_SoundSample* sample) { TFB_SoundChainData* scd = (TFB_SoundChainData*) sample->data; sample->decoder = NULL; scd->read_chain_ptr = NULL; } static void OnTrackTag (TFB_SoundSample* sample, TFB_SoundTag* tag) { TFB_SoundChainData* scd = (TFB_SoundChainData*) sample->data; TFB_SoundChain* chain = (TFB_SoundChain*) tag->data; TFB_ClearBufferTag (tag); DoTrackTag (chain); scd->play_chain_ptr = scd->read_chain_ptr; } int GetTimeStamps(UNICODE *TimeStamps, sint32 *time_stamps) { int pos; int num = 0; while (*TimeStamps && (pos = strcspn (TimeStamps, ",\r\n"))) { UNICODE valStr[32]; uint32 val; strncpy (valStr, TimeStamps, pos); valStr[pos] = '\0'; val = strtoul (valStr, NULL, 10); if (val) { *time_stamps = (sint32)val; num++; time_stamps++; } TimeStamps += pos; TimeStamps += strspn (TimeStamps, ",\r\n"); } return (num); } #define TEXT_SPEED 80 UNICODE ** SplitSubPages (UNICODE *text, sint32 *timestamp, int *num_pages) { UNICODE **split_text = NULL; int pos = 0, ellips = 0; COUNT page = 0; while (text[pos]) { if (text[pos] == '\n' || text[pos] == '\r') { if (! split_text) split_text = (UNICODE **) HMalloc (sizeof (UNICODE *) * (page + 1)); else split_text = (UNICODE **) HRealloc (split_text, sizeof (UNICODE *) * (page + 1)); // XXX: this will only work when ASCII punctuation and spaces // are used exclusively if (!ispunct (text[pos - 1]) && !isspace (text[pos - 1])) { split_text[page] = HMalloc (sizeof (UNICODE) * (pos + ellips + 4)); if (ellips) strcpy (split_text[page], ".."); strncpy (split_text[page] + ellips, text, pos); strcpy (split_text[page] + ellips + pos, "..."); timestamp[page] = - pos * TEXT_SPEED; if (timestamp[page] > -1000) timestamp[page] = -1000; ellips = 2; text = text + pos; pos = 0; page ++; } else { split_text[page] = HMalloc (sizeof (UNICODE) * (pos + ellips + 1)); if (ellips) strcpy (split_text[page], ".."); strncpy (split_text[page] + ellips, text, pos); *(split_text[page] + ellips + pos) = 0; timestamp[page] = - pos * TEXT_SPEED; if (timestamp[page] > -1000) timestamp[page] = -1000; ellips = 0; text = text + pos; pos = 0; page ++; } while (text[pos] == '\n' || text[pos] == '\r') text++; } else pos++; } if (pos) { if (! split_text) split_text = (UNICODE **) HMalloc (sizeof (UNICODE *) * (page + 1)); else split_text = (UNICODE **) HRealloc (split_text, sizeof (UNICODE *) * (page + 1)); split_text[page] = HMalloc (sizeof (UNICODE) * (pos + ellips + 1)); if (ellips) strcpy (split_text[page], ".."); strncpy (split_text[page] + ellips, text, pos); *(split_text[page] + ellips + pos) = 0; timestamp[page] = - pos * TEXT_SPEED; if (timestamp[page] > -1000) timestamp[page] = -1000; timestamp[page] += -1000; page ++; } *num_pages = page; return (split_text); } // decodes several tracks into one and adds it to queue // track list is NULL-terminated void SpliceMultiTrack (UNICODE *TrackNames[], UNICODE *TrackText) { #define MAX_MULTI_TRACKS 20 #define MAX_MULTI_BUFFERS 100 TFB_SoundDecoder* track_decs[MAX_MULTI_TRACKS + 1]; TFB_SoundChain *begin_chain; int tracks; int slen; if (!TrackText) { log_add (log_Debug, "SpliceMultiTrack(): no track text"); return; } if (tct >= MAX_CLIPS) { log_add (log_Warning, "SpliceMultiTrack(): no more clip slots (%d)", MAX_CLIPS); return; } if (! sound_sample) { log_add (log_Warning, "SpliceMultiTrack(): Cannot be called before SpliceTrack()"); return; } log_add (log_Info, "SpliceMultiTrack(): loading..."); for (tracks = 0; *TrackNames && tracks < MAX_MULTI_TRACKS; TrackNames++, tracks++) { track_decs[tracks] = SoundDecoder_Load (contentDir, *TrackNames, 32768, 0, - 3 * TEXT_SPEED); if (track_decs[tracks]) { log_add (log_Info, " track: %s, decoder: %s, rate %d format %x", *TrackNames, SoundDecoder_GetName (track_decs[tracks]), track_decs[tracks]->frequency, track_decs[tracks]->format); SoundDecoder_DecodeAll (track_decs[tracks]); last_chain->next = create_soundchain (track_decs[tracks], sound_sample->length); last_chain = last_chain->next; if (tracks == 0) begin_chain = last_chain; sound_sample->length += track_decs[tracks]->length; } else { log_add (log_Warning, "SpliceMultiTrack(): couldn't load %s\n", *TrackNames); tracks--; } } track_decs[tracks] = 0; // term if (tracks == 0) { log_add (log_Warning, "SpliceMultiTrack(): no tracks loaded"); return; } slen = strlen (TrackText); if (tct) { int slen1 = strlen ((UNICODE *)cur_text_chain->text); cur_text_chain->text = HRealloc ( (UNICODE *)cur_text_chain->text, slen1 + slen + 1); strcpy (&((UNICODE *)cur_text_chain->text)[slen1], TrackText); } else { begin_chain->text = HMalloc (slen + 1); strcpy ((UNICODE *)begin_chain->text, TrackText); cur_text_chain = begin_chain; begin_chain->tag_me = 1; begin_chain->track_num = tct; tct++; } no_page_break = 1; } void SpliceTrack (UNICODE *TrackName, UNICODE *TrackText, UNICODE *TimeStamp, TFB_TrackCB cb) { unsigned long startTime; UNICODE **split_text = NULL; if (TrackText) { if (TrackName == 0) { if (tct) { int slen1, slen2; UNICODE *oTT; int num_pages = 0, page_counter; sint32 time_stamps[50]; if (!last_ts_chain || !last_ts_chain->text) { log_add (log_Warning, "SpliceTrack(): Tried to append" " a subtitle to a NULL string"); return; } split_text = SplitSubPages (TrackText, time_stamps, &num_pages); if (! split_text) { log_add (log_Warning, "SpliceTrack(): Failed to parse sutitles"); return; } oTT = (UNICODE *)last_ts_chain->text; slen1 = strlen (oTT); slen2 = strlen (split_text[0]); last_ts_chain->text = HRealloc (oTT, slen1 + slen2 + 1); strcpy (&((UNICODE *)last_ts_chain->text)[slen1], split_text[0]); HFree (split_text[0]); for (page_counter = 1; page_counter < num_pages; page_counter++) { if (! last_ts_chain->next) { log_add (log_Warning, "SpliceTrack(): More text pages than timestamps!"); break; } last_ts_chain = last_ts_chain->next; last_ts_chain->text = split_text[page_counter]; } } } else { int num_pages = 0, num_timestamps = 0, page_counter; sint32 time_stamps[50]; int i; for (i = 0; i < 50; i++) time_stamps[i] = -1000; split_text = SplitSubPages (TrackText, time_stamps, &num_pages); if (! split_text) { log_add (log_Warning, "SpliceTrack(): Failed to parse sutitles"); return; } if (no_page_break && tct) { int slen1, slen2; UNICODE *oTT; oTT = (UNICODE *)cur_text_chain->text; slen1 = strlen (oTT); slen2 = strlen (split_text[0]); cur_text_chain->text = HRealloc (oTT, slen1 + slen2 + 1); strcpy (&((UNICODE *)cur_text_chain->text)[slen1], split_text[0]); HFree (split_text[0]); } else tct++; log_add (log_Info, "SpliceTrack(): loading %s", TrackName); if (TimeStamp) { num_timestamps = GetTimeStamps (TimeStamp, time_stamps) + 1; if (num_timestamps < num_pages) log_add (log_Warning, "SpliceTrack(): number of timestamps" " doesn't match number of pages!"); } else num_timestamps = num_pages; startTime = 0; for (page_counter = 0; page_counter < num_timestamps; page_counter++) { if (! sound_sample) { TFB_SoundDecoder *decoder; TFB_SoundChainData* scd; track_mutex = CreateMutex("trackplayer mutex", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_AUDIO); sound_sample = (TFB_SoundSample *) HMalloc (sizeof (TFB_SoundSample)); scd = (TFB_SoundChainData *) HCalloc (sizeof (TFB_SoundChainData)); sound_sample->data = scd; sound_sample->callbacks = trackCBs; sound_sample->num_buffers = 8; sound_sample->buffer_tag = HCalloc (sizeof (TFB_SoundTag) * sound_sample->num_buffers); sound_sample->buffer = HMalloc (sizeof (audio_Object) * sound_sample->num_buffers); audio_GenBuffers (sound_sample->num_buffers, sound_sample->buffer); decoder = SoundDecoder_Load (contentDir, TrackName, 4096, startTime, time_stamps[page_counter]); scd->read_chain_ptr = create_soundchain (decoder, 0.0); sound_sample->decoder = decoder; first_chain = last_chain = scd->read_chain_ptr; sound_sample->length = 0; scd->play_chain_ptr = 0; } else { TFB_SoundDecoder *decoder; decoder = SoundDecoder_Load (contentDir, TrackName, 4096, startTime, time_stamps[page_counter]); last_chain->next = create_soundchain (decoder, sound_sample->length); last_chain = last_chain->next; } startTime += abs (time_stamps[page_counter]); #if 0 log_add (log_Debug, "page (%d of %d): %d ts: %d", page_counter, num_pages, startTime, time_stamps[page_counter]); #endif if (last_chain->decoder) { static float old_volume = 0.0f; if (last_chain->decoder->is_null) { if (speechVolumeScale != 0.0f) { /* No voice ogg available so zeroing speech volume to ensure proper operation of oscilloscope and music fading */ old_volume = speechVolumeScale; speechVolumeScale = 0.0f; log_add (log_Warning, "SpliceTrack(): no voice ogg" " available so setting speech volume to zero"); } } else if (old_volume != 0.0f && speechVolumeScale != old_volume) { /* This time voice ogg is there */ log_add (log_Warning, "SpliceTrack(): restoring speech volume"); speechVolumeScale = old_volume; old_volume = 0.0f; } sound_sample->length += last_chain->decoder->length; if (! no_page_break) { last_chain->tag_me = 1; // last_chain->tag.value = (void *)(((tct - 1) << 8) | page_counter); last_chain->track_num = tct - 1; if (page_counter < num_pages) { last_chain->text = (void *)split_text[page_counter]; last_ts_chain = last_chain; } last_chain->callback = cb; cur_text_chain = last_chain; } no_page_break = 0; } else { log_add (log_Warning, "SpliceTrack(): couldn't load %s", TrackName); audio_DeleteBuffers (sound_sample->num_buffers, sound_sample->buffer); destroy_soundchain (first_chain); first_chain = NULL; HFree (sound_sample->buffer); HFree (sound_sample); sound_sample = NULL; } } } } } void PauseTrack () { if (sound_sample && sound_sample->decoder) { LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PauseStream (SPEECH_SOURCE); soundSource[SPEECH_SOURCE].pause_time = GetTimeCounter (); UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } } void recompute_track_pos (TFB_SoundSample *sample, TFB_SoundChain *first_chain, sint32 offset) { TFB_SoundChainData* scd; TFB_SoundChain *cur_chain = first_chain; if (! sample) return; scd = (TFB_SoundChainData*) sample->data; while (cur_chain->next && (sint32)(cur_chain->next->start_time * (float)ONE_SECOND) < offset) { if (cur_chain->tag_me) DoTrackTag (cur_chain); cur_chain = cur_chain->next; } if (cur_chain->tag_me) DoTrackTag (cur_chain); if ((sint32)((cur_chain->start_time + cur_chain->decoder->length) * (float)ONE_SECOND) < offset) { scd->read_chain_ptr = NULL; sample->decoder = NULL; } else { scd->read_chain_ptr = cur_chain; SoundDecoder_Seek(scd->read_chain_ptr->decoder, (uint32)(1000 * (offset / (float)ONE_SECOND - cur_chain->start_time))); } } void FastReverse_Smooth () { if (sound_sample) { sint32 offset; uint32 cur_time; sint32 total_length = (sint32)((last_chain->start_time + last_chain->decoder->length) * (float)ONE_SECOND); LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PauseStream (SPEECH_SOURCE); cur_time = GetTimeCounter(); track_pos_changed = 1; if ((sint32)cur_time - soundSource[SPEECH_SOURCE].start_time > total_length) soundSource[SPEECH_SOURCE].start_time = (sint32)cur_time - total_length; soundSource[SPEECH_SOURCE].start_time += ACCEL_SCROLL_SPEED; if (soundSource[SPEECH_SOURCE].start_time > (sint32)cur_time) { soundSource[SPEECH_SOURCE].start_time = cur_time; offset = 0; } else offset = cur_time - soundSource[SPEECH_SOURCE].start_time; recompute_track_pos(sound_sample, first_chain, offset); UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PlayingTrack(); } } void FastReverse_Page () { if (sound_sample) { TFB_SoundChainData* scd = (TFB_SoundChainData*) sound_sample->data; TFB_SoundChain *prev_chain; LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); prev_chain = get_previous_chain (first_chain, scd->play_chain_ptr); if (prev_chain) { scd->read_chain_ptr = prev_chain; PlayStream (sound_sample, SPEECH_SOURCE, false, speechVolumeScale != 0.0f, true); } UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } } void FastForward_Smooth () { if (sound_sample) { sint32 offset; uint32 cur_time; sint32 total_length = (sint32)((last_chain->start_time + last_chain->decoder->length) * (float)ONE_SECOND); LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PauseStream (SPEECH_SOURCE); cur_time = GetTimeCounter(); soundSource[SPEECH_SOURCE].start_time -= ACCEL_SCROLL_SPEED; if ((sint32)cur_time - soundSource[SPEECH_SOURCE].start_time > total_length) soundSource[SPEECH_SOURCE].start_time = (sint32)cur_time - total_length - 1; offset = cur_time - soundSource[SPEECH_SOURCE].start_time; track_pos_changed = 1; recompute_track_pos(sound_sample, first_chain, offset); UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); PlayingTrack(); } } int FastForward_Page () { if (sound_sample) { TFB_SoundChainData* scd = (TFB_SoundChainData*) sound_sample->data; TFB_SoundChain *cur_ptr = scd->play_chain_ptr; LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); while (cur_ptr->next && !cur_ptr->next->tag_me) cur_ptr = cur_ptr->next; if (cur_ptr->next) { scd->read_chain_ptr = cur_ptr->next; PlayStream (sound_sample, SPEECH_SOURCE, false, speechVolumeScale != 0.0f, true); UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); return TRUE; } else //means there are no more pages left { UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); return FALSE; } } return TRUE; } // processes sound data to oscilloscope int GetSoundData (void *data) { if (speechVolumeScale != 0.0f) { // speech is enabled LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); if (soundSource[SPEECH_SOURCE].sample && soundSource[SPEECH_SOURCE].sample->decoder && PlayingStream (SPEECH_SOURCE) && soundSource[SPEECH_SOURCE].sbuffer && soundSource[SPEECH_SOURCE].sbuf_size > 0) { float played_time = (GetTimeCounter () - soundSource[SPEECH_SOURCE].sbuf_lasttime) / (float)ONE_SECOND; long delta = (int) (played_time * (float)soundSource[SPEECH_SOURCE]. sample->decoder->frequency * 2.0f); unsigned long pos; int i; UBYTE *scopedata = (UBYTE *) data; UBYTE *sbuffer = soundSource[SPEECH_SOURCE].sbuffer; assert (soundSource[SPEECH_SOURCE].sample->decoder->frequency == 11025); assert (soundSource[SPEECH_SOURCE].sample->decoder->format == audio_FORMAT_MONO16); if (delta < 0) { log_add (log_Debug, "GetSoundData(): something's messed" " with timing, delta %ld", delta); delta = 0; } else if (delta > (int)(soundSource[SPEECH_SOURCE].sbuf_size * 2)) { #if 0 log_add (log_Debug, "GetSoundData(): something's messed" " with timing, delta %d", delta); #endif delta = 0; } #if 0 log_add (log_Debug, "played_data %d total_decoded %d delta %d", played_data, soundSource[SPEECH_SOURCE].total_decoded, delta); #endif pos = soundSource[SPEECH_SOURCE].sbuf_offset + delta; if (pos % 2 == 1) pos++; // pos is an unsigned data type; this assertion cannot fail! // assert (pos >= 0); for (i = 0; i < RADAR_WIDTH - 2; ++i) { SDWORD s; for (;;) { if (pos >= soundSource[SPEECH_SOURCE].sbuf_size) pos = pos - soundSource[SPEECH_SOURCE].sbuf_size; else break; } s = *(SWORD*) (&sbuffer[pos]); s = (s / 1360) + (RADAR_HEIGHT >> 1); if (s < 1) s = 1; else if (s > RADAR_HEIGHT - 2) s = RADAR_HEIGHT - 2; scopedata[i] = (UBYTE) s; pos += 2; } UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); return 1; } UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); } else if (musicVolumeScale != 0.0f) { // speech is disabled but music is not so process it instead LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); if (soundSource[MUSIC_SOURCE].sample && soundSource[MUSIC_SOURCE].sample->decoder && PlayingStream (MUSIC_SOURCE) && soundSource[MUSIC_SOURCE].sbuffer && soundSource[MUSIC_SOURCE].sbuf_size > 0) { float played_time = (GetTimeCounter () - soundSource[MUSIC_SOURCE].sbuf_lasttime) / (float)ONE_SECOND; int delta = (int) (played_time * (float)soundSource[MUSIC_SOURCE]. sample->decoder->frequency * 4.0f); unsigned long pos; int i, step; UBYTE *scopedata = (UBYTE *) data; UBYTE *sbuffer = soundSource[MUSIC_SOURCE].sbuffer; assert (soundSource[MUSIC_SOURCE].sample->decoder->frequency >= 11025); assert (soundSource[MUSIC_SOURCE].sample->decoder->format == audio_FORMAT_STEREO16); step = soundSource[MUSIC_SOURCE].sample->decoder->frequency / 11025 * 16; if (step % 2 == 1) step++; if (delta < 0) { #if 0 log_add (log_Debug, "GetSoundData(): something's messed" " with timing, delta %d", delta); #endif delta = 0; } else if (delta > (int)(soundSource[MUSIC_SOURCE].sbuf_size * 2)) { #if 0 log_add (log_Debug, "GetSoundData(): something's messed" " with timing, delta %d", delta); #endif delta = 0; } #if 0 log_add (log_Debug, "played_data %d total_decoded %d delta %d", played_data, soundSource[MUSIC_SOURCE].total_decoded, delta); #endif pos = soundSource[MUSIC_SOURCE].sbuf_offset + delta; if (pos % 2 == 1) pos++; // pos is an unsigned type; this assertion cannot fail! // assert (pos >= 0); for (i = 0; i < RADAR_WIDTH - 2; ++i) { SDWORD s; for (;;) { if (pos >= soundSource[MUSIC_SOURCE].sbuf_size) pos = pos - soundSource[MUSIC_SOURCE].sbuf_size; else break; } s = (*(SWORD*)(&sbuffer[pos])) + (*(SWORD*)(&sbuffer[pos + 2])); s = (s / 1800) + (RADAR_HEIGHT >> 1); if (s < 1) s = 1; else if (s > RADAR_HEIGHT - 2) s = RADAR_HEIGHT - 2; scopedata[i] = (UBYTE) s; pos += step; } UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); return 1; } UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); } return 0; } // tells current position of streaming speech int GetSoundInfo (int max_len) { uint32 length, offset; LockMutex (soundSource[SPEECH_SOURCE].stream_mutex); if (soundSource[SPEECH_SOURCE].sample) { length = (uint32) (soundSource[SPEECH_SOURCE].sample->length * (float)ONE_SECOND); offset = (uint32) (GetTimeCounter () - soundSource[SPEECH_SOURCE].start_time); } else { UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); return (0); } UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex); if (offset > length) return max_len; return (int)(max_len * offset / length); } TFB_SoundChain * create_soundchain (TFB_SoundDecoder *decoder, float startTime) { TFB_SoundChain *chain; chain = (TFB_SoundChain *)HMalloc (sizeof (TFB_SoundChain)); chain->decoder = decoder; chain->next = NULL; chain->start_time = startTime; chain->tag_me = 0; chain->text = 0; return (chain); } void destroy_soundchain (TFB_SoundChain *chain) { while (chain->next) { TFB_SoundChain *tmp_chain = chain->next; chain->next = chain->next->next; if (tmp_chain->decoder) SoundDecoder_Free (tmp_chain->decoder); if (tmp_chain->text) HFree (tmp_chain->text); HFree (tmp_chain); } SoundDecoder_Free (chain->decoder); HFree (chain); } TFB_SoundChain * get_previous_chain (TFB_SoundChain *first_chain, TFB_SoundChain *current_chain) { TFB_SoundChain *prev_chain, *last_valid = NULL; prev_chain = first_chain; if (prev_chain == current_chain) return (prev_chain); while (prev_chain->next) { if (prev_chain->tag_me) last_valid = prev_chain; if (prev_chain->next == current_chain) return (last_valid); prev_chain = prev_chain->next; } return (first_chain); } uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/0000755000175000017500000000000010552600275017472 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/modaud.c0000600000175000017500000002030210543202037021066 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* MikMod decoder (.mod adapter) */ #include #include #include #include "libs/misc.h" #include "port.h" #include "types.h" #include "endian_uqm.h" #include "uio.h" #include "decoder.h" #include "libs/sound/audiocore.h" #include "libs/log.h" #include "modaud.h" #ifdef USE_INTERNAL_MIKMOD # include "libs/mikmod/mikmod.h" #else # include #endif #define THIS_PTR TFB_SoundDecoder* This static const char* moda_GetName (void); static bool moda_InitModule (int flags, const TFB_DecoderFormats*); static void moda_TermModule (void); static uint32 moda_GetStructSize (void); static int moda_GetError (THIS_PTR); static bool moda_Init (THIS_PTR); static void moda_Term (THIS_PTR); static bool moda_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); static void moda_Close (THIS_PTR); static int moda_Decode (THIS_PTR, void* buf, sint32 bufsize); static uint32 moda_Seek (THIS_PTR, uint32 pcm_pos); static uint32 moda_GetFrame (THIS_PTR); TFB_SoundDecoderFuncs moda_DecoderVtbl = { moda_GetName, moda_InitModule, moda_TermModule, moda_GetStructSize, moda_GetError, moda_Init, moda_Term, moda_Open, moda_Close, moda_Decode, moda_Seek, moda_GetFrame, }; typedef struct tfb_modsounddecoder { // always the first member TFB_SoundDecoder decoder; // private sint32 last_error; MODULE* module; } TFB_ModSoundDecoder; // MikMod Output driver // we provide our own so that we can use MikMod as // generic decoder static void* buffer; static ULONG bufsize; static ULONG written; ULONG* moda_mmout_SetOutputBuffer (void* buf, ULONG size) { buffer = buf; bufsize = size; written = 0; return &written; } static BOOL moda_mmout_IsThere (void) { return 1; } static BOOL moda_mmout_Init (void) { md_mode |= DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX; return VC_Init (); } static void moda_mmout_Exit (void) { VC_Exit (); } static void moda_mmout_Update (void) { written = 0; if (!buffer || bufsize == 0) return; written = VC_WriteBytes (buffer, bufsize); } static BOOL moda_mmout_Reset (void) { return 0; } static MDRIVER moda_mmout_drv = { NULL, "Mem Buffer", // Name "Mem Buffer driver v1.1", // Version 0, 255, // Voice limits "membuf", // Alias // The minimum mikmod version we support is 3.1.8 #if (LIBMIKMOD_VERSION_MAJOR > 3) || \ ((LIBMIKMOD_VERSION_MAJOR == 3) && (LIBMIKMOD_VERSION_MINOR >= 2)) NULL, // Cmdline help #endif NULL, moda_mmout_IsThere, VC_SampleLoad, VC_SampleUnload, VC_SampleSpace, VC_SampleLength, moda_mmout_Init, moda_mmout_Exit, moda_mmout_Reset, VC_SetNumVoices, VC_PlayStart, VC_PlayStop, moda_mmout_Update, NULL, /* FIXME: Pause */ VC_VoiceSetVolume, VC_VoiceGetVolume, VC_VoiceSetFrequency, VC_VoiceGetFrequency, VC_VoiceSetPanning, VC_VoiceGetPanning, VC_VoicePlay, VC_VoiceStop, VC_VoiceStopped, VC_VoiceGetPosition, VC_VoiceRealVolume }; static const TFB_DecoderFormats* moda_formats = NULL; // MikMod READER interface // we provide our own so that we can do loading via uio // typedef struct MUIOREADER { MREADER core; uio_Stream* file; } MUIOREADER; static BOOL moda_uioReader_Eof (MREADER* reader) { return uio_feof (((MUIOREADER*)reader)->file); } static BOOL moda_uioReader_Read (MREADER* reader, void* ptr, size_t size) { return uio_fread (ptr, size, 1, ((MUIOREADER*)reader)->file); } static int moda_uioReader_Get (MREADER* reader) { return uio_fgetc (((MUIOREADER*)reader)->file); } static BOOL moda_uioReader_Seek (MREADER* reader, long offset, int whence) { return uio_fseek (((MUIOREADER*)reader)->file, offset, whence); } static long moda_uioReader_Tell (MREADER* reader) { return uio_ftell (((MUIOREADER*)reader)->file); } MREADER* moda_new_uioReader (uio_Stream* fp) { MUIOREADER* reader = (MUIOREADER*) HMalloc (sizeof(MUIOREADER)); if (reader) { reader->core.Eof = &moda_uioReader_Eof; reader->core.Read = &moda_uioReader_Read; reader->core.Get = &moda_uioReader_Get; reader->core.Seek = &moda_uioReader_Seek; reader->core.Tell = &moda_uioReader_Tell; reader->file = fp; } return (MREADER*)reader; } void moda_delete_uioReader (MREADER* reader) { if (reader) HFree (reader); } static const char* moda_GetName (void) { return "MikMod"; } static bool moda_InitModule (int flags, const TFB_DecoderFormats* fmts) { MikMod_RegisterDriver (&moda_mmout_drv); MikMod_RegisterAllLoaders (); if (flags & audio_QUALITY_HIGH) { md_mode = DMODE_HQMIXER|DMODE_STEREO|DMODE_16BITS|DMODE_INTERP|DMODE_SURROUND; md_mixfreq = 44100; md_reverb = 1; } else if (flags & audio_QUALITY_LOW) { md_mode = DMODE_SOFT_MUSIC|DMODE_STEREO|DMODE_16BITS; md_mixfreq = 22050; md_reverb = 0; } else { md_mode = DMODE_SOFT_MUSIC|DMODE_STEREO|DMODE_16BITS|DMODE_INTERP; md_mixfreq = 44100; md_reverb = 0; } md_pansep = 64; if (MikMod_Init ("")) { log_add (log_Error, "MikMod_Init() failed, %s", MikMod_strerror (MikMod_errno)); return false; } moda_formats = fmts; return true; } static void moda_TermModule (void) { MikMod_Exit (); } static uint32 moda_GetStructSize (void) { return sizeof (TFB_ModSoundDecoder); } static int moda_GetError (THIS_PTR) { TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; int ret = moda->last_error; moda->last_error = 0; return ret; } static bool moda_Init (THIS_PTR) { //TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; This->need_swap = moda_formats->big_endian != moda_formats->want_big_endian; return true; } static void moda_Term (THIS_PTR) { //TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; moda_Close (This); // ensure cleanup } static bool moda_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) { TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; uio_Stream *fp; MREADER* reader; MODULE* mod; fp = uio_fopen (dir, filename, "rb"); if (!fp) { moda->last_error = errno; return false; } reader = moda_new_uioReader (fp); if (!reader) { moda->last_error = -1; uio_fclose (fp); return false; } mod = Player_LoadGeneric (reader, 8, 0); // can already dispose of reader and fileh moda_delete_uioReader (reader); uio_fclose (fp); if (!mod) { log_add (log_Warning, "moda_Open(): could not load %s", filename); return false; } moda->module = mod; mod->extspd = 1; mod->panflag = 1; mod->wrap = 0; mod->loop = 1; This->format = moda_formats->stereo16; This->frequency = md_mixfreq; This->length = 0; // FIXME way to obtain this from mikmod? moda->last_error = 0; return true; } static void moda_Close (THIS_PTR) { TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; if (moda->module) { Player_Free (moda->module); moda->module = NULL; } } static int moda_Decode (THIS_PTR, void* buf, sint32 bufsize) { TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; volatile ULONG* poutsize; Player_Start (moda->module); if (!Player_Active()) return 0; poutsize = moda_mmout_SetOutputBuffer (buf, bufsize); MikMod_Update (); return *poutsize; } static uint32 moda_Seek (THIS_PTR, uint32 pcm_pos) { TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; Player_Start (moda->module); if (pcm_pos) log_add (log_Debug, "moda_Seek(): " "non-zero seek positions not supported for mod"); Player_SetPosition (0); return 0; } static uint32 moda_GetFrame (THIS_PTR) { TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; return moda->module->sngpos; } uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/modaud.h0000600000175000017500000000155710543202037021106 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* MikMod adapter */ #ifndef MODAUD_H #define MODAUD_H #include "decoder.h" extern TFB_SoundDecoderFuncs moda_DecoderVtbl; #endif // MODAUD_H uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/oggaud.c0000600000175000017500000001352510543202037021074 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Ogg Vorbis decoder (.ogg adapter) */ #include #include #include #include "libs/misc.h" #include "libs/log.h" #include "port.h" #include "types.h" #include "uio.h" #include "decoder.h" #ifdef OVCODEC_TREMOR # include # include #else # include # include #endif /* OVCODEC_TREMOR */ #include "oggaud.h" #define THIS_PTR TFB_SoundDecoder* This static const char* ova_GetName (void); static bool ova_InitModule (int flags, const TFB_DecoderFormats*); static void ova_TermModule (void); static uint32 ova_GetStructSize (void); static int ova_GetError (THIS_PTR); static bool ova_Init (THIS_PTR); static void ova_Term (THIS_PTR); static bool ova_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); static void ova_Close (THIS_PTR); static int ova_Decode (THIS_PTR, void* buf, sint32 bufsize); static uint32 ova_Seek (THIS_PTR, uint32 pcm_pos); static uint32 ova_GetFrame (THIS_PTR); TFB_SoundDecoderFuncs ova_DecoderVtbl = { ova_GetName, ova_InitModule, ova_TermModule, ova_GetStructSize, ova_GetError, ova_Init, ova_Term, ova_Open, ova_Close, ova_Decode, ova_Seek, ova_GetFrame, }; typedef struct tfb_oggsounddecoder { // always the first member TFB_SoundDecoder decoder; // private sint32 last_error; OggVorbis_File vf; } TFB_OggSoundDecoder; static const TFB_DecoderFormats* ova_formats = NULL; static size_t ogg_read (void *ptr, size_t size, size_t nmemb, void *datasource) { return uio_fread (ptr, size, nmemb, (uio_Stream *) datasource); } static int ogg_seek (void *datasource, ogg_int64_t offset, int whence) { long off = (long) offset; return uio_fseek ((uio_Stream *) datasource, off, whence); } static int ogg_close (void *datasource) { return uio_fclose ((uio_Stream *) datasource); } static long ogg_tell (void *datasource) { return uio_ftell ((uio_Stream *) datasource); } static const ov_callbacks ogg_callbacks = { ogg_read, ogg_seek, ogg_close, ogg_tell, }; static const char* ova_GetName (void) { return "Ogg Vorbis"; } static bool ova_InitModule (int flags, const TFB_DecoderFormats* fmts) { ova_formats = fmts; return true; (void)flags; // laugh at compiler warning } static void ova_TermModule (void) { // no specific module term } static uint32 ova_GetStructSize (void) { return sizeof (TFB_OggSoundDecoder); } static int ova_GetError (THIS_PTR) { TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; int ret = ova->last_error; ova->last_error = 0; return ret; } static bool ova_Init (THIS_PTR) { //TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; This->need_swap = false; return true; } static void ova_Term (THIS_PTR) { //TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; ova_Close (This); // ensure cleanup } static bool ova_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) { TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; int rc; uio_Stream *fp; vorbis_info *vinfo; fp = uio_fopen (dir, filename, "rb"); if (fp == NULL) { log_add (log_Warning, "ova_Open(): could not open %s", filename); return false; } rc = ov_open_callbacks (fp, &ova->vf, NULL, 0, ogg_callbacks); if (rc != 0) { log_add (log_Warning, "ova_Open(): " "ov_open_callbacks failed for %s, error code %d", filename, rc); uio_fclose (fp); return false; } vinfo = ov_info (&ova->vf, -1); if (!vinfo) { log_add (log_Warning, "ova_Open(): " "failed to retrieve ogg bitstream info for %s", filename); ov_clear (&ova->vf); return false; } This->frequency = vinfo->rate; #ifdef OVCODEC_TREMOR // With tremor ov_time_total returns an integer, in milliseconds. This->length = ((float) ov_time_total (&ova->vf, -1)) / 1000.0f; #else // With libvorbis ov_time_total returns a double, in seconds. This->length = (float) ov_time_total (&ova->vf, -1); #endif /* OVCODEC_TREMOR */ if (vinfo->channels == 1) This->format = ova_formats->mono16; else This->format = ova_formats->stereo16; ova->last_error = 0; return true; } static void ova_Close (THIS_PTR) { TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; ov_clear (&ova->vf); } static int ova_Decode (THIS_PTR, void* buf, sint32 bufsize) { TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; long rc; int bitstream; #ifdef OVCODEC_TREMOR rc = ov_read (&ova->vf, buf, bufsize, &bitstream); #else rc = ov_read (&ova->vf, buf, bufsize, ova_formats->want_big_endian, 2, 1, &bitstream); #endif /* OVCODEC_TREMOR */ if (rc < 0) ova->last_error = rc; else ova->last_error = 0; return rc; } static uint32 ova_Seek (THIS_PTR, uint32 pcm_pos) { TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; int ret; ret = ov_pcm_seek (&ova->vf, pcm_pos); if (ret != 0) { ova->last_error = ret; return (uint32) ov_pcm_tell (&ova->vf); } else return pcm_pos; } static uint32 ova_GetFrame (THIS_PTR) { TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; // this is the closest to a frame there is in ogg vorbis stream // doesn't seem to be a func to retrive it #ifdef OVCODEC_TREMOR return ova->vf.os->pageno; #else return ova->vf.os.pageno; #endif /* OVCODEC_TREMOR */ } uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/oggaud.h0000600000175000017500000000156210543202037021077 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Ogg Vorbis adapter */ #ifndef OGGAUD_H #define OGGAUD_H #include "decoder.h" extern TFB_SoundDecoderFuncs ova_DecoderVtbl; #endif // OGGAUD_H uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/dukaud.h0000600000175000017500000000205310543202037021102 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* .duk sound track decoder */ #ifndef DUKAUD_H #define DUKAUD_H #include "decoder.h" extern TFB_SoundDecoderFuncs duka_DecoderVtbl; typedef enum { // positive values are the same as in errno dukae_None = 0, dukae_Unknown = -1, dukae_BadFile = -2, dukae_BadArg = -3, dukae_Other = -1000, } DukAud_Error; #endif // DUKAUD_H uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/wav.c0000600000175000017500000002014010543202037020412 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Wave decoder (.wav adapter) * Code is based on Creative's Win32 OpenAL implementation. */ #include #include #include "port.h" #include "types.h" #include "uio.h" #include "endian_uqm.h" #include "libs/misc.h" #include "libs/log.h" #include "wav.h" #define RIFF 0x46464952 /* "RIFF" */ #define WAVE 0x45564157 /* "WAVE" */ #define FMT 0x20746D66 /* "fmt " */ #define DATA 0x61746164 /* "data" */ typedef struct { uint32 Id; sint32 Size; uint32 Type; } WAVFileHdr_Struct; typedef struct { uint16 Format; uint16 Channels; uint32 SamplesPerSec; uint32 BytesPerSec; uint16 BlockAlign; uint16 BitsPerSample; } WAVFmtHdr_Struct; typedef struct { uint32 Id; uint32 Size; } WAVChunkHdr_Struct; #define THIS_PTR TFB_SoundDecoder* This static const char* wava_GetName (void); static bool wava_InitModule (int flags, const TFB_DecoderFormats*); static void wava_TermModule (void); static uint32 wava_GetStructSize (void); static int wava_GetError (THIS_PTR); static bool wava_Init (THIS_PTR); static void wava_Term (THIS_PTR); static bool wava_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); static void wava_Close (THIS_PTR); static int wava_Decode (THIS_PTR, void* buf, sint32 bufsize); static uint32 wava_Seek (THIS_PTR, uint32 pcm_pos); static uint32 wava_GetFrame (THIS_PTR); TFB_SoundDecoderFuncs wava_DecoderVtbl = { wava_GetName, wava_InitModule, wava_TermModule, wava_GetStructSize, wava_GetError, wava_Init, wava_Term, wava_Open, wava_Close, wava_Decode, wava_Seek, wava_GetFrame, }; typedef struct tfb_wavesounddecoder { // always the first member TFB_SoundDecoder decoder; // private sint32 last_error; uio_Stream *fp; WAVFmtHdr_Struct FmtHdr; uint32 data_ofs; uint32 data_size; uint32 max_pcm; uint32 cur_pcm; } TFB_WaveSoundDecoder; static const TFB_DecoderFormats* wava_formats = NULL; static const char* wava_GetName (void) { return "Wave"; } static bool wava_InitModule (int flags, const TFB_DecoderFormats* fmts) { wava_formats = fmts; return true; (void)flags; // laugh at compiler warning } static void wava_TermModule (void) { // no specific module term } static uint32 wava_GetStructSize (void) { return sizeof (TFB_WaveSoundDecoder); } static int wava_GetError (THIS_PTR) { TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; int ret = wava->last_error; wava->last_error = 0; return ret; } static bool wava_Init (THIS_PTR) { //TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; This->need_swap = wava_formats->want_big_endian; return true; } static void wava_Term (THIS_PTR) { //TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; wava_Close (This); // ensure cleanup } static bool wava_readFileHeader (TFB_WaveSoundDecoder* wava, WAVFileHdr_Struct* hdr) { if (!uio_fread (&hdr->Id, 4, 1, wava->fp) || !uio_fread (&hdr->Size, 4, 1, wava->fp) || !uio_fread (&hdr->Type, 4, 1, wava->fp)) { wava->last_error = errno; return false; } hdr->Id = UQM_SwapLE32 (hdr->Id); hdr->Size = UQM_SwapLE32 (hdr->Size); hdr->Type = UQM_SwapLE32 (hdr->Type); return true; } static bool wava_readChunkHeader (TFB_WaveSoundDecoder* wava, WAVChunkHdr_Struct* chunk) { if (!uio_fread (&chunk->Id, 4, 1, wava->fp) || !uio_fread (&chunk->Size, 4, 1, wava->fp)) return false; chunk->Id = UQM_SwapLE32 (chunk->Id); chunk->Size = UQM_SwapLE32 (chunk->Size); return true; } static bool wava_readFormatHeader (TFB_WaveSoundDecoder* wava, WAVFmtHdr_Struct* fmt) { if (!uio_fread (&fmt->Format, 2, 1, wava->fp) || !uio_fread (&fmt->Channels, 2, 1, wava->fp) || !uio_fread (&fmt->SamplesPerSec, 4, 1, wava->fp) || !uio_fread (&fmt->BytesPerSec, 4, 1, wava->fp) || !uio_fread (&fmt->BlockAlign, 2, 1, wava->fp) || !uio_fread (&fmt->BitsPerSample, 2, 1, wava->fp)) return false; fmt->Format = UQM_SwapLE16 (fmt->Format); fmt->Channels = UQM_SwapLE16 (fmt->Channels); fmt->SamplesPerSec = UQM_SwapLE32 (fmt->SamplesPerSec); fmt->BytesPerSec = UQM_SwapLE32 (fmt->BytesPerSec); fmt->BlockAlign = UQM_SwapLE16 (fmt->BlockAlign); fmt->BitsPerSample = UQM_SwapLE16 (fmt->BitsPerSample); return true; } static bool wava_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) { TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; WAVFileHdr_Struct FileHdr; WAVChunkHdr_Struct ChunkHdr; wava->fp = uio_fopen (dir, filename, "rb"); if (!wava->fp) { wava->last_error = errno; return false; } wava->data_size = 0; wava->data_ofs = 0; // read wave header if (!wava_readFileHeader (wava, &FileHdr)) { wava->last_error = errno; wava_Close (This); return false; } if (FileHdr.Id != RIFF || FileHdr.Type != WAVE) { log_add (log_Warning, "wava_Open(): " "not a wave file, ID 0x%08x, Type 0x%08x", FileHdr.Id, FileHdr.Type); wava_Close (This); return false; } for (FileHdr.Size = ((FileHdr.Size + 1) & ~1) - 4; FileHdr.Size != 0; FileHdr.Size -= (((ChunkHdr.Size + 1) & ~1) + 8)) { if (!wava_readChunkHeader (wava, &ChunkHdr)) { wava->last_error = errno; wava_Close (This); return false; } if (ChunkHdr.Id == FMT) { if (!wava_readFormatHeader (wava, &wava->FmtHdr)) { wava->last_error = errno; wava_Close (This); return false; } uio_fseek (wava->fp, ChunkHdr.Size - 16, SEEK_CUR); } else { if (ChunkHdr.Id == DATA) { wava->data_size = ChunkHdr.Size; wava->data_ofs = uio_ftell (wava->fp); } uio_fseek (wava->fp, ChunkHdr.Size, SEEK_CUR); } uio_fseek (wava->fp, ChunkHdr.Size & 1, SEEK_CUR); } if (!wava->data_size || !wava->data_ofs) { log_add (log_Warning, "wava_Open(): bad wave file," " no DATA chunk found"); wava_Close (This); return false; } if (wava->FmtHdr.Format == 0x0001) { This->format = (wava->FmtHdr.Channels == 1 ? (wava->FmtHdr.BitsPerSample == 8 ? wava_formats->mono8 : wava_formats->mono16) : (wava->FmtHdr.BitsPerSample == 8 ? wava_formats->stereo8 : wava_formats->stereo16) ); This->frequency = wava->FmtHdr.SamplesPerSec; } else { log_add (log_Warning, "wava_Open(): unsupported format %x", wava->FmtHdr.Format); wava_Close (This); return false; } uio_fseek (wava->fp, wava->data_ofs, SEEK_SET); wava->max_pcm = wava->data_size / wava->FmtHdr.BlockAlign; wava->cur_pcm = 0; This->length = (float) wava->max_pcm / wava->FmtHdr.SamplesPerSec; wava->last_error = 0; return true; } static void wava_Close (THIS_PTR) { TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; if (wava->fp) { uio_fclose (wava->fp); wava->fp = NULL; } } static int wava_Decode (THIS_PTR, void* buf, sint32 bufsize) { TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; uint32 dec_pcm; dec_pcm = bufsize / wava->FmtHdr.BlockAlign; if (dec_pcm > wava->max_pcm - wava->cur_pcm) dec_pcm = wava->max_pcm - wava->cur_pcm; dec_pcm = uio_fread (buf, wava->FmtHdr.BlockAlign, dec_pcm, wava->fp); wava->cur_pcm += dec_pcm; return dec_pcm * wava->FmtHdr.BlockAlign; } static uint32 wava_Seek (THIS_PTR, uint32 pcm_pos) { TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; if (pcm_pos > wava->max_pcm) pcm_pos = wava->max_pcm; wava->cur_pcm = pcm_pos; uio_fseek (wava->fp, wava->data_ofs + pcm_pos * wava->FmtHdr.BlockAlign, SEEK_SET); return pcm_pos; } static uint32 wava_GetFrame (THIS_PTR) { //TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; return 0; // only 1 frame for now (void)This; // laugh at compiler warning } uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/decoder.c0000600000175000017500000004672210543202037021240 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Sound file decoder for .wav, .mod, .ogg (to be used with OpenAL) * API is heavily influenced by SDL_sound. */ #include #include #include "port.h" #include "libs/misc.h" #include "libs/file.h" #include "libs/log.h" #include "decoder.h" #include "wav.h" #include "dukaud.h" #include "modaud.h" #include "oggaud.h" #define MAX_REG_DECODERS 31 #define THIS_PTR TFB_SoundDecoder* static const char* bufa_GetName (void); static bool bufa_InitModule (int flags, const TFB_DecoderFormats*); static void bufa_TermModule (void); static uint32 bufa_GetStructSize (void); static int bufa_GetError (THIS_PTR); static bool bufa_Init (THIS_PTR); static void bufa_Term (THIS_PTR); static bool bufa_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); static void bufa_Close (THIS_PTR); static int bufa_Decode (THIS_PTR, void* buf, sint32 bufsize); static uint32 bufa_Seek (THIS_PTR, uint32 pcm_pos); static uint32 bufa_GetFrame (THIS_PTR); TFB_SoundDecoderFuncs bufa_DecoderVtbl = { bufa_GetName, bufa_InitModule, bufa_TermModule, bufa_GetStructSize, bufa_GetError, bufa_Init, bufa_Term, bufa_Open, bufa_Close, bufa_Decode, bufa_Seek, bufa_GetFrame, }; typedef struct tfb_bufsounddecoder { // always the first member TFB_SoundDecoder decoder; // private void* data; uint32 max_pcm; uint32 cur_pcm; } TFB_BufSoundDecoder; #define SD_MIN_SIZE (sizeof (TFB_BufSoundDecoder)) static const char* nula_GetName (void); static bool nula_InitModule (int flags, const TFB_DecoderFormats*); static void nula_TermModule (void); static uint32 nula_GetStructSize (void); static int nula_GetError (THIS_PTR); static bool nula_Init (THIS_PTR); static void nula_Term (THIS_PTR); static bool nula_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); static void nula_Close (THIS_PTR); static int nula_Decode (THIS_PTR, void* buf, sint32 bufsize); static uint32 nula_Seek (THIS_PTR, uint32 pcm_pos); static uint32 nula_GetFrame (THIS_PTR); TFB_SoundDecoderFuncs nula_DecoderVtbl = { nula_GetName, nula_InitModule, nula_TermModule, nula_GetStructSize, nula_GetError, nula_Init, nula_Term, nula_Open, nula_Close, nula_Decode, nula_Seek, nula_GetFrame, }; typedef struct tfb_nullsounddecoder { // always the first member TFB_SoundDecoder decoder; // private uint32 cur_pcm; } TFB_NullSoundDecoder; #undef THIS_PTR struct TFB_RegSoundDecoder { bool builtin; bool used; // ever used indicator const char* ext; const TFB_SoundDecoderFuncs* funcs; }; static TFB_RegSoundDecoder sd_decoders[MAX_REG_DECODERS + 1] = { {true, true, "wav", &wava_DecoderVtbl}, {true, true, "mod", &moda_DecoderVtbl}, {true, true, "ogg", &ova_DecoderVtbl}, {true, true, "duk", &duka_DecoderVtbl}, {false, false, NULL, NULL}, // null term }; static TFB_DecoderFormats decoder_formats; static int sd_flags = 0; /* change endianness of 16bit words * Only works optimal when 'data' is aligned on a 32 bits boundary. */ void SoundDecoder_SwapWords (uint16* data, uint32 size) { uint32 fsize = size & (~3U); size -= fsize; fsize >>= 2; for (; fsize; fsize--, data += 2) { uint32 v = *(uint32*)data; *(uint32*)data = ((v & 0x00ff00ff) << 8) | ((v & 0xff00ff00) >> 8); } if (size) { /* leftover word */ *data = ((*data & 0x00ff) << 8) | ((*data & 0xff00) >> 8); } } const char* SoundDecoder_GetName (TFB_SoundDecoder *decoder) { if (!decoder || !decoder->funcs) return "(Null)"; return decoder->funcs->GetName (); } sint32 SoundDecoder_Init (int flags, TFB_DecoderFormats *formats) { TFB_RegSoundDecoder* info; sint32 ret = 0; if (!formats) { log_add (log_Error, "SoundDecoder_Init(): missing decoder formats"); return 1; } decoder_formats = *formats; // init built-in decoders for (info = sd_decoders; info->ext; info++) { if (!info->funcs->InitModule (flags, &decoder_formats)) { log_add (log_Error, "SoundDecoder_Init(): " "%s audio decoder init failed", info->funcs->GetName ()); ret = 1; } } sd_flags = flags; return ret; } void SoundDecoder_Uninit (void) { TFB_RegSoundDecoder* info; // uninit all decoders // and unregister loaded decoders for (info = sd_decoders; info->used; info++) { if (info->ext) // check if present info->funcs->TermModule (); if (!info->builtin) { info->used = false; info->ext = NULL; } } } TFB_RegSoundDecoder* SoundDecoder_Register (const char* fileext, TFB_SoundDecoderFuncs* decvtbl) { TFB_RegSoundDecoder* info; TFB_RegSoundDecoder* newslot = NULL; if (!decvtbl) { log_add (log_Warning, "SoundDecoder_Register(): Null decoder table"); return NULL; } if (!fileext) { log_add (log_Warning, "SoundDecoder_Register(): Bad file type for %s", decvtbl->GetName ()); return NULL; } // check if extension already registered for (info = sd_decoders; info->used && (!info->ext || strcmp (info->ext, fileext) != 0); ++info) { // and pick up an empty slot (where available) if (!newslot && !info->ext) newslot = info; } if (info >= sd_decoders + MAX_REG_DECODERS) { log_add (log_Warning, "SoundDecoder_Register(): Decoders limit reached"); return NULL; } else if (info->ext) { log_add (log_Warning, "SoundDecoder_Register(): " "'%s' decoder already registered (%s denied)", fileext, decvtbl->GetName ()); return NULL; } if (!decvtbl->InitModule (sd_flags, &decoder_formats)) { log_add (log_Warning, "SoundDecoder_Register(): %s decoder init failed", decvtbl->GetName ()); return NULL; } if (!newslot) { newslot = info; newslot->used = true; // make next one a term info[1].builtin = false; info[1].used = false; info[1].ext = NULL; } newslot->ext = fileext; newslot->funcs = decvtbl; return newslot; } void SoundDecoder_Unregister (TFB_RegSoundDecoder* regdec) { if (regdec < sd_decoders || regdec >= sd_decoders + MAX_REG_DECODERS || !regdec->ext || !regdec->funcs) { log_add (log_Warning, "SoundDecoder_Unregister(): " "Invalid or expired decoder passed"); return; } regdec->funcs->TermModule (); regdec->ext = NULL; regdec->funcs = NULL; } const TFB_SoundDecoderFuncs* SoundDecoder_Lookup (const char* fileext) { TFB_RegSoundDecoder* info; for (info = sd_decoders; info->used && (!info->ext || strcmp (info->ext, fileext) != 0); ++info) ; return info->ext ? info->funcs : NULL; } TFB_SoundDecoder* SoundDecoder_Load (uio_DirHandle *dir, char *filename, uint32 buffer_size, uint32 startTime, sint32 runTime) { const char* pext; TFB_RegSoundDecoder* info; const TFB_SoundDecoderFuncs* funcs; TFB_SoundDecoder* decoder; uint32 struct_size; pext = strrchr (filename, '.'); if (!pext) { log_add (log_Warning, "SoundDecoder_Load(): Unknown file type (%s)", filename); return NULL; } ++pext; for (info = sd_decoders; info->used && (!info->ext || strcmp (info->ext, pext) != 0); ++info) ; if (!info->ext) { log_add (log_Warning, "SoundDecoder_Load(): Unsupported file type (%s)", filename); return NULL; } funcs = info->funcs; if (!fileExists2 (dir, filename)) { if (runTime) { runTime = abs (runTime); startTime = 0; funcs = &nula_DecoderVtbl; } else { log_add (log_Warning, "SoundDecoder_Load(): %s does not exist", filename); return NULL; } } struct_size = info->funcs->GetStructSize (); if (struct_size < SD_MIN_SIZE) struct_size = SD_MIN_SIZE; decoder = (TFB_SoundDecoder*) HCalloc (struct_size); decoder->funcs = funcs; if (!decoder->funcs->Init (decoder)) { log_add (log_Warning, "SoundDecoder_Load(): " "%s decoder instance failed init", decoder->funcs->GetName ()); HFree (decoder); return NULL; } if (!decoder->funcs->Open (decoder, dir, filename)) { log_add (log_Warning, "SoundDecoder_Load(): " "%s decoder could not load %s", decoder->funcs->GetName (), filename); decoder->funcs->Term (decoder); HFree (decoder); return NULL; } decoder->buffer = HMalloc (buffer_size); decoder->buffer_size = buffer_size; decoder->looping = false; decoder->error = SOUNDDECODER_OK; decoder->dir = dir; decoder->filename = (char *) HMalloc (strlen (filename) + 1); strcpy (decoder->filename, filename); if (decoder->is_null) { // fake decoder, keeps voiceovers and etc. going decoder->length = (float) (runTime / 1000.0); } decoder->length -= startTime / 1000.0f; if (runTime > 0 && runTime / 1000.0 < decoder->length) decoder->length = (float)(runTime / 1000.0); decoder->start_sample = decoder->frequency * startTime / 1000; decoder->end_sample = decoder->start_sample + (unsigned long)(decoder->length * decoder->frequency); if (decoder->start_sample != 0) decoder->funcs->Seek (decoder, decoder->start_sample); if (decoder->format == decoder_formats.mono8) decoder->bytes_per_samp = 1; else if (decoder->format == decoder_formats.mono16) decoder->bytes_per_samp = 2; else if (decoder->format == decoder_formats.stereo8) decoder->bytes_per_samp = 2; else if (decoder->format == decoder_formats.stereo16) decoder->bytes_per_samp = 4; decoder->pos = decoder->start_sample * decoder->bytes_per_samp; return decoder; } uint32 SoundDecoder_Decode (TFB_SoundDecoder *decoder) { long decoded_bytes; long rc; long buffer_size; uint32 max_bytes = UINT32_MAX; uint8 *buffer; if (!decoder || !decoder->funcs) { log_add (log_Warning, "SoundDecoder_Decode(): null or bad decoder"); return 0; } buffer = (uint8*) decoder->buffer; buffer_size = decoder->buffer_size; if (!decoder->looping && decoder->end_sample > 0) { max_bytes = decoder->end_sample * decoder->bytes_per_samp; if (max_bytes - decoder->pos < decoder->buffer_size) buffer_size = max_bytes - decoder->pos; } if (buffer_size == 0) { // nothing more to decode decoder->error = SOUNDDECODER_EOF; return 0; } for (decoded_bytes = 0, rc = 1; rc > 0 && decoded_bytes < buffer_size; ) { rc = decoder->funcs->Decode (decoder, buffer + decoded_bytes, buffer_size - decoded_bytes); if (rc < 0) { log_add (log_Warning, "SoundDecoder_Decode(): " "error decoding %s, code %ld", decoder->filename, rc); } else if (rc == 0) { // probably EOF if (decoder->looping) { SoundDecoder_Rewind (decoder); if (decoder->error) { log_add (log_Warning, "SoundDecoder_Decode(): " "tried to loop %s but couldn't rewind, " "error code %d", decoder->filename, decoder->error); } else { log_add (log_Info, "SoundDecoder_Decode(): " "looping %s", decoder->filename); rc = 1; // prime the loop again } } else { log_add (log_Info, "SoundDecoder_Decode(): eof for %s", decoder->filename); } } else { // some bytes decoded decoded_bytes += rc; } } decoder->pos += decoded_bytes; if (rc < 0) decoder->error = SOUNDDECODER_ERROR; else if (rc == 0 || decoder->pos >= max_bytes) decoder->error = SOUNDDECODER_EOF; else decoder->error = SOUNDDECODER_OK; if (decoder->need_swap && decoded_bytes > 0 && (decoder->format == decoder_formats.stereo16 || decoder->format == decoder_formats.mono16)) { SoundDecoder_SwapWords ( decoder->buffer, decoded_bytes); } return decoded_bytes; } uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder) { uint32 decoded_bytes; long rc; uint32 reqbufsize; if (!decoder || !decoder->funcs) { log_add (log_Warning, "SoundDecoder_DecodeAll(): null or bad decoder"); return 0; } reqbufsize = decoder->buffer_size; if (decoder->looping) { log_add (log_Warning, "SoundDecoder_DecodeAll(): " "called for %s with looping", decoder->filename); return 0; } if (reqbufsize < 4096) reqbufsize = 4096; if (reqbufsize < 16384) log_add (log_Debug, "SoundDecoder_DecodeAll(): WARNING, " "called with a small buffer (%u)", reqbufsize); for (decoded_bytes = 0, rc = 1; rc > 0; ) { if (decoded_bytes >= decoder->buffer_size) { // need to grow buffer decoder->buffer_size += reqbufsize; decoder->buffer = HRealloc ( decoder->buffer, decoder->buffer_size); } rc = decoder->funcs->Decode (decoder, (uint8*) decoder->buffer + decoded_bytes, decoder->buffer_size - decoded_bytes); if (rc > 0) decoded_bytes += rc; } decoder->buffer_size = decoded_bytes; decoder->pos += decoded_bytes; if (decoder->need_swap && decoded_bytes > 0 && (decoder->format == decoder_formats.stereo16 || decoder->format == decoder_formats.mono16)) { SoundDecoder_SwapWords ( decoder->buffer, decoded_bytes); } if (rc < 0) { decoder->error = SOUNDDECODER_ERROR; log_add (log_Warning, "SoundDecoder_DecodeAll(): " "error decoding %s, code %ld", decoder->filename, rc); return decoded_bytes; } // switch to Buffer decoder decoder->funcs->Close (decoder); decoder->funcs->Term (decoder); decoder->funcs = &bufa_DecoderVtbl; decoder->funcs->Init (decoder); decoder->pos = 0; decoder->start_sample = 0; decoder->error = SOUNDDECODER_OK; return decoded_bytes; } void SoundDecoder_Rewind (TFB_SoundDecoder *decoder) { SoundDecoder_Seek (decoder, 0); } // seekTime is specified in mili-seconds void SoundDecoder_Seek (TFB_SoundDecoder *decoder, uint32 seekTime) { uint32 pcm_pos; if (!decoder) return; if (!decoder->funcs) { log_add (log_Warning, "SoundDecoder_Seek(): bad decoder passed"); return; } pcm_pos = seekTime * decoder->frequency / 1000; pcm_pos = decoder->funcs->Seek (decoder, decoder->start_sample + pcm_pos); decoder->pos = pcm_pos * decoder->bytes_per_samp; decoder->error = SOUNDDECODER_OK; } void SoundDecoder_Free (TFB_SoundDecoder *decoder) { if (!decoder) return; if (!decoder->funcs) { log_add (log_Warning, "SoundDecoder_Free(): bad decoder passed"); return; } decoder->funcs->Close (decoder); decoder->funcs->Term (decoder); HFree (decoder->buffer); HFree (decoder->filename); HFree (decoder); } float SoundDecoder_GetTime (TFB_SoundDecoder *decoder) { if (!decoder) return 0.0f; if (!decoder->funcs) { log_add (log_Warning, "SoundDecoder_GetTime(): bad decoder passed"); return 0.0f; } return (float) ((decoder->pos / decoder->bytes_per_samp) - decoder->start_sample ) / decoder->frequency; } uint32 SoundDecoder_GetFrame (TFB_SoundDecoder *decoder) { if (!decoder) return 0; if (!decoder->funcs) { log_add (log_Warning, "SoundDecoder_GetFrame(): bad decoder passed"); return 0; } return decoder->funcs->GetFrame (decoder); } #define THIS_PTR TFB_SoundDecoder* This static const char* bufa_GetName (void) { return "Buffer"; } static bool bufa_InitModule (int flags, const TFB_DecoderFormats* fmts) { // this should never be called log_add (log_Debug, "bufa_InitModule(): dead function called"); return false; (void)flags; (void)fmts; // laugh at compiler warning } static void bufa_TermModule (void) { // this should never be called log_add (log_Debug, "bufa_TermModule(): dead function called"); } static uint32 bufa_GetStructSize (void) { return sizeof (TFB_BufSoundDecoder); } static int bufa_GetError (THIS_PTR) { return 0; // error? what error?! (void)This; // laugh at compiler warning } static bool bufa_Init (THIS_PTR) { TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This; This->need_swap = false; // hijack the buffer bufa->data = This->buffer; bufa->max_pcm = This->buffer_size / This->bytes_per_samp; bufa->cur_pcm = bufa->max_pcm; return true; } static void bufa_Term (THIS_PTR) { //TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This; bufa_Close (This); // ensure cleanup } static bool bufa_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) { // this should never be called log_add (log_Debug, "bufa_Open(): dead function called"); return false; // laugh at compiler warnings (void)This; (void)dir; (void)filename; } static void bufa_Close (THIS_PTR) { TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This; // restore the status quo if (bufa->data) { This->buffer = bufa->data; bufa->data = NULL; } bufa->cur_pcm = 0; } static int bufa_Decode (THIS_PTR, void* buf, sint32 bufsize) { TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This; uint32 dec_pcm; uint32 dec_bytes; dec_pcm = bufsize / This->bytes_per_samp; if (dec_pcm > bufa->max_pcm - bufa->cur_pcm) dec_pcm = bufa->max_pcm - bufa->cur_pcm; dec_bytes = dec_pcm * This->bytes_per_samp; // Buffer decode is a hack This->buffer = (uint8*) bufa->data + bufa->cur_pcm * This->bytes_per_samp; if (dec_pcm > 0) bufa->cur_pcm += dec_pcm; return dec_bytes; (void)buf; // laugh at compiler warning } static uint32 bufa_Seek (THIS_PTR, uint32 pcm_pos) { TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This; if (pcm_pos > bufa->max_pcm) pcm_pos = bufa->max_pcm; bufa->cur_pcm = pcm_pos; return pcm_pos; } static uint32 bufa_GetFrame (THIS_PTR) { return 0; // only 1 frame (void)This; // laugh at compiler warning } static const char* nula_GetName (void) { return "Null"; } static bool nula_InitModule (int flags, const TFB_DecoderFormats* fmts) { // this should never be called log_add (log_Debug, "nula_InitModule(): dead function called"); return false; (void)flags; (void)fmts; // laugh at compiler warning } static void nula_TermModule (void) { // this should never be called log_add (log_Debug, "nula_TermModule(): dead function called"); } static uint32 nula_GetStructSize (void) { return sizeof (TFB_NullSoundDecoder); } static int nula_GetError (THIS_PTR) { return 0; // error? what error?! (void)This; // laugh at compiler warning } static bool nula_Init (THIS_PTR) { TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This; This->need_swap = false; nula->cur_pcm = 0; return true; } static void nula_Term (THIS_PTR) { //TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This; nula_Close (This); // ensure cleanup } static bool nula_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) { This->frequency = 11025; This->format = decoder_formats.mono16; This->is_null = true; return true; // laugh at compiler warnings (void)dir; (void)filename; } static void nula_Close (THIS_PTR) { TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This; nula->cur_pcm = 0; } static int nula_Decode (THIS_PTR, void* buf, sint32 bufsize) { TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This; uint32 max_pcm; uint32 dec_pcm; uint32 dec_bytes; max_pcm = (uint32) (This->length * This->frequency); dec_pcm = bufsize / This->bytes_per_samp; if (dec_pcm > max_pcm - nula->cur_pcm) dec_pcm = max_pcm - nula->cur_pcm; dec_bytes = dec_pcm * This->bytes_per_samp; if (dec_pcm > 0) { memset (buf, 0, dec_bytes); nula->cur_pcm += dec_pcm; } return dec_bytes; } static uint32 nula_Seek (THIS_PTR, uint32 pcm_pos) { TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This; uint32 max_pcm; max_pcm = (uint32) (This->length * This->frequency); if (pcm_pos > max_pcm) pcm_pos = max_pcm; nula->cur_pcm = pcm_pos; return pcm_pos; } static uint32 nula_GetFrame (THIS_PTR) { return 0; // only 1 frame (void)This; // laugh at compiler warning } uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/Makeinfo0000600000175000017500000000007010543202037021125 0ustar joeyjoeyuqm_CFILES="decoder.c wav.c dukaud.c modaud.c oggaud.c" uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/dukaud.c0000600000175000017500000003054610543202037021105 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* .duk sound track decoder */ #include #include #include #include "libs/misc.h" #include "port.h" #include "types.h" #include "uio.h" #include "dukaud.h" #include "decoder.h" #include "endian_uqm.h" #define DATA_BUF_SIZE 0x8000 #define DUCK_GENERAL_FPS 14.622f #define THIS_PTR TFB_SoundDecoder* This static const char* duka_GetName (void); static bool duka_InitModule (int flags, const TFB_DecoderFormats*); static void duka_TermModule (void); static uint32 duka_GetStructSize (void); static int duka_GetError (THIS_PTR); static bool duka_Init (THIS_PTR); static void duka_Term (THIS_PTR); static bool duka_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); static void duka_Close (THIS_PTR); static int duka_Decode (THIS_PTR, void* buf, sint32 bufsize); static uint32 duka_Seek (THIS_PTR, uint32 pcm_pos); static uint32 duka_GetFrame (THIS_PTR); TFB_SoundDecoderFuncs duka_DecoderVtbl = { duka_GetName, duka_InitModule, duka_TermModule, duka_GetStructSize, duka_GetError, duka_Init, duka_Term, duka_Open, duka_Close, duka_Decode, duka_Seek, duka_GetFrame, }; typedef struct tfb_ducksounddecoder { // always the first member TFB_SoundDecoder decoder; // public read-only uint32 iframe; // current frame index uint32 cframes; // total count of frames uint32 channels; // number of channels uint32 pcm_frame; // samples per frame // private sint32 last_error; uio_Stream* duk; uint32* frames; // buffer void* data; uint32 maxdata; uint32 cbdata; uint32 dataofs; // decoder stuff sint32 predictors[2]; } TFB_DuckSoundDecoder; typedef struct { uint32 audsize; uint32 vidsize; } DukAud_FrameHeader; typedef struct { uint16 magic; // always 0xf77f uint16 numsamples; uint16 tag; uint16 indices[2]; // initial indices for channels } DukAud_AudSubframe; static const TFB_DecoderFormats* duka_formats = NULL; sint32 duka_readAudFrameHeader (TFB_DuckSoundDecoder* duka, uint32 iframe, DukAud_AudSubframe* aud) { DukAud_FrameHeader hdr; uio_fseek (duka->duk, duka->frames[iframe], SEEK_SET); if (uio_fread (&hdr, sizeof(hdr), 1, duka->duk) != 1) { duka->last_error = errno; return dukae_BadFile; } hdr.audsize = UQM_SwapBE32 (hdr.audsize); if (uio_fread (aud, sizeof(*aud), 1, duka->duk) != 1) { duka->last_error = errno; return dukae_BadFile; } aud->magic = UQM_SwapBE16 (aud->magic); if (aud->magic != 0xf77f) return duka->last_error = dukae_BadFile; aud->numsamples = UQM_SwapBE16 (aud->numsamples); aud->tag = UQM_SwapBE16 (aud->tag); aud->indices[0] = UQM_SwapBE16 (aud->indices[0]); aud->indices[1] = UQM_SwapBE16 (aud->indices[1]); return 0; } // This table is from one of the files that came with the original 3do source // It's slightly different from the data used by MPlayer. static int adpcm_step[89] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xF, 0x10, 0x12, 0x13, 0x15, 0x17, 0x1A, 0x1C, 0x1F, 0x22, 0x26, 0x29, 0x2E, 0x32, 0x37, 0x3D, 0x43, 0x4A, 0x51, 0x59, 0x62, 0x6C, 0x76, 0x82, 0x8F, 0x9E, 0xAD, 0xBF, 0xD2, 0xE7, 0xFE, 0x117, 0x133, 0x152, 0x174, 0x199, 0x1C2, 0x1EF, 0x220, 0x256, 0x292, 0x2D4, 0x31D, 0x36C, 0x3C4, 0x424, 0x48E, 0x503, 0x583, 0x610, 0x6AC, 0x756, 0x812, 0x8E1, 0x9C4, 0xABE, 0xBD1, 0xCFF, 0xE4C, 0xFBA, 0x114D, 0x1308, 0x14EF, 0x1707, 0x1954, 0x1BDD, 0x1EA6, 0x21B7, 0x2516, 0x28CB, 0x2CDF, 0x315C, 0x364C, 0x3BBA, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x6030, 0x69CE, 0x7463, 0x7FFF }; // *** BEGIN part copied from MPlayer *** // (some little changes) #if 0 // pertinent tables for IMA ADPCM static int adpcm_step[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 }; #endif static int adpcm_index[16] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; // clamp a number between 0 and 88 #define CLAMP_0_TO_88(x) \ if ((x) < 0) (x) = 0; else if ((x) > 88) (x) = 88; // clamp a number within a signed 16-bit range #define CLAMP_S16(x) \ if ((x) < -32768) \ (x) = -32768; \ else if ((x) > 32767) \ (x) = 32767; static void decode_nibbles (sint16 *output, sint32 output_size, sint32 channels, sint32* predictors, uint16* indices) { sint32 step[2]; sint32 index[2]; sint32 diff; sint32 i; int sign; sint32 delta; int channel_number = 0; channels -= 1; index[0] = indices[0]; index[1] = indices[1]; step[0] = adpcm_step[index[0]]; step[1] = adpcm_step[index[1]]; for (i = 0; i < output_size; i++) { delta = output[i]; index[channel_number] += adpcm_index[delta]; CLAMP_0_TO_88(index[channel_number]); sign = delta & 8; delta = delta & 7; #if 0 // fast approximation, used in most decoders diff = step[channel_number] >> 3; if (delta & 4) diff += step[channel_number]; if (delta & 2) diff += step[channel_number] >> 1; if (delta & 1) diff += step[channel_number] >> 2; #else // real thing // diff = ((signed)delta + 0.5) * step[channel_number] / 4; diff = (((delta << 1) + 1) * step[channel_number]) >> 3; #endif if (sign) predictors[channel_number] -= diff; else predictors[channel_number] += diff; CLAMP_S16(predictors[channel_number]); output[i] = predictors[channel_number]; step[channel_number] = adpcm_step[index[channel_number]]; // toggle channel channel_number ^= channels; } } // *** END part copied from MPlayer *** sint32 duka_decodeFrame (TFB_DuckSoundDecoder* duka, DukAud_AudSubframe* header, uint8* input) { uint8* inend; sint16* output; sint16* outptr; sint32 outputsize; outputsize = header->numsamples * 2 * sizeof (sint16); outptr = output = (sint16*) ((uint8*)duka->data + duka->cbdata); for (inend = input + header->numsamples; input < inend; ++input) { *(outptr++) = *input >> 4; *(outptr++) = *input & 0x0f; } decode_nibbles (output, header->numsamples * 2, duka->channels, duka->predictors, header->indices); duka->cbdata += outputsize; return outputsize; } sint32 duka_readNextFrame (TFB_DuckSoundDecoder* duka) { DukAud_FrameHeader hdr; DukAud_AudSubframe* aud; uint8* p; uio_fseek (duka->duk, duka->frames[duka->iframe], SEEK_SET); if (uio_fread (&hdr, sizeof(hdr), 1, duka->duk) != 1) { duka->last_error = errno; return dukae_BadFile; } hdr.audsize = UQM_SwapBE32 (hdr.audsize); // dump encoded data at the end of the buffer aligned on 8-byte p = ((uint8*)duka->data + duka->maxdata - ((hdr.audsize + 7) & (-8))); if (uio_fread (p, 1, hdr.audsize, duka->duk) != hdr.audsize) { duka->last_error = errno; return dukae_BadFile; } aud = (DukAud_AudSubframe*) p; p += sizeof(DukAud_AudSubframe); aud->magic = UQM_SwapBE16 (aud->magic); if (aud->magic != 0xf77f) return duka->last_error = dukae_BadFile; aud->numsamples = UQM_SwapBE16 (aud->numsamples); aud->tag = UQM_SwapBE16 (aud->tag); aud->indices[0] = UQM_SwapBE16 (aud->indices[0]); aud->indices[1] = UQM_SwapBE16 (aud->indices[1]); duka->iframe++; return duka_decodeFrame (duka, aud, p); } static sint32 duka_stuffBuffer (TFB_DuckSoundDecoder* duka, void* buf, sint32 bufsize) { sint32 dataleft; dataleft = duka->cbdata - duka->dataofs; if (dataleft > 0) { if (dataleft > bufsize) dataleft = bufsize & (-4); memcpy (buf, (uint8*)duka->data + duka->dataofs, dataleft); duka->dataofs += dataleft; } if (duka->cbdata > 0 && duka->dataofs >= duka->cbdata) duka->cbdata = duka->dataofs = 0; // reset for new data return dataleft; } static const char* duka_GetName (void) { return "DukAud"; } static bool duka_InitModule (int flags, const TFB_DecoderFormats* fmts) { duka_formats = fmts; return true; (void)flags; // laugh at compiler warning } static void duka_TermModule (void) { // no specific module term } static uint32 duka_GetStructSize (void) { return sizeof (TFB_DuckSoundDecoder); } static int duka_GetError (THIS_PTR) { TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; int ret = duka->last_error; duka->last_error = dukae_None; return ret; } static bool duka_Init (THIS_PTR) { //TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; This->need_swap = duka_formats->big_endian != duka_formats->want_big_endian; return true; } static void duka_Term (THIS_PTR) { //TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; duka_Close (This); // ensure cleanup } static bool duka_Open (THIS_PTR, uio_DirHandle *dir, const char *file) { TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; uio_Stream* duk; uio_Stream* frm; DukAud_AudSubframe aud; char filename[256]; uint32 filelen; size_t cread; uint32 i; filelen = strlen (file); if (filelen > sizeof (filename) - 1) return false; strcpy (filename, file); duk = uio_fopen (dir, filename, "rb"); if (!duk) { duka->last_error = errno; return false; } strcpy (filename + filelen - 3, "frm"); frm = uio_fopen (dir, filename, "rb"); if (!frm) { duka->last_error = errno; uio_fclose (duk); return false; } duka->duk = duk; uio_fseek (frm, 0, SEEK_END); duka->cframes = uio_ftell (frm) / sizeof (uint32); uio_fseek (frm, 0, SEEK_SET); if (!duka->cframes) { duka->last_error = dukae_BadFile; uio_fclose (frm); duka_Close (This); return false; } duka->frames = (uint32*) HMalloc (duka->cframes * sizeof (uint32)); cread = uio_fread (duka->frames, sizeof (uint32), duka->cframes, frm); uio_fclose (frm); if (cread != duka->cframes) { duka->last_error = dukae_BadFile; duka_Close (This); return false; } for (i = 0; i < duka->cframes; ++i) duka->frames[i] = UQM_SwapBE32 (duka->frames[i]); if (duka_readAudFrameHeader (duka, 0, &aud) < 0) { duka_Close (This); return false; } This->frequency = 22050; This->format = duka_formats->stereo16; duka->channels = 2; duka->pcm_frame = aud.numsamples; duka->data = HMalloc (DATA_BUF_SIZE); duka->maxdata = DATA_BUF_SIZE; // estimate This->length = (float) duka->cframes / DUCK_GENERAL_FPS; duka->last_error = 0; return true; } static void duka_Close (THIS_PTR) { TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; if (duka->data) { HFree (duka->data); duka->data = NULL; } if (duka->frames) { HFree (duka->frames); duka->frames = NULL; } if (duka->duk) { uio_fclose (duka->duk); duka->duk = NULL; } duka->last_error = 0; } static int duka_Decode (THIS_PTR, void* buf, sint32 bufsize) { TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; sint32 stuffed; sint32 total = 0; if (bufsize <= 0) return duka->last_error = dukae_BadArg; do { stuffed = duka_stuffBuffer (duka, buf, bufsize); buf = (void *) ((uint8 *) buf + stuffed); bufsize -= stuffed; total += stuffed; if (bufsize > 0 && duka->iframe < duka->cframes) { stuffed = duka_readNextFrame (duka); if (stuffed <= 0) return stuffed; } } while (bufsize > 0 && duka->iframe < duka->cframes); return total; } static uint32 duka_Seek (THIS_PTR, uint32 pcm_pos) { TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; uint32 iframe; iframe = pcm_pos / duka->pcm_frame; if (iframe < duka->cframes) { duka->iframe = iframe; duka->cbdata = 0; duka->dataofs = 0; duka->predictors[0] = 0; duka->predictors[1] = 0; } return duka->iframe * duka->pcm_frame; } static uint32 duka_GetFrame (THIS_PTR) { TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; // if there is nothing buffered return the actual current frame // otherwise return previous return duka->dataofs == duka->cbdata ? duka->iframe : duka->iframe - 1; } uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/decoder.h0000600000175000017500000000671510543202037021243 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Sound file decoder for .wav, .mod, .ogg * API is heavily influenced by SDL_sound. */ #ifndef DECODER_H #define DECODER_H #include "port.h" #include "types.h" #include "uio.h" #ifdef _MSC_VER # pragma comment (lib, "vorbisfile.lib") #endif typedef struct tfb_decoderformats { bool big_endian; bool want_big_endian; uint32 mono8; uint32 stereo8; uint32 mono16; uint32 stereo16; } TFB_DecoderFormats; // forward-declare typedef struct tfb_sounddecoder TFB_SoundDecoder; #define THIS_PTR TFB_SoundDecoder* typedef struct tfb_sounddecoderfunc { const char* (* GetName) (void); bool (* InitModule) (int flags, const TFB_DecoderFormats*); void (* TermModule) (void); uint32 (* GetStructSize) (void); int (* GetError) (THIS_PTR); bool (* Init) (THIS_PTR); void (* Term) (THIS_PTR); bool (* Open) (THIS_PTR, uio_DirHandle *dir, const char *filename); void (* Close) (THIS_PTR); int (* Decode) (THIS_PTR, void* buf, sint32 bufsize); // returns <0 on error, ==0 when no more data, >0 bytes returned uint32 (* Seek) (THIS_PTR, uint32 pcm_pos); // returns the pcm position set uint32 (* GetFrame) (THIS_PTR); } TFB_SoundDecoderFuncs; #undef THIS_PTR struct tfb_sounddecoder { // decoder virtual funcs - R/O const TFB_SoundDecoderFuncs *funcs; // public R/O, set by decoder uint32 format; uint32 frequency; float length; // total length in seconds bool is_null; bool need_swap; // public R/O, set by wrapper void *buffer; uint32 buffer_size; sint32 error; uint32 bytes_per_samp; // public R/W bool looping; // semi-private uio_DirHandle *dir; char *filename; uint32 pos; uint32 start_sample; uint32 end_sample; }; // return values enum { SOUNDDECODER_OK, SOUNDDECODER_ERROR, SOUNDDECODER_EOF, }; typedef struct TFB_RegSoundDecoder TFB_RegSoundDecoder; TFB_RegSoundDecoder* SoundDecoder_Register (const char* fileext, TFB_SoundDecoderFuncs* decvtbl); void SoundDecoder_Unregister (TFB_RegSoundDecoder* regdec); const TFB_SoundDecoderFuncs* SoundDecoder_Lookup (const char* fileext); void SoundDecoder_SwapWords (uint16* data, uint32 size); sint32 SoundDecoder_Init (int flags, TFB_DecoderFormats* formats); void SoundDecoder_Uninit (void); TFB_SoundDecoder* SoundDecoder_Load (uio_DirHandle *dir, char *filename, uint32 buffer_size, uint32 startTime, sint32 runTime); uint32 SoundDecoder_Decode (TFB_SoundDecoder *decoder); uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder); float SoundDecoder_GetTime (TFB_SoundDecoder *decoder); uint32 SoundDecoder_GetFrame (TFB_SoundDecoder *decoder); void SoundDecoder_Seek (TFB_SoundDecoder *decoder, uint32 msecs); void SoundDecoder_Rewind (TFB_SoundDecoder *decoder); void SoundDecoder_Free (TFB_SoundDecoder *decoder); const char* SoundDecoder_GetName (TFB_SoundDecoder *decoder); #endif uqm-0.6.2/sc2/src/sc2code/libs/sound/decoders/wav.h0000600000175000017500000000153310543202037020424 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Wave decoder */ #ifndef WAV_H #define WAV_H #include "decoder.h" extern TFB_SoundDecoderFuncs wava_DecoderVtbl; #endif uqm-0.6.2/sc2/src/sc2code/libs/sound/sndintrn.h0000600000175000017500000000255410543202040017674 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SNDINTRN_H #define _SNDINTRN_H #include #include "sndlib.h" #include "reslib.h" extern MEM_HANDLE _GetMusicData (uio_Stream *fp, DWORD length); extern BOOLEAN _ReleaseMusicData (MEM_HANDLE handle); extern MEM_HANDLE _GetSoundBankData (uio_Stream *fp, DWORD length); extern BOOLEAN _ReleaseSoundBankData (MEM_HANDLE handle); #define AllocMusicData(s) AllocResourceData((s),MEM_ZEROINIT) #define LockMusicData LockResourceData #define UnlockMusicData UnlockResourceData #define FreeMusicData _ReleaseMusicData extern char* CheckMusicResName (char* filename); #endif /* _SNDINTRN_H */ uqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/0000755000175000017500000000000010552600275017026 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/mixer.h0000600000175000017500000001525410543202037020314 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Mixer for low-level sound output drivers */ #ifndef _MIXER_H #define _MIXER_H #include "config.h" #include "types.h" #include "endian_uqm.h" /** * The interface heavily influenced by OpenAL * to the point where you should use OpenAL's * documentation when programming the mixer. * (some source properties are not supported) * * EXCEPTION: You may not queue the same buffer * on more than one source */ #ifdef WORDS_BIGENDIAN # define MIX_IS_BIG_ENDIAN true # define MIX_WANT_BIG_ENDIAN true #else # define MIX_IS_BIG_ENDIAN false # define MIX_WANT_BIG_ENDIAN false #endif /** * Mixer errors (see OpenAL errors) */ enum { MIX_NO_ERROR = 0, MIX_INVALID_NAME = 0xA001U, MIX_INVALID_ENUM = 0xA002U, MIX_INVALID_VALUE = 0xA003U, MIX_INVALID_OPERATION = 0xA004U, MIX_OUT_OF_MEMORY = 0xA005U, MIX_DRIVER_FAILURE = 0xA101U }; /** * Source properties (see OpenAL) */ typedef enum { MIX_POSITION = 0x1004, MIX_LOOPING = 0x1007, MIX_BUFFER = 0x1009, MIX_GAIN = 0x100A, MIX_SOURCE_STATE = 0x1010, MIX_BUFFERS_QUEUED = 0x1015, MIX_BUFFERS_PROCESSED = 0x1016 } mixer_SourceProp; /** * Source state information */ typedef enum { MIX_INITIAL = 0, MIX_STOPPED, MIX_PLAYING, MIX_PAUSED, } mixer_SourceState; /** * Sound buffer properties */ typedef enum { MIX_FREQUENCY = 0x2001, MIX_BITS = 0x2002, MIX_CHANNELS = 0x2003, MIX_SIZE = 0x2004, MIX_DATA = 0x2005 } mixer_BufferProp; /** * Buffer states: semi-private */ typedef enum { MIX_BUF_INITIAL = 0, MIX_BUF_FILLED, MIX_BUF_QUEUED, MIX_BUF_PLAYING, MIX_BUF_PROCESSED } mixer_BufferState; /** Sound buffers: format specifier. * bits 00..07: bytes per sample * bits 08..15: channels * bits 15..31: meaningless */ #define MIX_FORMAT_DUMMYID 0x00170000 #define MIX_FORMAT_BPC(f) ((f) & 0xff) #define MIX_FORMAT_CHANS(f) (((f) >> 8) & 0xff) #define MIX_FORMAT_BPC_MAX 2 #define MIX_FORMAT_CHANS_MAX 2 #define MIX_FORMAT_MAKE(b, c) \ ( MIX_FORMAT_DUMMYID | ((b) & 0xff) | (((c) & 0xff) << 8) ) #define MIX_FORMAT_SAMPSIZE(f) \ ( MIX_FORMAT_BPC(f) * MIX_FORMAT_CHANS(f) ) typedef enum { MIX_FORMAT_MONO8 = MIX_FORMAT_MAKE (1, 1), MIX_FORMAT_STEREO8 = MIX_FORMAT_MAKE (1, 2), MIX_FORMAT_MONO16 = MIX_FORMAT_MAKE (2, 1), MIX_FORMAT_STEREO16 = MIX_FORMAT_MAKE (2, 2) } mixer_Format; typedef enum { MIX_QUALITY_LOW = 0, MIX_QUALITY_MEDIUM, MIX_QUALITY_HIGH, MIX_QUALITY_DEFAULT = MIX_QUALITY_MEDIUM, MIX_QUALITY_COUNT } mixer_Quality; typedef enum { MIX_NOFLAGS = 0, MIX_FAKE_DATA = 1 } mixer_Flags; /************************************************* * Interface Types */ typedef intptr_t mixer_Object; typedef intptr_t mixer_IntVal; typedef struct _mixer_Source mixer_Source; typedef struct _mixer_Buffer { uint32 magic; bool locked; mixer_BufferState state; uint8 *data; uint32 size; uint32 sampsize; uint32 high; uint32 low; float (* Resample) (mixer_Source *src, bool left); /* original buffer values for OpenAL compat */ void* orgdata; uint32 orgfreq; uint32 orgsize; uint32 orgchannels; uint32 orgchansize; /* next buffer in chain */ struct _mixer_Buffer *next; } mixer_Buffer; #define mixer_bufMagic 0x4258494DU /* MIXB in LSB */ struct _mixer_Source { uint32 magic; bool locked; mixer_SourceState state; bool looping; float gain; uint32 cqueued; uint32 cprocessed; mixer_Buffer *firstqueued; /* first buf in the queue */ mixer_Buffer *nextqueued; /* next to play, or 0 */ mixer_Buffer *prevqueued; /* previously played */ mixer_Buffer *lastqueued; /* last in queue */ uint32 pos; /* position in current buffer */ uint32 count; /* fractional part of pos */ float samplecache; }; #define mixer_srcMagic 0x5358494DU /* MIXS in LSB */ /************************************************* * General interface */ uint32 mixer_GetError (void); bool mixer_Init (uint32 frequency, uint32 format, mixer_Quality quality, mixer_Flags flags); void mixer_Uninit (void); void mixer_MixChannels (void *userdata, uint8 *stream, sint32 len); void mixer_MixFake (void *userdata, uint8 *stream, sint32 len); /************************************************* * Sources */ void mixer_GenSources (uint32 n, mixer_Object *psrcobj); void mixer_DeleteSources (uint32 n, mixer_Object *psrcobj); bool mixer_IsSource (mixer_Object srcobj); void mixer_Sourcei (mixer_Object srcobj, mixer_SourceProp pname, mixer_IntVal value); void mixer_Sourcef (mixer_Object srcobj, mixer_SourceProp pname, float value); void mixer_Sourcefv (mixer_Object srcobj, mixer_SourceProp pname, float *value); void mixer_GetSourcei (mixer_Object srcobj, mixer_SourceProp pname, mixer_IntVal *value); void mixer_GetSourcef (mixer_Object srcobj, mixer_SourceProp pname, float *value); void mixer_SourceRewind (mixer_Object srcobj); void mixer_SourcePlay (mixer_Object srcobj); void mixer_SourcePause (mixer_Object srcobj); void mixer_SourceStop (mixer_Object srcobj); void mixer_SourceQueueBuffers (mixer_Object srcobj, uint32 n, mixer_Object* pbufobj); void mixer_SourceUnqueueBuffers (mixer_Object srcobj, uint32 n, mixer_Object* pbufobj); /************************************************* * Buffers */ void mixer_GenBuffers (uint32 n, mixer_Object *pbufobj); void mixer_DeleteBuffers (uint32 n, mixer_Object *pbufobj); bool mixer_IsBuffer (mixer_Object bufobj); void mixer_GetBufferi (mixer_Object bufobj, mixer_BufferProp pname, mixer_IntVal *value); void mixer_BufferData (mixer_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq); /* Make sure the prop-value type is of suitable size * it must be able to store both int and void* * Adapted from SDL * This will generate "negative subscript or subscript is too large" * error during compile, if the actual size of a type is wrong */ #define MIX_COMPILE_TIME_ASSERT(name, x) \ typedef int mixer_dummy_##name [(x) * 2 - 1] MIX_COMPILE_TIME_ASSERT (mixer_Object, sizeof(mixer_Object) >= sizeof(void*)); MIX_COMPILE_TIME_ASSERT (mixer_IntVal, sizeof(mixer_IntVal) >= sizeof(mixer_Object)); #undef MIX_COMPILE_TIME_ASSERT #endif /* _MIXER_H */ uqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/mixer.c0000600000175000017500000011170710543202037020307 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Mixer for low-level sound output drivers */ #include #include #include #include "mixer.h" #include "mixerint.h" #include "libs/misc.h" #include "libs/threadlib.h" #include "libs/log.h" static uint32 mixer_initialized = 0; static uint32 mixer_format; static uint32 mixer_chansize; static uint32 mixer_sampsize; static uint32 mixer_freq; static uint32 mixer_channels; static uint32 last_error = MIX_NO_ERROR; static mixer_Quality mixer_quality; static mixer_Resampling mixer_resampling; static mixer_Flags mixer_flags; /* when locking more than one mutex * you must lock them in this order */ static RecursiveMutex src_mutex; static RecursiveMutex buf_mutex; static RecursiveMutex act_mutex; #define MAX_SOURCES 8 mixer_Source *active_sources[MAX_SOURCES]; /************************************************* * Internals */ static void mixer_SetError (uint32 error) { last_error = error; } /************************************************* * General interface */ uint32 mixer_GetError (void) { uint32 error = last_error; last_error = MIX_NO_ERROR; return error; } /* Initialize the mixer with a certain audio format */ bool mixer_Init (uint32 frequency, uint32 format, mixer_Quality quality, mixer_Flags flags) { if (mixer_initialized) mixer_Uninit (); last_error = MIX_NO_ERROR; memset (active_sources, 0, sizeof(mixer_Source*) * MAX_SOURCES); mixer_chansize = MIX_FORMAT_BPC (format); mixer_channels = MIX_FORMAT_CHANS (format); mixer_sampsize = MIX_FORMAT_SAMPSIZE (format); mixer_freq = frequency; mixer_quality = quality; mixer_format = format; mixer_flags = flags; mixer_resampling.None = mixer_ResampleNone; mixer_resampling.Downsample = mixer_ResampleNearest; if (mixer_quality == MIX_QUALITY_DEFAULT) mixer_resampling.Upsample = mixer_UpsampleLinear; else if (mixer_quality == MIX_QUALITY_HIGH) mixer_resampling.Upsample = mixer_UpsampleCubic; else mixer_resampling.Upsample = mixer_ResampleNearest; src_mutex = CreateRecursiveMutex("mixer_SourceMutex", SYNC_CLASS_AUDIO); buf_mutex = CreateRecursiveMutex("mixer_BufferMutex", SYNC_CLASS_AUDIO); act_mutex = CreateRecursiveMutex("mixer_ActiveMutex", SYNC_CLASS_AUDIO); mixer_initialized = 1; return true; } /* Uninitialize the mixer */ void mixer_Uninit (void) { if (mixer_initialized) { DestroyRecursiveMutex (src_mutex); DestroyRecursiveMutex (buf_mutex); DestroyRecursiveMutex (act_mutex); mixer_initialized = 0; } } /********************************************************** * THE mixer * */ void mixer_MixChannels (void *userdata, uint8 *stream, sint32 len) { uint8 *end_stream = stream + len; bool left = true; /* keep this order or die */ LockRecursiveMutex (src_mutex); LockRecursiveMutex (buf_mutex); LockRecursiveMutex (act_mutex); for (; stream < end_stream; stream += mixer_chansize) { uint32 i; float fullsamp = 0; for (i = 0; i < MAX_SOURCES; i++) { mixer_Source *src; float samp; /* find next source */ for (; i < MAX_SOURCES && ( (src = active_sources[i]) == 0 || src->state != MIX_PLAYING || !mixer_SourceGetNextSample (src, &samp, left)); i++) ; if (i < MAX_SOURCES) { /* sample acquired */ fullsamp += samp; } } /* clip the sample */ if (mixer_chansize == 2) { /* check S16 clipping */ if (fullsamp > SINT16_MAX) fullsamp = SINT16_MAX; else if (fullsamp < SINT16_MIN) fullsamp = SINT16_MIN; } else { /* check S8 clipping */ if (fullsamp > SINT8_MAX) fullsamp = SINT8_MAX; else if (fullsamp < SINT8_MIN) fullsamp = SINT8_MIN; } mixer_PutSampleExt (stream, mixer_chansize, (sint32)fullsamp); if (mixer_channels == 2) left = !left; } /* keep this order or die */ UnlockRecursiveMutex (act_mutex); UnlockRecursiveMutex (buf_mutex); UnlockRecursiveMutex (src_mutex); (void) userdata; // satisfying compiler - unused arg } /* fake mixer -- only process buffer and source states */ void mixer_MixFake (void *userdata, uint8 *stream, sint32 len) { uint8 *end_stream = stream + len; bool left = true; /* keep this order or die */ LockRecursiveMutex (src_mutex); LockRecursiveMutex (buf_mutex); LockRecursiveMutex (act_mutex); for (; stream < end_stream; stream += mixer_chansize) { uint32 i; for (i = 0; i < MAX_SOURCES; i++) { mixer_Source *src; float samp; /* find next source */ for (; i < MAX_SOURCES && ( (src = active_sources[i]) == 0 || src->state != MIX_PLAYING || !mixer_SourceGetFakeSample (src, &samp, left)); i++) ; } if (mixer_channels == 2) left = !left; } /* keep this order or die */ UnlockRecursiveMutex (act_mutex); UnlockRecursiveMutex (buf_mutex); UnlockRecursiveMutex (src_mutex); (void) userdata; // satisfying compiler - unused arg } /************************************************* * Sources interface */ /* generate n sources */ void mixer_GenSources (uint32 n, mixer_Object *psrcobj) { if (n == 0) return; /* do nothing per OpenAL */ if (!psrcobj) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_GenSources() called with null ptr"); return; } for (; n; n--, psrcobj++) { mixer_Source *src; src = (mixer_Source *) HMalloc (sizeof (mixer_Source)); src->magic = mixer_srcMagic; src->locked = false; src->state = MIX_INITIAL; src->looping = false; src->gain = MIX_GAIN_ADJ; src->cqueued = 0; src->cprocessed = 0; src->firstqueued = 0; src->nextqueued = 0; src->prevqueued = 0; src->lastqueued = 0; src->pos = 0; src->count = 0; *psrcobj = (mixer_Object) src; } } /* delete n sources */ void mixer_DeleteSources (uint32 n, mixer_Object *psrcobj) { uint32 i; mixer_Object *pcurobj; if (n == 0) return; /* do nothing per OpenAL */ if (!psrcobj) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_DeleteSources() called with null ptr"); return; } LockRecursiveMutex (src_mutex); /* check to make sure we can delete all sources */ for (i = n, pcurobj = psrcobj; i && pcurobj; i--, pcurobj++) { mixer_Source *src = (mixer_Source *) *pcurobj; if (!src) continue; if (src->magic != mixer_srcMagic) break; } if (i) { /* some source failed */ mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_DeleteSources(): not a source"); } else { /* all sources checked out */ for (; n; n--, psrcobj++) { mixer_Source *src = (mixer_Source *) *psrcobj; if (!src) continue; /* stopping should not be necessary * under ideal circumstances */ if (src->state != MIX_INITIAL) mixer_SourceStop_internal (src); /* unqueueing should not be necessary * under ideal circumstances */ mixer_SourceUnqueueAll (src); HFree (src); *psrcobj = 0; } } UnlockRecursiveMutex (src_mutex); } /* check if really is a source */ bool mixer_IsSource (mixer_Object srcobj) { mixer_Source *src = (mixer_Source *) srcobj; bool ret; if (!src) return false; LockRecursiveMutex (src_mutex); ret = src->magic == mixer_srcMagic; UnlockRecursiveMutex (src_mutex); return ret; } /* set source integer property */ void mixer_Sourcei (mixer_Object srcobj, mixer_SourceProp pname, mixer_IntVal value) { mixer_Source *src = (mixer_Source *) srcobj; if (!src) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_Sourcei() called with null source"); return; } LockRecursiveMutex (src_mutex); if (src->magic != mixer_srcMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_Sourcei(): not a source"); } else { switch (pname) { case MIX_LOOPING: src->looping = value; break; case MIX_BUFFER: { mixer_Buffer *buf = (mixer_Buffer *) value; if (src->cqueued > 0) mixer_SourceUnqueueAll (src); if (buf && !mixer_CheckBufferState (buf, "mixer_Sourcei")) break; src->firstqueued = buf; src->nextqueued = src->firstqueued; src->prevqueued = 0; src->lastqueued = src->nextqueued; if (src->lastqueued) src->lastqueued->next = 0; src->cqueued = 1; } break; case MIX_SOURCE_STATE: if (value == MIX_INITIAL) { mixer_SourceRewind_internal (src); } else { log_add (log_Debug, "mixer_Sourcei(MIX_SOURCE_STATE): " "unsupported state, call ignored"); } break; default: mixer_SetError (MIX_INVALID_ENUM); log_add (log_Debug, "mixer_Sourcei() called " "with unsupported property %u", pname); } } UnlockRecursiveMutex (src_mutex); } /* set source float property */ void mixer_Sourcef (mixer_Object srcobj, mixer_SourceProp pname, float value) { mixer_Source *src = (mixer_Source *) srcobj; if (!src) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_Sourcef() called with null source"); return; } LockRecursiveMutex (src_mutex); if (src->magic != mixer_srcMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_Sourcef(): not a source"); } else { switch (pname) { case MIX_GAIN: src->gain = value * MIX_GAIN_ADJ; break; default: log_add (log_Debug, "mixer_Sourcei() called " "with unsupported property %u", pname); } } UnlockRecursiveMutex (src_mutex); } /* set source float array property (CURRENTLY NOT IMPLEMENTED) */ void mixer_Sourcefv (mixer_Object srcobj, mixer_SourceProp pname, float *value) { (void)srcobj; (void)pname; (void)value; } /* get source integer property */ void mixer_GetSourcei (mixer_Object srcobj, mixer_SourceProp pname, mixer_IntVal *value) { mixer_Source *src = (mixer_Source *) srcobj; if (!src || !value) { mixer_SetError (src ? MIX_INVALID_VALUE : MIX_INVALID_NAME); log_add (log_Debug, "mixer_GetSourcei() called with null param"); return; } LockRecursiveMutex (src_mutex); if (src->magic != mixer_srcMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_GetSourcei(): not a source"); } else { switch (pname) { case MIX_LOOPING: *value = src->looping; break; case MIX_BUFFER: *value = (mixer_IntVal) src->firstqueued; break; case MIX_SOURCE_STATE: *value = src->state; break; case MIX_BUFFERS_QUEUED: *value = src->cqueued; break; case MIX_BUFFERS_PROCESSED: *value = src->cprocessed; break; default: mixer_SetError (MIX_INVALID_ENUM); log_add (log_Debug, "mixer_GetSourcei() called " "with unsupported property %u", pname); } } UnlockRecursiveMutex (src_mutex); } /* get source float property */ void mixer_GetSourcef (mixer_Object srcobj, mixer_SourceProp pname, float *value) { mixer_Source *src = (mixer_Source *) srcobj; if (!src || !value) { mixer_SetError (src ? MIX_INVALID_VALUE : MIX_INVALID_NAME); log_add (log_Debug, "mixer_GetSourcef() called with null param"); return; } LockRecursiveMutex (src_mutex); if (src->magic != mixer_srcMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_GetSourcef(): not a source"); } else { switch (pname) { case MIX_GAIN: *value = src->gain / MIX_GAIN_ADJ; break; default: log_add (log_Debug, "mixer_GetSourcef() called " "with unsupported property %u", pname); } } UnlockRecursiveMutex (src_mutex); } /* start the source; add it to active array */ void mixer_SourcePlay (mixer_Object srcobj) { mixer_Source *src = (mixer_Source *) srcobj; if (!src) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourcePlay() called with null source"); return; } LockRecursiveMutex (src_mutex); if (src->magic != mixer_srcMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourcePlay(): not a source"); } else /* should make the source active */ { if (src->state < MIX_PLAYING) { if (src->firstqueued && !src->nextqueued) mixer_SourceRewind_internal (src); mixer_SourceActivate (src); } src->state = MIX_PLAYING; } UnlockRecursiveMutex (src_mutex); } /* stop the source; remove it from active array and requeue buffers */ void mixer_SourceRewind (mixer_Object srcobj) { mixer_Source *src = (mixer_Source *) srcobj; if (!src) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourceRewind() called with null source"); return; } LockRecursiveMutex (src_mutex); if (src->magic != mixer_srcMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourcePlay(): not a source"); } else { mixer_SourceRewind_internal (src); } UnlockRecursiveMutex (src_mutex); } /* pause the source; keep in active array */ void mixer_SourcePause (mixer_Object srcobj) { mixer_Source *src = (mixer_Source *) srcobj; if (!src) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourcePause() called with null source"); return; } LockRecursiveMutex (src_mutex); if (src->magic != mixer_srcMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourcePause(): not a source"); } else /* should keep all buffers and offsets */ { if (src->state < MIX_PLAYING) mixer_SourceActivate (src); src->state = MIX_PAUSED; } UnlockRecursiveMutex (src_mutex); } /* stop the source; remove it from active array * and unqueue 'queued' buffers */ void mixer_SourceStop (mixer_Object srcobj) { mixer_Source *src = (mixer_Source *) srcobj; if (!src) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourceStop() called with null source"); return; } LockRecursiveMutex (src_mutex); if (src->magic != mixer_srcMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourceStop(): not a source"); } else /* should remove queued buffers */ { if (src->state >= MIX_PLAYING) mixer_SourceDeactivate (src); mixer_SourceStop_internal (src); src->state = MIX_STOPPED; } UnlockRecursiveMutex (src_mutex); } /* queue buffers on the source */ void mixer_SourceQueueBuffers (mixer_Object srcobj, uint32 n, mixer_Object* pbufobj) { uint32 i; mixer_Object* pobj; mixer_Source *src = (mixer_Source *) srcobj; if (!src || !pbufobj) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourceQueueBuffers() called " "with null param"); return; } LockRecursiveMutex (buf_mutex); /* check to make sure we can safely queue all buffers */ for (i = n, pobj = pbufobj; i; i--, pobj++) { mixer_Buffer *buf = (mixer_Buffer *) *pobj; if (!buf || !mixer_CheckBufferState (buf, "mixer_SourceQueueBuffers")) { break; } } UnlockRecursiveMutex (buf_mutex); if (i == 0) { /* all buffers checked out */ LockRecursiveMutex (src_mutex); LockRecursiveMutex (buf_mutex); if (src->magic != mixer_srcMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourceQueueBuffers(): not a source"); } else { for (i = n, pobj = pbufobj; i; i--, pobj++) { mixer_Buffer *buf = (mixer_Buffer *) *pobj; /* add buffer to the chain */ if (src->lastqueued) src->lastqueued->next = buf; src->lastqueued = buf; if (!src->firstqueued) { src->firstqueued = buf; src->nextqueued = buf; src->prevqueued = 0; } src->cqueued++; buf->state = MIX_BUF_QUEUED; } } UnlockRecursiveMutex (buf_mutex); UnlockRecursiveMutex (src_mutex); } } /* unqueue buffers from the source */ void mixer_SourceUnqueueBuffers (mixer_Object srcobj, uint32 n, mixer_Object* pbufobj) { uint32 i; mixer_Source *src = (mixer_Source *) srcobj; mixer_Buffer *curbuf = 0; if (!src || !pbufobj) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourceUnqueueBuffers() called " "with null source"); return; } LockRecursiveMutex (src_mutex); if (src->magic != mixer_srcMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_SourceUnqueueBuffers(): not a source"); } else if (n > src->cqueued) { mixer_SetError (MIX_INVALID_OPERATION); } else { LockRecursiveMutex (buf_mutex); /* check to make sure we can unqueue all buffers */ for (i = n, curbuf = src->firstqueued; i && curbuf && curbuf->state != MIX_BUF_PLAYING; i--, curbuf = curbuf->next) ; if (i) { mixer_SetError (MIX_INVALID_OPERATION); log_add (log_Debug, "mixer_SourceUnqueueBuffers(): " "active buffer attempted"); } else { /* all buffers checked out */ for (i = n; i; i--, pbufobj++) { mixer_Buffer *buf = src->firstqueued; /* remove buffer from the chain */ if (src->nextqueued == buf) src->nextqueued = buf->next; if (src->prevqueued == buf) src->prevqueued = 0; if (src->lastqueued == buf) src->lastqueued = 0; src->firstqueued = buf->next; src->cqueued--; if (buf->state == MIX_BUF_PROCESSED) src->cprocessed--; buf->state = MIX_BUF_FILLED; buf->next = 0; *pbufobj = (mixer_Object) buf; } } UnlockRecursiveMutex (buf_mutex); } UnlockRecursiveMutex (src_mutex); } /************************************************* * Sources internals */ static void mixer_SourceUnqueueAll (mixer_Source *src) { mixer_Buffer *buf; mixer_Buffer *nextbuf; if (!src) { log_add (log_Debug, "mixer_SourceUnqueueAll() called " "with null source"); return; } LockRecursiveMutex (buf_mutex); for (buf = src->firstqueued; buf; buf = nextbuf) { if (buf->state == MIX_BUF_PLAYING) { log_add (log_Debug, "mixer_SourceUnqueueAll(): " "attempted on active buffer"); } nextbuf = buf->next; buf->state = MIX_BUF_FILLED; buf->next = 0; } UnlockRecursiveMutex (buf_mutex); src->firstqueued = 0; src->nextqueued = 0; src->prevqueued = 0; src->lastqueued = 0; src->cqueued = 0; src->cprocessed = 0; src->pos = 0; src->count = 0; } /* add the source to the active array */ static void mixer_SourceActivate (mixer_Source* src) { uint32 i; LockRecursiveMutex (act_mutex); /* check active sources, see if this source is there already */ for (i = 0; i < MAX_SOURCES && active_sources[i] != src; i++) ; if (i < MAX_SOURCES) { /* source found */ log_add (log_Debug, "mixer_SourceActivate(): " "source already active in slot %u", i); UnlockRecursiveMutex (act_mutex); return; } /* find an empty slot */ for (i = 0; i < MAX_SOURCES && active_sources[i] != 0; i++) ; if (i < MAX_SOURCES) { /* slot found */ active_sources[i] = src; } else { log_add (log_Debug, "mixer_SourceActivate(): " "no more slots available (max=%d)", MAX_SOURCES); } UnlockRecursiveMutex (act_mutex); } /* remove the source from the active array */ static void mixer_SourceDeactivate (mixer_Source* src) { uint32 i; LockRecursiveMutex (act_mutex); /* check active sources, see if this source is there */ for (i = 0; i < MAX_SOURCES && active_sources[i] != src; i++) ; if (i < MAX_SOURCES) { /* source found */ active_sources[i] = 0; } else { /* source not found */ log_add (log_Debug, "mixer_SourceDeactivate(): source not active"); } UnlockRecursiveMutex (act_mutex); } static void mixer_SourceStop_internal (mixer_Source *src) { mixer_Buffer *buf; mixer_Buffer *nextbuf; if (!src->firstqueued) return; /* assert the source buffers state */ if (!src->lastqueued) { log_add (log_Debug, "mixer_SourceStop_internal(): " "desynced source state"); #ifdef DEBUG explode (); #endif } LockRecursiveMutex (buf_mutex); /* find last 'processed' buffer */ for (buf = src->firstqueued; buf && buf->next && buf->next != src->nextqueued; buf = buf->next) ; src->lastqueued = buf; if (buf) buf->next = 0; /* break the chain */ /* unqueue all 'queued' buffers */ for (buf = src->nextqueued; buf; buf = nextbuf) { nextbuf = buf->next; buf->state = MIX_BUF_FILLED; buf->next = 0; src->cqueued--; } if (src->cqueued == 0) { /* all buffers were removed */ src->firstqueued = 0; src->lastqueued = 0; } src->nextqueued = 0; src->prevqueued = 0; src->pos = 0; src->count = 0; UnlockRecursiveMutex (buf_mutex); } static void mixer_SourceRewind_internal (mixer_Source *src) { /* should change the processed buffers to queued */ mixer_Buffer *buf; if (src->state >= MIX_PLAYING) mixer_SourceDeactivate (src); LockRecursiveMutex (buf_mutex); for (buf = src->firstqueued; buf && buf->state != MIX_BUF_QUEUED; buf = buf->next) { buf->state = MIX_BUF_QUEUED; } UnlockRecursiveMutex (buf_mutex); src->pos = 0; src->count = 0; src->cprocessed = 0; src->nextqueued = src->firstqueued; src->prevqueued = 0; src->state = MIX_INITIAL; } /* get the sample next in queue in internal format */ static inline bool mixer_SourceGetNextSample (mixer_Source *src, float *psamp, bool left) { /* fake the data if requested */ if (mixer_flags & MIX_FAKE_DATA) return mixer_SourceGetFakeSample (src, psamp, left); while (src->nextqueued) { mixer_Buffer *buf = src->nextqueued; if (!buf->data || buf->size < mixer_sampsize) { /* buffer invalid, go next */ buf->state = MIX_BUF_PROCESSED; src->pos = 0; src->nextqueued = src->nextqueued->next; src->cprocessed++; continue; } if (!left && buf->orgchannels == 1) { /* mono source so we can copy left channel to right */ *psamp = src->samplecache; } else { *psamp = src->samplecache = buf->Resample(src, left) * src->gain; } if (src->pos < buf->size || (left && buf->sampsize != mixer_sampsize)) { buf->state = MIX_BUF_PLAYING; } else { /* buffer exhausted, go next */ buf->state = MIX_BUF_PROCESSED; src->pos = 0; src->prevqueued = src->nextqueued; src->nextqueued = src->nextqueued->next; src->cprocessed++; } return true; } /* no more playable buffers */ if (src->state >= MIX_PLAYING) mixer_SourceDeactivate (src); src->state = MIX_STOPPED; return false; } /* fake the next sample, but process buffers and states */ static inline bool mixer_SourceGetFakeSample (mixer_Source *src, float *psamp, bool left) { while (src->nextqueued) { mixer_Buffer *buf = src->nextqueued; if (left || buf->orgchannels != 1) { if (mixer_freq == buf->orgfreq) src->pos += mixer_chansize; else mixer_SourceAdvance(src, left); } *psamp = 0; if (src->pos < buf->size || (left && buf->sampsize != mixer_sampsize)) { buf->state = MIX_BUF_PLAYING; } else { /* buffer exhausted, go next */ buf->state = MIX_BUF_PROCESSED; src->pos = 0; src->prevqueued = src->nextqueued; src->nextqueued = src->nextqueued->next; src->cprocessed++; } return true; } /* no more playable buffers */ if (src->state >= MIX_PLAYING) mixer_SourceDeactivate (src); src->state = MIX_STOPPED; return false; } /* advance position in currently queued buffer */ static inline uint32 mixer_SourceAdvance (mixer_Source *src, bool left) { mixer_Buffer *curr = src->nextqueued; if (curr->orgchannels == 2 && mixer_channels == 2) { if (!left) { src->pos += curr->high; src->count += curr->low; if (src->count > UINT16_MAX) { src->count -= UINT16_MAX; src->pos += curr->sampsize; } return mixer_chansize; } } else { src->pos += curr->high; src->count += curr->low; if (src->count > UINT16_MAX) { src->count -= UINT16_MAX; src->pos += curr->sampsize; } } return 0; } /************************************************* * Buffers interface */ /* generate n buffer objects */ void mixer_GenBuffers (uint32 n, mixer_Object *pbufobj) { if (n == 0) return; /* do nothing per OpenAL */ if (!pbufobj) { mixer_SetError (MIX_INVALID_VALUE); log_add (log_Debug, "mixer_GenBuffers() called with null ptr"); return; } for (; n; n--, pbufobj++) { mixer_Buffer *buf; buf = (mixer_Buffer *) HMalloc (sizeof (mixer_Buffer)); buf->magic = mixer_bufMagic; buf->locked = false; buf->state = MIX_BUF_INITIAL; buf->data = 0; buf->size = 0; buf->next = 0; buf->orgdata = 0; buf->orgfreq = 0; buf->orgsize = 0; buf->orgchannels = 0; buf->orgchansize = 0; *pbufobj = (mixer_Object) buf; } } /* delete n buffer objects */ void mixer_DeleteBuffers (uint32 n, mixer_Object *pbufobj) { uint32 i; mixer_Object *pcurobj; if (n == 0) return; /* do nothing per OpenAL */ if (!pbufobj) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_DeleteBuffers() called with null ptr"); return; } LockRecursiveMutex (buf_mutex); /* check to make sure we can delete all buffers */ for (i = n, pcurobj = pbufobj; i && pcurobj; i--, pcurobj++) { mixer_Buffer *buf = (mixer_Buffer *) *pcurobj; if (!buf) continue; if (buf->magic != mixer_bufMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_DeleteBuffers(): not a buffer"); break; } else if (buf->locked) { mixer_SetError (MIX_INVALID_OPERATION); log_add (log_Debug, "mixer_DeleteBuffers(): locked buffer"); break; } else if (buf->state >= MIX_BUF_QUEUED) { mixer_SetError (MIX_INVALID_OPERATION); log_add (log_Debug, "mixer_DeleteBuffers(): " "attempted on queued/active buffer"); break; } } if (i == 0) { /* all buffers check out */ for (; n; n--, pbufobj++) { mixer_Buffer *buf = (mixer_Buffer *) *pbufobj; if (!buf) continue; if (buf->data) HFree (buf->data); HFree (buf); *pbufobj = 0; } } UnlockRecursiveMutex (buf_mutex); } /* check if really a buffer object */ bool mixer_IsBuffer (mixer_Object bufobj) { mixer_Buffer *buf = (mixer_Buffer *) bufobj; bool ret; if (!buf) return false; LockRecursiveMutex (buf_mutex); ret = buf->magic == mixer_bufMagic; UnlockRecursiveMutex (buf_mutex); return ret; } /* get buffer property */ void mixer_GetBufferi (mixer_Object bufobj, mixer_BufferProp pname, mixer_IntVal *value) { mixer_Buffer *buf = (mixer_Buffer *) bufobj; if (!buf || !value) { mixer_SetError (buf ? MIX_INVALID_VALUE : MIX_INVALID_NAME); log_add (log_Debug, "mixer_GetBufferi() called with null param"); return; } LockRecursiveMutex (buf_mutex); if (buf->locked) { UnlockRecursiveMutex (buf_mutex); mixer_SetError (MIX_INVALID_OPERATION); log_add (log_Debug, "mixer_GetBufferi() called with locked buffer"); return; } if (buf->magic != mixer_bufMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_GetBufferi(): not a buffer"); } else { /* Return original buffer values */ switch (pname) { case MIX_FREQUENCY: *value = buf->orgfreq; break; case MIX_BITS: *value = buf->orgchansize << 3; break; case MIX_CHANNELS: *value = buf->orgchannels; break; case MIX_SIZE: *value = buf->orgsize; break; case MIX_DATA: *value = (mixer_IntVal) buf->orgdata; break; default: mixer_SetError (MIX_INVALID_ENUM); log_add (log_Debug, "mixer_GetBufferi() called " "with invalid property %u", pname); } } UnlockRecursiveMutex (buf_mutex); } /* fill buffer with external data */ void mixer_BufferData (mixer_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq) { mixer_Buffer *buf = (mixer_Buffer *) bufobj; mixer_Convertion conv; uint32 dstsize; if (!buf || !data || !size) { mixer_SetError (buf ? MIX_INVALID_VALUE : MIX_INVALID_NAME); log_add (log_Debug, "mixer_BufferData() called with bad param"); return; } LockRecursiveMutex (buf_mutex); if (buf->locked) { UnlockRecursiveMutex (buf_mutex); mixer_SetError (MIX_INVALID_OPERATION); log_add (log_Debug, "mixer_BufferData() called " "with locked buffer"); return; } if (buf->magic != mixer_bufMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "mixer_BufferData(): not a buffer"); } else if (buf->state > MIX_BUF_FILLED) { mixer_SetError (MIX_INVALID_OPERATION); log_add (log_Debug, "mixer_BufferData() attempted " "on in-use buffer"); } else { if (buf->data) HFree (buf->data); buf->data = 0; buf->size = 0; /* Store original buffer values for OpenAL compatibility */ buf->orgdata = data; buf->orgfreq = freq; buf->orgsize = size; buf->orgchannels = MIX_FORMAT_CHANS (format); buf->orgchansize = MIX_FORMAT_BPC (format); conv.srcsamples = conv.dstsamples = size / MIX_FORMAT_SAMPSIZE (format); if (conv.dstsamples > UINT32_MAX / MIX_FORMAT_SAMPSIZE (format)) { mixer_SetError (MIX_INVALID_VALUE); } else { if (MIX_FORMAT_CHANS (format) < MIX_FORMAT_CHANS (mixer_format)) buf->sampsize = MIX_FORMAT_BPC (mixer_format) * MIX_FORMAT_CHANS (format); else buf->sampsize = MIX_FORMAT_SAMPSIZE (mixer_format); buf->size = dstsize = conv.dstsamples * buf->sampsize; /* only copy/convert the data if not faking */ if (! (mixer_flags & MIX_FAKE_DATA)) { buf->data = HMalloc (dstsize); if (MIX_FORMAT_BPC (format) == MIX_FORMAT_BPC (mixer_format) && MIX_FORMAT_CHANS (format) <= MIX_FORMAT_CHANS (mixer_format)) { /* format is compatible with internal */ buf->locked = true; UnlockRecursiveMutex (buf_mutex); memcpy (buf->data, data, size); if (MIX_FORMAT_BPC (format) == 1) { /* convert buffer to S8 format internally */ uint8* dst; for (dst = buf->data; dstsize; dstsize--, dst++) *dst ^= 0x80; } LockRecursiveMutex (buf_mutex); buf->locked = false; } else { /* needs convertion */ conv.srcfmt = format; conv.srcdata = data; conv.srcsize = size; if (MIX_FORMAT_CHANS (format) < MIX_FORMAT_CHANS (mixer_format)) conv.dstfmt = MIX_FORMAT_MAKE (mixer_chansize, MIX_FORMAT_CHANS (format)); else conv.dstfmt = mixer_format; conv.dstdata = buf->data; conv.dstsize = dstsize; buf->locked = true; UnlockRecursiveMutex (buf_mutex); mixer_ConvertBuffer_internal (&conv); LockRecursiveMutex (buf_mutex); buf->locked = false; } } buf->state = MIX_BUF_FILLED; buf->high = (buf->orgfreq / mixer_freq) * buf->sampsize; buf->low = (((buf->orgfreq % mixer_freq) << 16) / mixer_freq); if (mixer_freq == buf->orgfreq) buf->Resample = mixer_resampling.None; else if (mixer_freq > buf->orgfreq) buf->Resample = mixer_resampling.Upsample; else buf->Resample = mixer_resampling.Downsample; } } UnlockRecursiveMutex (buf_mutex); } /************************************************* * Buffer internals */ static inline bool mixer_CheckBufferState (mixer_Buffer *buf, const char* FuncName) { if (!buf) return false; if (buf->magic != mixer_bufMagic) { mixer_SetError (MIX_INVALID_NAME); log_add (log_Debug, "%s(): not a buffer", FuncName); return false; } if (buf->locked) { mixer_SetError (MIX_INVALID_OPERATION); log_add (log_Debug, "%s(): locked buffer attempted", FuncName); return false; } if (buf->state != MIX_BUF_FILLED) { mixer_SetError (MIX_INVALID_OPERATION); log_add (log_Debug, "%s: invalid buffer attempted", FuncName); return false; } return true; } static void mixer_ConvertBuffer_internal (mixer_Convertion *conv) { conv->srcbpc = MIX_FORMAT_BPC (conv->srcfmt); conv->srcchans = MIX_FORMAT_CHANS (conv->srcfmt); conv->dstbpc = MIX_FORMAT_BPC (conv->dstfmt); conv->dstchans = MIX_FORMAT_CHANS (conv->dstfmt); conv->flags = 0; if (conv->srcbpc > conv->dstbpc) conv->flags |= mixConvSizeDown; else if (conv->srcbpc < conv->dstbpc) conv->flags |= mixConvSizeUp; if (conv->srcchans > conv->dstchans) conv->flags |= mixConvStereoDown; else if (conv->srcchans < conv->dstchans) conv->flags |= mixConvStereoUp; mixer_ResampleFlat (conv); } /************************************************* * Resampling routines */ /* get a sample from external buffer * in internal format */ static inline sint32 mixer_GetSampleExt (void *src, uint32 bpc) { if (bpc == 2) return *(sint16 *)src; else return (*(uint8 *)src) - 128; } /* get a sample from internal buffer */ static inline sint32 mixer_GetSampleInt (void *src, uint32 bpc) { if (bpc == 2) return *(sint16 *)src; else return *(sint8 *)src; } /* put a sample into an external buffer * from internal format */ static inline void mixer_PutSampleExt (void *dst, uint32 bpc, sint32 samp) { if (bpc == 2) *(sint16 *)dst = samp; else *(uint8 *)dst = samp ^ 0x80; } /* put a sample into an internal buffer * in internal format */ static inline void mixer_PutSampleInt (void *dst, uint32 bpc, sint32 samp) { if (bpc == 2) *(sint16 *)dst = samp; else *(sint8 *)dst = samp; } /* get a sample from source */ static float mixer_ResampleNone (mixer_Source *src, bool left) { uint8 *d0 = src->nextqueued->data + src->pos; src->pos += mixer_chansize; (void) left; // satisfying compiler - unused arg return (float)mixer_GetSampleInt (d0, mixer_chansize); } /* get a resampled (up/down) sample from source (nearest neighbor) */ static float mixer_ResampleNearest (mixer_Source *src, bool left) { uint8 *d0 = src->nextqueued->data + src->pos; d0 += mixer_SourceAdvance (src, left); return (float)mixer_GetSampleInt (d0, mixer_chansize); } /* get an upsampled sample from source (linear interpolation) */ static float mixer_UpsampleLinear (mixer_Source *src, bool left) { mixer_Buffer *curr = src->nextqueued; mixer_Buffer *next = src->nextqueued->next; uint8 *d0, *d1; float s0, s1, t; t = src->count / 65536.0f; d0 = curr->data + src->pos; d0 += mixer_SourceAdvance (src, left); if (d0 + curr->sampsize >= curr->data + curr->size) { if (next && next->data && next->size >= curr->sampsize) { d1 = next->data; if (!left) d1 += mixer_chansize; } else d1 = d0; } else d1 = d0 + curr->sampsize; s0 = (float)mixer_GetSampleInt (d0, mixer_chansize); s1 = (float)mixer_GetSampleInt (d1, mixer_chansize); return s0 + t * (s1 - s0); } /* get an upsampled sample from source (cubic interpolation) */ static float mixer_UpsampleCubic (mixer_Source *src, bool left) { mixer_Buffer *prev = src->prevqueued; mixer_Buffer *curr = src->nextqueued; mixer_Buffer *next = src->nextqueued->next; uint8 *d0, *d1, *d2, *d3; /* prev, curr, next, next + 1 */ float t, t2, a, b, c, s0, s1, s2, s3; t = src->count / 65536.0f; t2 = t * t; d1 = curr->data + src->pos; d1 += mixer_SourceAdvance (src, left); if (d1 - curr->sampsize < curr->data) { if (prev && prev->data && prev->size >= curr->sampsize) { d0 = prev->data + prev->size - curr->sampsize; if (!left) d0 += mixer_chansize; } else d0 = d1; } else d0 = d1 - curr->sampsize; if (d1 + curr->sampsize >= curr->data + curr->size) { if (next && next->data && next->size >= curr->sampsize * 2) { d2 = next->data; if (!left) d2 += mixer_chansize; d3 = d2 + curr->sampsize; } else d2 = d3 = d1; } else { d2 = d1 + curr->sampsize; if (d2 + curr->sampsize >= curr->data + curr->size) { if (next && next->data && next->size >= curr->sampsize) { d3 = next->data; if (!left) d3 += mixer_chansize; } else d3 = d2; } else d3 = d2 + curr->sampsize; } s0 = (float)mixer_GetSampleInt (d0, mixer_chansize); s1 = (float)mixer_GetSampleInt (d1, mixer_chansize); s2 = (float)mixer_GetSampleInt (d2, mixer_chansize); s3 = (float)mixer_GetSampleInt (d3, mixer_chansize); a = (3.0f * (s1 - s2) - s0 + s3) * 0.5f; b = 2.0f * s2 + s0 - ((5.0f * s1 + s3) * 0.5f); c = (s2 - s0) * 0.5f; return a * t2 * t + b * t2 + c * t + s1; } /* get next sample from external buffer * in internal format, while performing * convertion if necessary */ static inline sint32 mixer_GetConvSample (uint8 **psrc, uint32 bpc, uint32 flags) { sint32 samp; samp = mixer_GetSampleExt (*psrc, bpc); *psrc += bpc; if (flags & mixConvStereoDown) { /* downmix to mono - average up channels */ samp = (samp + mixer_GetSampleExt (*psrc, bpc)) / 2; *psrc += bpc; } if (flags & mixConvSizeUp) { /* convert S8 to S16 */ samp <<= 8; } else if (flags & mixConvSizeDown) { /* convert S16 to S8 * if arithmetic shift is available to the compiler * it will use it to optimize this */ samp /= 0x100; } return samp; } /* put next sample into an internal buffer * in internal format, while performing * convertion if necessary */ static inline void mixer_PutConvSample (uint8 **pdst, uint32 bpc, uint32 flags, sint32 samp) { mixer_PutSampleInt (*pdst, bpc, samp); *pdst += bpc; if (flags & mixConvStereoUp) { mixer_PutSampleInt (*pdst, bpc, samp); *pdst += bpc; } } /* resampling with respect to sample size only */ static void mixer_ResampleFlat (mixer_Convertion *conv) { mixer_ConvFlags flags = conv->flags; uint8 *src = conv->srcdata; uint8 *dst = conv->dstdata; uint32 srcbpc = conv->srcbpc; uint32 dstbpc = conv->dstbpc; uint32 samples; samples = conv->srcsamples; if ( !(conv->flags & (mixConvStereoUp | mixConvStereoDown))) samples *= conv->srcchans; for (; samples; samples--) { sint32 samp; samp = mixer_GetConvSample (&src, srcbpc, flags); mixer_PutConvSample (&dst, dstbpc, flags, samp); } } uqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/Makeinfo0000600000175000017500000000005710543202037020466 0ustar joeyjoeyuqm_SUBDIRS="sdl nosound" uqm_CFILES="mixer.c" uqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/mixerint.h0000600000175000017500000000634010543202037021023 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Mixer for low-level sound output drivers * Internals */ #ifndef _MIXERINT_H #define _MIXERINT_H #include "port.h" #include "types.h" /************************************************* * Internals */ /* Conversion info types and funcs */ typedef enum { mixConvNone = 0, mixConvStereoUp = 1, mixConvStereoDown = 2, mixConvSizeUp = 4, mixConvSizeDown = 8 } mixer_ConvFlags; typedef struct { uint32 srcfmt; void *srcdata; uint32 srcsize; uint32 srcbpc; /* bytes/sample for 1 chan */ uint32 srcchans; uint32 srcsamples; uint32 dstfmt; void *dstdata; uint32 dstsize; uint32 dstbpc; /* bytes/sample for 1 chan */ uint32 dstchans; uint32 dstsamples; mixer_ConvFlags flags; } mixer_Convertion; typedef struct { float (* Upsample) (mixer_Source *src, bool left); float (* Downsample) (mixer_Source *src, bool left); float (* None) (mixer_Source *src, bool left); } mixer_Resampling; static void mixer_ConvertBuffer_internal (mixer_Convertion *conv); static void mixer_ResampleFlat (mixer_Convertion *conv); static inline sint32 mixer_GetSampleExt (void *src, uint32 bpc); static inline sint32 mixer_GetSampleInt (void *src, uint32 bpc); static inline void mixer_PutSampleInt (void *dst, uint32 bpc, sint32 samp); static inline void mixer_PutSampleExt (void *dst, uint32 bpc, sint32 samp); static float mixer_ResampleNone (mixer_Source *src, bool left); static float mixer_ResampleNearest (mixer_Source *src, bool left); static float mixer_UpsampleLinear (mixer_Source *src, bool left); static float mixer_UpsampleCubic (mixer_Source *src, bool left); /* Source manipulation */ static void mixer_SourceUnqueueAll (mixer_Source *src); static void mixer_SourceStop_internal (mixer_Source *src); static void mixer_SourceRewind_internal (mixer_Source *src); static void mixer_SourceActivate (mixer_Source* src); static void mixer_SourceDeactivate (mixer_Source* src); static inline bool mixer_CheckBufferState (mixer_Buffer *buf, const char* FuncName); /* Clipping boundaries */ #define MIX_S16_MAX ((float) SINT16_MAX) #define MIX_S16_MIN ((float) SINT16_MIN) #define MIX_S8_MAX ((float) SINT8_MAX) #define MIX_S8_MIN ((float) SINT8_MIN) /* Channel gain adjustment for clipping reduction */ #define MIX_GAIN_ADJ (0.75f) /* The Mixer */ static inline bool mixer_SourceGetNextSample (mixer_Source *src, float *psamp, bool left); static inline bool mixer_SourceGetFakeSample (mixer_Source *src, float *psamp, bool left); static inline uint32 mixer_SourceAdvance (mixer_Source *src, bool left); #endif /* _MIXERINT_H */ uqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/nosound/0000755000175000017500000000000010552600275020513 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/nosound/audiodrv_nosound.h0000600000175000017500000000470310543202037024234 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Nosound audio driver */ #ifndef _AUDIODRV_NOSOUND_H #define _AUDIODRV_NOSOUND_H #include "config.h" #include "libs/sound/sound.h" #include "libs/sound/mixer/mixer.h" /* Playback task */ int PlaybackTaskFunc (void *data); /* General */ sint32 noSound_Init (audio_Driver *driver, sint32 flags); void noSound_Uninit (void); sint32 noSound_GetError (void); /* Sources */ void noSound_GenSources (uint32 n, audio_Object *psrcobj); void noSound_DeleteSources (uint32 n, audio_Object *psrcobj); bool noSound_IsSource (audio_Object srcobj); void noSound_Sourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal value); void noSound_Sourcef (audio_Object srcobj, audio_SourceProp pname, float value); void noSound_Sourcefv (audio_Object srcobj, audio_SourceProp pname, float *value); void noSound_GetSourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal *value); void noSound_GetSourcef (audio_Object srcobj, audio_SourceProp pname, float *value); void noSound_SourceRewind (audio_Object srcobj); void noSound_SourcePlay (audio_Object srcobj); void noSound_SourcePause (audio_Object srcobj); void noSound_SourceStop (audio_Object srcobj); void noSound_SourceQueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj); void noSound_SourceUnqueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj); /* Buffers */ void noSound_GenBuffers (uint32 n, audio_Object *pbufobj); void noSound_DeleteBuffers (uint32 n, audio_Object *pbufobj); bool noSound_IsBuffer (audio_Object bufobj); void noSound_GetBufferi (audio_Object bufobj, audio_BufferProp pname, audio_IntVal *value); void noSound_BufferData (audio_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq); #endif /* _AUDIODRV_NOSOUND_H */ uqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/nosound/audiodrv_nosound.c0000600000175000017500000002055410543202037024231 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Nosound audio driver */ #include "audiodrv_nosound.h" #include "libs/tasklib.h" #include "libs/log.h" #include static Task StreamDecoderTask; static Task PlaybackTask; static uint32 nosound_freq = 22050; static const audio_Driver noSound_Driver = { noSound_Uninit, noSound_GetError, audio_DRIVER_NOSOUND, { /* Errors */ MIX_NO_ERROR, MIX_INVALID_NAME, MIX_INVALID_ENUM, MIX_INVALID_VALUE, MIX_INVALID_OPERATION, MIX_OUT_OF_MEMORY, MIX_DRIVER_FAILURE, /* Source properties */ MIX_POSITION, MIX_LOOPING, MIX_BUFFER, MIX_GAIN, MIX_SOURCE_STATE, MIX_BUFFERS_QUEUED, MIX_BUFFERS_PROCESSED, /* Source state information */ MIX_INITIAL, MIX_STOPPED, MIX_PLAYING, MIX_PAUSED, /* Sound buffer properties */ MIX_FREQUENCY, MIX_BITS, MIX_CHANNELS, MIX_SIZE, MIX_FORMAT_MONO16, MIX_FORMAT_STEREO16, MIX_FORMAT_MONO8, MIX_FORMAT_STEREO8 }, /* Sources */ noSound_GenSources, noSound_DeleteSources, noSound_IsSource, noSound_Sourcei, noSound_Sourcef, noSound_Sourcefv, noSound_GetSourcei, noSound_GetSourcef, noSound_SourceRewind, noSound_SourcePlay, noSound_SourcePause, noSound_SourceStop, noSound_SourceQueueBuffers, noSound_SourceUnqueueBuffers, /* Buffers */ noSound_GenBuffers, noSound_DeleteBuffers, noSound_IsBuffer, noSound_GetBufferi, noSound_BufferData }; /* * Initialization */ sint32 noSound_Init (audio_Driver *driver, sint32 flags) { int i; TFB_DecoderFormats formats = { 0, 0, audio_FORMAT_MONO8, audio_FORMAT_STEREO8, audio_FORMAT_MONO16, audio_FORMAT_STEREO16 }; log_add (log_Info, "Using nosound audio driver."); log_add (log_Info, "Initializing mixer."); if (!mixer_Init (nosound_freq, MIX_FORMAT_MAKE (1, 1), MIX_QUALITY_LOW, MIX_FAKE_DATA)) { log_add (log_Error, "Mixer initialization failed: %x", mixer_GetError ()); return -1; } log_add (log_Info, "Mixer initialized."); log_add (log_Info, "Initializing sound decoders."); if (SoundDecoder_Init (flags, &formats)) { log_add (log_Error, "Sound decoders initialization failed."); mixer_Uninit (); return -1; } log_add (log_Info, "Sound decoders initialized."); *driver = noSound_Driver; for (i = 0; i < NUM_SOUNDSOURCES; ++i) { audio_GenSources (1, &soundSource[i].handle); soundSource[i].sample = NULL; soundSource[i].stream_should_be_playing = FALSE; soundSource[i].stream_mutex = CreateMutex ("Nosound stream mutex", SYNC_CLASS_AUDIO); soundSource[i].sbuffer = NULL; soundSource[i].sbuf_start = 0; soundSource[i].sbuf_size = 0; soundSource[i].sbuf_offset = 0; } atexit (unInitAudio); SetSFXVolume (sfxVolumeScale); SetSpeechVolume (speechVolumeScale); SetMusicVolume ((COUNT)musicVolume); StreamDecoderTask = AssignTask (StreamDecoderTaskFunc, 1024, "audio stream decoder"); PlaybackTask = AssignTask (PlaybackTaskFunc, 1024, "nosound audio playback"); return 0; } void noSound_Uninit (void) { int i; if (StreamDecoderTask) { ConcludeTask (StreamDecoderTask); StreamDecoderTask = NULL; } for (i = 0; i < NUM_SOUNDSOURCES; ++i) { if (soundSource[i].sample && soundSource[i].sample->decoder) { StopStream (i); } if (soundSource[i].sbuffer) { void *sbuffer = soundSource[i].sbuffer; soundSource[i].sbuffer = NULL; HFree (sbuffer); } DestroyMutex (soundSource[i].stream_mutex); noSound_DeleteSources (1, &soundSource[i].handle); } if (PlaybackTask) { ConcludeTask (PlaybackTask); PlaybackTask = 0; } mixer_Uninit (); SoundDecoder_Uninit (); } /* * Playback task */ int PlaybackTaskFunc (void *data) { Task task = (Task)data; uint8 *stream; uint32 entryTime; sint32 period, delay; uint32 len = 2048; stream = (uint8 *) HMalloc (len); period = (sint32)((len / (double)nosound_freq) * ONE_SECOND); while (!Task_ReadState (task, TASK_EXIT)) { entryTime = GetTimeCounter (); mixer_MixFake (NULL, stream, len); delay = period - (GetTimeCounter () - entryTime); if (delay > 0) SleepThread (delay); } HFree (stream); FinishTask (task); return 0; } /* * General */ sint32 noSound_GetError (void) { sint32 value = mixer_GetError (); switch (value) { case MIX_NO_ERROR: return audio_NO_ERROR; case MIX_INVALID_NAME: return audio_INVALID_NAME; case MIX_INVALID_ENUM: return audio_INVALID_ENUM; case MIX_INVALID_VALUE: return audio_INVALID_VALUE; case MIX_INVALID_OPERATION: return audio_INVALID_OPERATION; case MIX_OUT_OF_MEMORY: return audio_OUT_OF_MEMORY; default: log_add (log_Debug, "noSound_GetError: unknown value %x", value); return audio_DRIVER_FAILURE; break; } } /* * Sources */ void noSound_GenSources (uint32 n, audio_Object *psrcobj) { mixer_GenSources (n, (mixer_Object *) psrcobj); } void noSound_DeleteSources (uint32 n, audio_Object *psrcobj) { mixer_DeleteSources (n, (mixer_Object *) psrcobj); } bool noSound_IsSource (audio_Object srcobj) { return mixer_IsSource ((mixer_Object) srcobj); } void noSound_Sourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal value) { mixer_Sourcei ((mixer_Object) srcobj, (mixer_SourceProp) pname, (mixer_IntVal) value); } void noSound_Sourcef (audio_Object srcobj, audio_SourceProp pname, float value) { mixer_Sourcef ((mixer_Object) srcobj, (mixer_SourceProp) pname, value); } void noSound_Sourcefv (audio_Object srcobj, audio_SourceProp pname, float *value) { mixer_Sourcefv ((mixer_Object) srcobj, (mixer_SourceProp) pname, value); } void noSound_GetSourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal *value) { mixer_GetSourcei ((mixer_Object) srcobj, (mixer_SourceProp) pname, (mixer_IntVal *) value); if (pname == MIX_SOURCE_STATE) { switch (*value) { case MIX_INITIAL: *value = audio_INITIAL; break; case MIX_STOPPED: *value = audio_STOPPED; break; case MIX_PLAYING: *value = audio_PLAYING; break; case MIX_PAUSED: *value = audio_PAUSED; break; default: log_add (log_Debug, "noSound_GetSourcei(): unknown value %lx", (long int) *value); *value = audio_DRIVER_FAILURE; } } } void noSound_GetSourcef (audio_Object srcobj, audio_SourceProp pname, float *value) { mixer_GetSourcef ((mixer_Object) srcobj, (mixer_SourceProp) pname, value); } void noSound_SourceRewind (audio_Object srcobj) { mixer_SourceRewind ((mixer_Object) srcobj); } void noSound_SourcePlay (audio_Object srcobj) { mixer_SourcePlay ((mixer_Object) srcobj); } void noSound_SourcePause (audio_Object srcobj) { mixer_SourcePause ((mixer_Object) srcobj); } void noSound_SourceStop (audio_Object srcobj) { mixer_SourceStop ((mixer_Object) srcobj); } void noSound_SourceQueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj) { mixer_SourceQueueBuffers ((mixer_Object) srcobj, n, (mixer_Object *) pbufobj); } void noSound_SourceUnqueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj) { mixer_SourceUnqueueBuffers ((mixer_Object) srcobj, n, (mixer_Object *) pbufobj); } /* * Buffers */ void noSound_GenBuffers (uint32 n, audio_Object *pbufobj) { mixer_GenBuffers (n, (mixer_Object *) pbufobj); } void noSound_DeleteBuffers (uint32 n, audio_Object *pbufobj) { mixer_DeleteBuffers (n, (mixer_Object *) pbufobj); } bool noSound_IsBuffer (audio_Object bufobj) { return mixer_IsBuffer ((mixer_Object) bufobj); } void noSound_GetBufferi (audio_Object bufobj, audio_BufferProp pname, audio_IntVal *value) { mixer_GetBufferi ((mixer_Object) bufobj, (mixer_BufferProp) pname, (mixer_IntVal *) value); } void noSound_BufferData (audio_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq) { mixer_BufferData ((mixer_Object) bufobj, format, data, size, freq); } uqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/nosound/Makeinfo0000600000175000017500000000004010543202037022143 0ustar joeyjoeyuqm_CFILES="audiodrv_nosound.c" uqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/sdl/0000755000175000017500000000000010552600275017610 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/sdl/audiodrv_sdl.c0000600000175000017500000002215010543202036022414 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* SDL audio driver */ #include "audiodrv_sdl.h" #include "libs/tasklib.h" #include "libs/log.h" #include static Task StreamDecoderTask; static const audio_Driver mixSDL_Driver = { mixSDL_Uninit, mixSDL_GetError, audio_DRIVER_MIXSDL, { /* Errors */ MIX_NO_ERROR, MIX_INVALID_NAME, MIX_INVALID_ENUM, MIX_INVALID_VALUE, MIX_INVALID_OPERATION, MIX_OUT_OF_MEMORY, MIX_DRIVER_FAILURE, /* Source properties */ MIX_POSITION, MIX_LOOPING, MIX_BUFFER, MIX_GAIN, MIX_SOURCE_STATE, MIX_BUFFERS_QUEUED, MIX_BUFFERS_PROCESSED, /* Source state information */ MIX_INITIAL, MIX_STOPPED, MIX_PLAYING, MIX_PAUSED, /* Sound buffer properties */ MIX_FREQUENCY, MIX_BITS, MIX_CHANNELS, MIX_SIZE, MIX_FORMAT_MONO16, MIX_FORMAT_STEREO16, MIX_FORMAT_MONO8, MIX_FORMAT_STEREO8 }, /* Sources */ mixSDL_GenSources, mixSDL_DeleteSources, mixSDL_IsSource, mixSDL_Sourcei, mixSDL_Sourcef, mixSDL_Sourcefv, mixSDL_GetSourcei, mixSDL_GetSourcef, mixSDL_SourceRewind, mixSDL_SourcePlay, mixSDL_SourcePause, mixSDL_SourceStop, mixSDL_SourceQueueBuffers, mixSDL_SourceUnqueueBuffers, /* Buffers */ mixSDL_GenBuffers, mixSDL_DeleteBuffers, mixSDL_IsBuffer, mixSDL_GetBufferi, mixSDL_BufferData }; /* * Initialization */ sint32 mixSDL_Init (audio_Driver *driver, sint32 flags) { int i; char devicename[256]; SDL_AudioSpec desired, obtained; mixer_Quality quality; TFB_DecoderFormats formats = { MIX_IS_BIG_ENDIAN, MIX_WANT_BIG_ENDIAN, audio_FORMAT_MONO8, audio_FORMAT_STEREO8, audio_FORMAT_MONO16, audio_FORMAT_STEREO16 }; log_add (log_Info, "Initializing SDL audio subsystem."); if ((SDL_InitSubSystem(SDL_INIT_AUDIO)) == -1) { log_add (log_Error, "Couldn't initialize audio subsystem: %s", SDL_GetError()); return -1; } log_add (log_Info, "SDL audio subsystem initialized."); if (flags & audio_QUALITY_HIGH) { quality = MIX_QUALITY_HIGH; desired.freq = 44100; desired.samples = 4096; } else if (flags & audio_QUALITY_LOW) { quality = MIX_QUALITY_LOW; desired.freq = 22050; desired.samples = 2048; } else { quality = MIX_QUALITY_DEFAULT; desired.freq = 44100; desired.samples = 4096; } desired.format = AUDIO_S16SYS; desired.channels = 2; desired.callback = mixer_MixChannels; log_add (log_Info, "Opening SDL audio device."); if (SDL_OpenAudio (&desired, &obtained) < 0) { log_add (log_Error, "Unable to open audio device: %s", SDL_GetError ()); SDL_QuitSubSystem (SDL_INIT_AUDIO); return -1; } if (obtained.format != desired.format || (obtained.channels != 1 && obtained.channels != 2)) { log_add (log_Error, "Unable to obtain desired audio format."); SDL_CloseAudio (); SDL_QuitSubSystem (SDL_INIT_AUDIO); return -1; } SDL_AudioDriverName (devicename, sizeof (devicename)); log_add (log_Info, " using %s at %d Hz 16 bit %s, " "%d samples audio buffer", devicename, obtained.freq, obtained.channels > 1 ? "stereo" : "mono", obtained.samples); log_add (log_Info, "Initializing mixer."); if (!mixer_Init (obtained.freq, MIX_FORMAT_MAKE (2, obtained.channels), quality, 0)) { log_add (log_Error, "Mixer initialization failed: %x", mixer_GetError ()); SDL_CloseAudio (); SDL_QuitSubSystem (SDL_INIT_AUDIO); return -1; } log_add (log_Info, "Mixer initialized."); log_add (log_Info, "Initializing sound decoders."); if (SoundDecoder_Init (flags, &formats)) { log_add (log_Error, "Sound decoders initialization failed."); SDL_CloseAudio (); mixer_Uninit (); SDL_QuitSubSystem (SDL_INIT_AUDIO); return -1; } log_add (log_Info, "Sound decoders initialized."); *driver = mixSDL_Driver; for (i = 0; i < NUM_SOUNDSOURCES; ++i) { audio_GenSources (1, &soundSource[i].handle); soundSource[i].sample = NULL; soundSource[i].stream_should_be_playing = FALSE; soundSource[i].stream_mutex = CreateMutex ("MixSDL stream mutex", SYNC_CLASS_AUDIO); soundSource[i].sbuffer = NULL; soundSource[i].sbuf_start = 0; soundSource[i].sbuf_size = 0; soundSource[i].sbuf_offset = 0; } atexit (unInitAudio); SetSFXVolume (sfxVolumeScale); SetSpeechVolume (speechVolumeScale); SetMusicVolume ((COUNT)musicVolume); StreamDecoderTask = AssignTask (StreamDecoderTaskFunc, 1024, "audio stream decoder"); SDL_PauseAudio (0); return 0; } void mixSDL_Uninit (void) { int i; if (StreamDecoderTask) { ConcludeTask (StreamDecoderTask); StreamDecoderTask = NULL; } for (i = 0; i < NUM_SOUNDSOURCES; ++i) { if (soundSource[i].sample && soundSource[i].sample->decoder) { StopStream (i); } if (soundSource[i].sbuffer) { void *sbuffer = soundSource[i].sbuffer; soundSource[i].sbuffer = NULL; HFree (sbuffer); } DestroyMutex (soundSource[i].stream_mutex); mixSDL_DeleteSources (1, &soundSource[i].handle); } SDL_CloseAudio (); mixer_Uninit (); SoundDecoder_Uninit (); SDL_QuitSubSystem (SDL_INIT_AUDIO); } /* * General */ sint32 mixSDL_GetError (void) { sint32 value = mixer_GetError (); switch (value) { case MIX_NO_ERROR: return audio_NO_ERROR; case MIX_INVALID_NAME: return audio_INVALID_NAME; case MIX_INVALID_ENUM: return audio_INVALID_ENUM; case MIX_INVALID_VALUE: return audio_INVALID_VALUE; case MIX_INVALID_OPERATION: return audio_INVALID_OPERATION; case MIX_OUT_OF_MEMORY: return audio_OUT_OF_MEMORY; default: log_add (log_Debug, "mixSDL_GetError: unknown value %x", value); return audio_DRIVER_FAILURE; break; } } /* * Sources */ void mixSDL_GenSources (uint32 n, audio_Object *psrcobj) { mixer_GenSources (n, (mixer_Object *) psrcobj); } void mixSDL_DeleteSources (uint32 n, audio_Object *psrcobj) { mixer_DeleteSources (n, (mixer_Object *) psrcobj); } bool mixSDL_IsSource (audio_Object srcobj) { return mixer_IsSource ((mixer_Object) srcobj); } void mixSDL_Sourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal value) { mixer_Sourcei ((mixer_Object) srcobj, (mixer_SourceProp) pname, (mixer_IntVal) value); } void mixSDL_Sourcef (audio_Object srcobj, audio_SourceProp pname, float value) { mixer_Sourcef ((mixer_Object) srcobj, (mixer_SourceProp) pname, value); } void mixSDL_Sourcefv (audio_Object srcobj, audio_SourceProp pname, float *value) { mixer_Sourcefv ((mixer_Object) srcobj, (mixer_SourceProp) pname, value); } void mixSDL_GetSourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal *value) { mixer_GetSourcei ((mixer_Object) srcobj, (mixer_SourceProp) pname, (mixer_IntVal *) value); if (pname == MIX_SOURCE_STATE) { switch (*value) { case MIX_INITIAL: *value = audio_INITIAL; break; case MIX_STOPPED: *value = audio_STOPPED; break; case MIX_PLAYING: *value = audio_PLAYING; break; case MIX_PAUSED: *value = audio_PAUSED; break; default: *value = audio_DRIVER_FAILURE; } } } void mixSDL_GetSourcef (audio_Object srcobj, audio_SourceProp pname, float *value) { mixer_GetSourcef ((mixer_Object) srcobj, (mixer_SourceProp) pname, value); } void mixSDL_SourceRewind (audio_Object srcobj) { mixer_SourceRewind ((mixer_Object) srcobj); } void mixSDL_SourcePlay (audio_Object srcobj) { mixer_SourcePlay ((mixer_Object) srcobj); } void mixSDL_SourcePause (audio_Object srcobj) { mixer_SourcePause ((mixer_Object) srcobj); } void mixSDL_SourceStop (audio_Object srcobj) { mixer_SourceStop ((mixer_Object) srcobj); } void mixSDL_SourceQueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj) { mixer_SourceQueueBuffers ((mixer_Object) srcobj, n, (mixer_Object *) pbufobj); } void mixSDL_SourceUnqueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj) { mixer_SourceUnqueueBuffers ((mixer_Object) srcobj, n, (mixer_Object *) pbufobj); } /* * Buffers */ void mixSDL_GenBuffers (uint32 n, audio_Object *pbufobj) { mixer_GenBuffers (n, (mixer_Object *) pbufobj); } void mixSDL_DeleteBuffers (uint32 n, audio_Object *pbufobj) { mixer_DeleteBuffers (n, (mixer_Object *) pbufobj); } bool mixSDL_IsBuffer (audio_Object bufobj) { return mixer_IsBuffer ((mixer_Object) bufobj); } void mixSDL_GetBufferi (audio_Object bufobj, audio_BufferProp pname, audio_IntVal *value) { mixer_GetBufferi ((mixer_Object) bufobj, (mixer_BufferProp) pname, (mixer_IntVal *) value); } void mixSDL_BufferData (audio_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq) { mixer_BufferData ((mixer_Object) bufobj, format, data, size, freq); } uqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/sdl/audiodrv_sdl.h0000600000175000017500000000457710543202037022437 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* SDL audio driver */ #ifndef _AUDIODRV_SDL_H #define _AUDIODRV_SDL_H #include "port.h" #include "libs/sound/sound.h" #include "libs/sound/mixer/mixer.h" #include SDL_INCLUDE(SDL.h) /* General */ sint32 mixSDL_Init (audio_Driver *driver, sint32 flags); void mixSDL_Uninit (void); sint32 mixSDL_GetError (void); /* Sources */ void mixSDL_GenSources (uint32 n, audio_Object *psrcobj); void mixSDL_DeleteSources (uint32 n, audio_Object *psrcobj); bool mixSDL_IsSource (audio_Object srcobj); void mixSDL_Sourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal value); void mixSDL_Sourcef (audio_Object srcobj, audio_SourceProp pname, float value); void mixSDL_Sourcefv (audio_Object srcobj, audio_SourceProp pname, float *value); void mixSDL_GetSourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal *value); void mixSDL_GetSourcef (audio_Object srcobj, audio_SourceProp pname, float *value); void mixSDL_SourceRewind (audio_Object srcobj); void mixSDL_SourcePlay (audio_Object srcobj); void mixSDL_SourcePause (audio_Object srcobj); void mixSDL_SourceStop (audio_Object srcobj); void mixSDL_SourceQueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj); void mixSDL_SourceUnqueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj); /* Buffers */ void mixSDL_GenBuffers (uint32 n, audio_Object *pbufobj); void mixSDL_DeleteBuffers (uint32 n, audio_Object *pbufobj); bool mixSDL_IsBuffer (audio_Object bufobj); void mixSDL_GetBufferi (audio_Object bufobj, audio_BufferProp pname, audio_IntVal *value); void mixSDL_BufferData (audio_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq); #endif /* _AUDIODRV_SDL_H */ uqm-0.6.2/sc2/src/sc2code/libs/sound/mixer/sdl/Makeinfo0000600000175000017500000000003410543202037021243 0ustar joeyjoeyuqm_CFILES="audiodrv_sdl.c" uqm-0.6.2/sc2/src/sc2code/libs/sound/Makeinfo0000600000175000017500000000037310543202040017335 0ustar joeyjoeyif [ "$uqm_SOUNDMODULE" = "openal" ]; then uqm_SUBDIRS="openal mixer decoders" uqm_CFLAGS="$uqm_CFLAGS -DHAVE_OPENAL" else uqm_SUBDIRS="mixer decoders" fi uqm_CFILES="audiocore.c fileinst.c resinst.c sound.c sfx.c music.c stream.c trackplayer.c" uqm-0.6.2/sc2/src/sc2code/libs/sound/openal/0000755000175000017500000000000010552600275017160 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/sound/openal/audiodrv_openal.c0000600000175000017500000002163210543202040022457 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* OpenAL audio driver */ #ifdef HAVE_OPENAL #include "audiodrv_openal.h" #include "libs/tasklib.h" #include "libs/log.h" #include ALCcontext *alcContext = NULL; ALCdevice *alcDevice = NULL; ALfloat defaultPos[] = {0.0f, 0.0f, -1.0f}; ALfloat listenerPos[] = {0.0f, 0.0f, 0.0f}; ALfloat listenerVel[] = {0.0f, 0.0f, 0.0f}; ALfloat listenerOri[] = {0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f}; static Task StreamDecoderTask; static const audio_Driver openAL_Driver = { openAL_Uninit, openAL_GetError, audio_DRIVER_OPENAL, { /* Errors */ AL_FALSE, AL_INVALID_NAME, AL_INVALID_ENUM, AL_INVALID_VALUE, AL_INVALID_OPERATION, AL_OUT_OF_MEMORY, audio_DRIVER_FAILURE, /* Source properties */ AL_POSITION, AL_LOOPING, AL_BUFFER, AL_GAIN, AL_SOURCE_STATE, AL_BUFFERS_QUEUED, AL_BUFFERS_PROCESSED, /* Source state information */ AL_INITIAL, AL_STOPPED, AL_PLAYING, AL_PAUSED, /* Sound buffer properties */ AL_FREQUENCY, AL_BITS, AL_CHANNELS, AL_SIZE, AL_FORMAT_MONO16, AL_FORMAT_STEREO16, AL_FORMAT_MONO8, AL_FORMAT_STEREO8 }, /* Sources */ openAL_GenSources, openAL_DeleteSources, openAL_IsSource, openAL_Sourcei, openAL_Sourcef, openAL_Sourcefv, openAL_GetSourcei, openAL_GetSourcef, openAL_SourceRewind, openAL_SourcePlay, openAL_SourcePause, openAL_SourceStop, openAL_SourceQueueBuffers, openAL_SourceUnqueueBuffers, /* Buffers */ openAL_GenBuffers, openAL_DeleteBuffers, openAL_IsBuffer, openAL_GetBufferi, openAL_BufferData }; /* * Initialization */ sint32 openAL_Init (audio_Driver *driver, sint32 flags) { int i; TFB_DecoderFormats formats = { MIX_IS_BIG_ENDIAN, MIX_WANT_BIG_ENDIAN, audio_FORMAT_MONO8, audio_FORMAT_STEREO8, audio_FORMAT_MONO16, audio_FORMAT_STEREO16 }; log_add (log_Info, "Initializing OpenAL."); #ifdef WIN32 alcDevice = alcOpenDevice ((ALubyte*)"DirectSound3D"); #else alcDevice = alcOpenDevice (NULL); #endif if (!alcDevice) { log_add (log_Error, "Couldn't initialize OpenAL: %d", alcGetError (NULL)); return -1; } *driver = openAL_Driver; atexit (unInitAudio); alcContext = alcCreateContext (alcDevice, NULL); if (!alcContext) { log_add (log_Error, "Couldn't create OpenAL context: %d", alcGetError (alcDevice)); alcCloseDevice (alcDevice); alcDevice = NULL; return -1; } alcMakeContextCurrent (alcContext); log_add (log_Info, "OpenAL initialized.\n" " version: %s\n", " vendor: %s\n", " renderer: %s\n", " device: %s", alGetString (AL_VERSION), alGetString (AL_VENDOR), alGetString (AL_RENDERER), alcGetString (alcDevice, ALC_DEFAULT_DEVICE_SPECIFIER)); //log_add (log_Info, " extensions: %s", alGetString (AL_EXTENSIONS)); log_add (log_Info, "Initializing sound decoders."); if (SoundDecoder_Init (flags, &formats)) { log_add (log_Error, "Sound decoders initialization failed."); alcMakeContextCurrent (NULL); alcDestroyContext (alcContext); alcContext = NULL; alcCloseDevice (alcDevice); alcDevice = NULL; return -1; } log_add (log_Error, "Sound decoders initialized."); alListenerfv (AL_POSITION, listenerPos); alListenerfv (AL_VELOCITY, listenerVel); alListenerfv (AL_ORIENTATION, listenerOri); for (i = 0; i < NUM_SOUNDSOURCES; ++i) { float zero[3] = {0.0f, 0.0f, 0.0f}; alGenSources (1, &soundSource[i].handle); alSourcei (soundSource[i].handle, AL_LOOPING, AL_FALSE); alSourcefv (soundSource[i].handle, AL_POSITION, defaultPos); alSourcefv (soundSource[i].handle, AL_VELOCITY, zero); alSourcefv (soundSource[i].handle, AL_DIRECTION, zero); soundSource[i].sample = NULL; soundSource[i].stream_should_be_playing = FALSE; soundSource[i].stream_mutex = CreateMutex ("OpenAL stream mutex", SYNC_CLASS_AUDIO); soundSource[i].sbuffer = NULL; soundSource[i].sbuf_start = 0; soundSource[i].sbuf_size = 0; soundSource[i].sbuf_offset = 0; } SetSFXVolume (sfxVolumeScale); SetSpeechVolume (speechVolumeScale); SetMusicVolume ((COUNT) musicVolume); if (optStereoSFX) alDistanceModel (AL_INVERSE_DISTANCE); else alDistanceModel (AL_NONE); StreamDecoderTask = AssignTask (StreamDecoderTaskFunc, 1024, "audio stream decoder"); (void) driver; // eat compiler warning return 0; } void openAL_Uninit (void) { int i; if (StreamDecoderTask) { ConcludeTask (StreamDecoderTask); StreamDecoderTask = NULL; } for (i = 0; i < NUM_SOUNDSOURCES; ++i) { if (soundSource[i].sample && soundSource[i].sample->decoder) { StopStream (i); } if (soundSource[i].sbuffer) { void *sbuffer = soundSource[i].sbuffer; soundSource[i].sbuffer = NULL; HFree (sbuffer); } DestroyMutex (soundSource[i].stream_mutex); } alcMakeContextCurrent (NULL); alcDestroyContext (alcContext); alcContext = NULL; alcCloseDevice (alcDevice); alcDevice = NULL; SoundDecoder_Uninit (); } /* * General */ sint32 openAL_GetError (void) { ALint value = alGetError (); switch (value) { case AL_FALSE: return audio_NO_ERROR; case AL_INVALID_NAME: return audio_INVALID_NAME; case AL_INVALID_ENUM: return audio_INVALID_ENUM; case AL_INVALID_VALUE: return audio_INVALID_VALUE; case AL_INVALID_OPERATION: return audio_INVALID_OPERATION; case AL_OUT_OF_MEMORY: return audio_OUT_OF_MEMORY; default: log_add (log_Debug, "openAL_GetError: unknown value %x", value); return audio_DRIVER_FAILURE; break; } } /* * Sources */ void openAL_GenSources (uint32 n, audio_Object *psrcobj) { alGenSources ((ALsizei) n, (ALuint *) psrcobj); } void openAL_DeleteSources (uint32 n, audio_Object *psrcobj) { alDeleteSources ((ALsizei) n, (ALuint *) psrcobj); } bool openAL_IsSource (audio_Object srcobj) { return alIsSource ((ALuint) srcobj); } void openAL_Sourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal value) { alSourcei ((ALuint) srcobj, (ALenum) pname, (ALint) value); } void openAL_Sourcef (audio_Object srcobj, audio_SourceProp pname, float value) { alSourcef ((ALuint) srcobj, (ALenum) pname, (ALfloat) value); } void openAL_Sourcefv (audio_Object srcobj, audio_SourceProp pname, float *value) { alSourcefv ((ALuint) srcobj, (ALenum) pname, (ALfloat *) value); } void openAL_GetSourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal *value) { alGetSourcei ((ALuint) srcobj, (ALenum) pname, (ALint *) value); if (pname == AL_SOURCE_STATE) { switch (*value) { case AL_INITIAL: *value = audio_INITIAL; break; case AL_STOPPED: *value = audio_STOPPED; break; case AL_PLAYING: *value = audio_PLAYING; break; case AL_PAUSED: *value = audio_PAUSED; break; default: log_add (log_Debug, "openAL_GetSourcei(): unknown value %x", *value); *value = audio_DRIVER_FAILURE; } } } void openAL_GetSourcef (audio_Object srcobj, audio_SourceProp pname, float *value) { alGetSourcef ((ALuint) srcobj, (ALenum) pname, (ALfloat *) value); } void openAL_SourceRewind (audio_Object srcobj) { alSourceRewind ((ALuint) srcobj); } void openAL_SourcePlay (audio_Object srcobj) { alSourcePlay ((ALuint) srcobj); } void openAL_SourcePause (audio_Object srcobj) { alSourcePause ((ALuint) srcobj); } void openAL_SourceStop (audio_Object srcobj) { alSourceStop ((ALuint) srcobj); } void openAL_SourceQueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj) { alSourceQueueBuffers ((ALuint) srcobj, (ALsizei) n, (ALuint *) pbufobj); } void openAL_SourceUnqueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj) { alSourceUnqueueBuffers ((ALuint) srcobj, (ALsizei) n, (ALuint *) pbufobj); } /* * Buffers */ void openAL_GenBuffers (uint32 n, audio_Object *pbufobj) { alGenBuffers ((ALsizei) n, (ALuint *) pbufobj); } void openAL_DeleteBuffers (uint32 n, audio_Object *pbufobj) { alDeleteBuffers ((ALsizei) n, (ALuint *) pbufobj); } bool openAL_IsBuffer (audio_Object bufobj) { return alIsBuffer ((ALuint) bufobj); } void openAL_GetBufferi (audio_Object bufobj, audio_BufferProp pname, audio_IntVal *value) { alGetBufferi ((ALuint) bufobj, (ALenum) pname, (ALint *) value); } void openAL_BufferData (audio_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq) { alBufferData ((ALuint) bufobj, (ALenum) format, (ALvoid *) data, (ALsizei) size, (ALsizei) freq); } #endif uqm-0.6.2/sc2/src/sc2code/libs/sound/openal/Makeinfo0000600000175000017500000000003710543202040020610 0ustar joeyjoeyuqm_CFILES="audiodrv_openal.c" uqm-0.6.2/sc2/src/sc2code/libs/sound/openal/audiodrv_openal.h0000600000175000017500000000544510543202040022470 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* OpenAL audio driver */ #ifndef _AUDIODRV_OPENAL_H #define _AUDIODRV_OPENAL_H #include "config.h" #include "libs/sound/sound.h" #include "options.h" #include "endian_uqm.h" #if defined (__APPLE__) # include # include #else # include # include # ifdef _MSC_VER # pragma comment (lib, "OpenAL32.lib") # endif #endif /* This is just a simple endianness setup for decoders */ #ifdef WORDS_BIGENDIAN # define MIX_IS_BIG_ENDIAN true # define MIX_WANT_BIG_ENDIAN true #else # define MIX_IS_BIG_ENDIAN false # define MIX_WANT_BIG_ENDIAN false #endif /* General */ sint32 openAL_Init (audio_Driver *driver, sint32 flags); void openAL_Uninit (void); sint32 openAL_GetError (void); /* Sources */ void openAL_GenSources (uint32 n, audio_Object *psrcobj); void openAL_DeleteSources (uint32 n, audio_Object *psrcobj); bool openAL_IsSource (audio_Object srcobj); void openAL_Sourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal value); void openAL_Sourcef (audio_Object srcobj, audio_SourceProp pname, float value); void openAL_Sourcefv (audio_Object srcobj, audio_SourceProp pname, float *value); void openAL_GetSourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal *value); void openAL_GetSourcef (audio_Object srcobj, audio_SourceProp pname, float *value); void openAL_SourceRewind (audio_Object srcobj); void openAL_SourcePlay (audio_Object srcobj); void openAL_SourcePause (audio_Object srcobj); void openAL_SourceStop (audio_Object srcobj); void openAL_SourceQueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj); void openAL_SourceUnqueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj); /* Buffers */ void openAL_GenBuffers (uint32 n, audio_Object *pbufobj); void openAL_DeleteBuffers (uint32 n, audio_Object *pbufobj); bool openAL_IsBuffer (audio_Object bufobj); void openAL_GetBufferi (audio_Object bufobj, audio_BufferProp pname, audio_IntVal *value); void openAL_BufferData (audio_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq); #endif /* _AUDIODRV_OPENAL_H */ uqm-0.6.2/sc2/src/sc2code/libs/sound/sound.h0000600000175000017500000000567110543202040017170 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UQM_SOUND_H // try avoiding collisions on id #define _UQM_SOUND_H #include "misc.h" #include "libs/strings/strintrn.h" #include "sndintrn.h" #include "audiocore.h" #include "decoders/decoder.h" #include "libs/threadlib.h" #define FIRST_SFX_SOURCE 0 #define LAST_SFX_SOURCE (FIRST_SFX_SOURCE + NUM_SFX_CHANNELS - 1) #define MUSIC_SOURCE (LAST_SFX_SOURCE + 1) #define SPEECH_SOURCE (MUSIC_SOURCE + 1) #define NUM_SOUNDSOURCES (SPEECH_SOURCE + 1) #define PAD_SCOPE_BYTES 8096 typedef struct { int in_use; audio_Object buf_name; void *data; // user-defined data } TFB_SoundTag; // forward-declare typedef struct tfb_soundsample TFB_SoundSample; typedef struct tfb_soundcallbacks { // return TRUE to continue, FALSE to abort bool (* OnStartStream) (TFB_SoundSample*); // return TRUE to continue, FALSE to abort bool (* OnEndChunk) (TFB_SoundSample*, audio_Object); // return TRUE to continue, FALSE to abort void (* OnEndStream) (TFB_SoundSample*); // tagged buffer callback void (* OnTaggedBuffer) (TFB_SoundSample*, TFB_SoundTag*); // buffer just queued void (* OnQueueBuffer) (TFB_SoundSample*, audio_Object); } TFB_SoundCallbacks; // audio data struct tfb_soundsample { TFB_SoundDecoder *decoder; // decoder to read from float length; // total length of decoder chain in seconds audio_Object *buffer; uint32 num_buffers; TFB_SoundTag *buffer_tag; sint32 offset; // initial offset void* data; // user-defined data TFB_SoundCallbacks callbacks; // user-defined callbacks }; // equivalent to channel in legacy sound code typedef struct tfb_soundsource { TFB_SoundSample *sample; audio_Object handle; bool stream_should_be_playing; Mutex stream_mutex; sint32 start_time; void *positional_object; // for oscilloscope void *sbuffer; uint32 sbuf_start; uint32 sbuf_size; uint32 sbuf_offset; uint32 sbuf_lasttime; // keep track for paused tracks uint32 pause_time; } TFB_SoundSource; extern TFB_SoundSource soundSource[]; extern int musicVolume; extern float musicVolumeScale; extern float sfxVolumeScale; extern float speechVolumeScale; void StopSource (int iSource); void CleanSource (int iSource); void SetSFXVolume (float volume); void SetSpeechVolume (float volume); #include "stream.h" #endif // _UQM_SOUND_H uqm-0.6.2/sc2/src/sc2code/libs/sound/trackplayer.h0000600000175000017500000000255010543202040020352 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TRACKPLAYER_H #define TRACKPLAYER_H #include "compiler.h" typedef void (*TFB_TrackCB) (void); #define ACCEL_SCROLL_SPEED 300 void ResumeTrack(void); void PauseTrack(void); COUNT PlayingTrack(void); void JumpTrack(void); void FastForward_Smooth(void); int FastForward_Page(void); void FastReverse_Smooth(void); void FastReverse_Page(void); void StopTrack(void); void SpliceTrack(UNICODE *filespec, UNICODE *textspec, UNICODE *TimeStamp, TFB_TrackCB cb); void SpliceMultiTrack (UNICODE *TrackNames[], UNICODE *TrackText); int GetSoundData (void *data); int GetSoundInfo (int max_len); #endif uqm-0.6.2/sc2/src/sc2code/libs/sound/stream.h0000600000175000017500000000243610543202040017327 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef STREAM_H #define STREAM_H void PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope, bool rewind); void StopStream (uint32 source); void PauseStream (uint32 source); void ResumeStream (uint32 source); void SeekStream (uint32 source, uint32 pos); BOOLEAN PlayingStream (uint32 source); int StreamDecoderTaskFunc (void *data); TFB_SoundTag* FindTaggedBuffer (TFB_SoundSample* sample, audio_Object buffer); void TFB_ClearBufferTag (TFB_SoundTag* ptag); void TFB_TagBuffer (TFB_SoundSample* sample, audio_Object buffer, void* data); #endif uqm-0.6.2/sc2/src/sc2code/libs/sound/sfx.c0000600000175000017500000001735210543202040016632 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "options.h" #include "sound.h" #include "libs/reslib.h" #include "libs/log.h" #include static void CheckFinishedChannels (void); void PlayChannel (COUNT channel, PVOID sample, SoundPosition pos, void *positional_object, unsigned char priority) { TFB_SoundSample *tfb_sample = *(TFB_SoundSample**) sample; StopSource (channel); // all finished (stopped) channels can be cleaned up at this point // since this is the only func that can initiate an sfx sound CheckFinishedChannels (); soundSource[channel].sample = tfb_sample; soundSource[channel].positional_object = positional_object; if (optStereoSFX) UpdateSoundPosition (channel, pos); audio_Sourcei (soundSource[channel].handle, audio_BUFFER, tfb_sample->buffer[0]); audio_SourcePlay (soundSource[channel].handle); (void) priority; } void StopChannel (COUNT channel, unsigned char Priority) { StopSource (channel); (void)Priority; // ignored } static void CheckFinishedChannels (void) { int i; for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i) { audio_IntVal state; audio_GetSourcei (soundSource[i].handle, audio_SOURCE_STATE, &state); if (state == audio_STOPPED) { CleanSource (i); // and if it failed... we still dont care audio_GetError(); } } } BOOLEAN ChannelPlaying (COUNT WhichChannel) { audio_IntVal state; audio_GetSourcei (soundSource[WhichChannel].handle, audio_SOURCE_STATE, &state); if (state == audio_PLAYING) return TRUE; return FALSE; } void * GetPositionalObject (COUNT channel) { return soundSource[channel].positional_object; } void SetPositionalObject (COUNT channel, void *positional_object) { soundSource[channel].positional_object = positional_object; } void UpdateSoundPosition (COUNT channel, SoundPosition pos) { const float ATTENUATION = 160.0f; const float MIN_DISTANCE = 0.5f; float fpos[3]; if (pos.positional) { float dist; fpos[0] = pos.x / ATTENUATION; fpos[1] = 0.0f; fpos[2] = pos.y / ATTENUATION; dist = (float) sqrt (fpos[0] * fpos[0] + fpos[2] * fpos[2]); if (dist < MIN_DISTANCE) { // object is too close to listener // move it away along the same vector float scale = MIN_DISTANCE / dist; fpos[0] *= scale; fpos[2] *= scale; } audio_Sourcefv (soundSource[channel].handle, audio_POSITION, fpos); //log_add (log_Debug, "UpdateSoundPosition(): channel %d, pos %d %d, posobj %x", // channel, pos.x, pos.y, (unsigned int)soundSource[channel].positional_object); } else { fpos[0] = fpos[1] = 0.0f; fpos[2] = -1.0f; audio_Sourcefv (soundSource[channel].handle, audio_POSITION, fpos); } } void SetChannelVolume (COUNT channel, COUNT volume, BYTE priority) // I wonder what this whole priority business is... // I can probably ignore it. { audio_Sourcef (soundSource[channel].handle, audio_GAIN, (volume / (float)MAX_VOLUME) * sfxVolumeScale); (void)priority; // ignored } // Status: Ignored PBYTE GetSampleAddress (SOUND sound) // I might be prototyping this wrong, type-wise. { return ((PBYTE)GetSoundAddress (sound)); } // Status: Ignored COUNT GetSampleLength (SOUND sound) { (void)sound; return 0; } // Status: Ignored void SetChannelRate (COUNT channel, DWORD rate_hz, unsigned char priority) { (void) channel; (void) rate_hz; (void) priority; } // Status: Ignored COUNT GetSampleRate (SOUND sound) { (void) sound; return 0; } MEM_HANDLE _GetSoundBankData (uio_Stream *fp, DWORD length) { int snd_ct, n; DWORD opos; char CurrentLine[1024], filename[1024]; #define MAX_FX 256 TFB_SoundSample *sndfx[MAX_FX]; STRING_TABLE Snd; (void) length; // ignored opos = uio_ftell (fp); { char *s1, *s2; if (_cur_resfile_name == 0 || (((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0) && (s2 = strrchr (_cur_resfile_name, '\\')) == 0)) n = 0; else { if (s2 > s1) s1 = s2; n = s1 - _cur_resfile_name + 1; strncpy (filename, _cur_resfile_name, n); } } snd_ct = 0; while (uio_fgets (CurrentLine, sizeof (CurrentLine), fp) && snd_ct < MAX_FX) { if (sscanf(CurrentLine, "%s", &filename[n]) == 1) { log_add (log_Info, "_GetSoundBankData(): loading %s", filename); sndfx[snd_ct] = (TFB_SoundSample *) HCalloc (sizeof (TFB_SoundSample)); sndfx[snd_ct]->decoder = SoundDecoder_Load (contentDir, filename, 4096, 0, 0); if (!sndfx[snd_ct]->decoder) { log_add (log_Warning, "_GetSoundBankData(): couldn't load %s", filename); HFree (sndfx[snd_ct]); } else { uint32 decoded_bytes; decoded_bytes = SoundDecoder_DecodeAll (sndfx[snd_ct]->decoder); log_add (log_Info, "_GetSoundBankData(): decoded_bytes %d", decoded_bytes); sndfx[snd_ct]->num_buffers = 1; sndfx[snd_ct]->buffer = (audio_Object *) HMalloc ( sizeof (audio_Object) * sndfx[snd_ct]->num_buffers); audio_GenBuffers (sndfx[snd_ct]->num_buffers, sndfx[snd_ct]->buffer); audio_BufferData (sndfx[snd_ct]->buffer[0], sndfx[snd_ct]->decoder->format, sndfx[snd_ct]->decoder->buffer, decoded_bytes, sndfx[snd_ct]->decoder->frequency); SoundDecoder_Free (sndfx[snd_ct]->decoder); sndfx[snd_ct]->decoder = NULL; ++snd_ct; } } else { log_add (log_Warning, "_GetSoundBankData: Bad file!"); } // pkunk insult fix 2002/11/12 (ftell shouldn't be needed for loop to terminate) /*if (uio_ftell (fp) - opos >= length) break;*/ } Snd = 0; if (snd_ct && (Snd = AllocStringTable ( sizeof (STRING_TABLE_DESC) + (sizeof (DWORD) * snd_ct) + (sizeof (sndfx[0]) * snd_ct) ))) { STRING_TABLEPTR fxTab; LockStringTable (Snd, &fxTab); if (fxTab == 0) { while (snd_ct--) { if (sndfx[snd_ct]->decoder) SoundDecoder_Free (sndfx[snd_ct]->decoder); HFree (sndfx[snd_ct]); } FreeStringTable (Snd); Snd = 0; } else { DWORD *offs, StringOffs; fxTab->StringCount = snd_ct; fxTab->flags = 0; offs = fxTab->StringOffsets; StringOffs = sizeof (STRING_TABLE_DESC) + (sizeof (DWORD) * snd_ct); memcpy ((BYTE *)fxTab + StringOffs, sndfx, sizeof (sndfx[0]) * snd_ct); do { *offs++ = StringOffs; StringOffs += sizeof (sndfx[0]); } while (snd_ct--); UnlockStringTable (Snd); } } return ((MEM_HANDLE)Snd); } BOOLEAN _ReleaseSoundBankData (MEM_HANDLE Snd) { STRING_TABLEPTR fxTab; LockStringTable (Snd, &fxTab); if (fxTab) { int snd_ct; TFB_SoundSample **sptr; snd_ct = fxTab->StringCount; sptr = (TFB_SoundSample **)((BYTE *)fxTab + fxTab->StringOffsets[0]); while (snd_ct--) { int i; for (i = 0; i < NUM_SOUNDSOURCES; ++i) { if (soundSource[i].sample == (*sptr)) { StopSource (i); soundSource[i].sample = NULL; } } if ((*sptr)->decoder) SoundDecoder_Free ((*sptr)->decoder); audio_DeleteBuffers ((*sptr)->num_buffers, (*sptr)->buffer); HFree ((*sptr)->buffer); if ((*sptr)->buffer_tag) HFree ((*sptr)->buffer_tag); HFree (*sptr); *sptr++ = 0; } UnlockStringTable (Snd); FreeStringTable (Snd); return (TRUE); } return (FALSE); } BOOLEAN DestroySound(SOUND_REF target) { return _ReleaseSoundBankData ((MEM_HANDLE) target); } uqm-0.6.2/sc2/src/sc2code/libs/sound/audiocore.c0000600000175000017500000001071210543202040017775 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Audio Core API (derived from OpenAL) */ #include #include #include "audiocore.h" #include "libs/log.h" static audio_Driver audiodrv; /* The globals that control the sound drivers. */ int snddriver, soundflags; /* * Declarations for driver init funcs */ #ifdef HAVE_OPENAL sint32 openAL_Init (audio_Driver *driver, sint32 flags); #endif sint32 mixSDL_Init (audio_Driver *driver, sint32 flags); sint32 noSound_Init (audio_Driver *driver, sint32 flags); /* * Initialization */ sint32 initAudio (sint32 driver, sint32 flags) { sint32 ret; #ifdef HAVE_OPENAL if (driver == audio_DRIVER_MIXSDL) ret = mixSDL_Init (&audiodrv, flags); else if (driver == audio_DRIVER_OPENAL) ret = openAL_Init (&audiodrv, flags); else ret = noSound_Init (&audiodrv, flags); #else if (driver == audio_DRIVER_OPENAL) { log_add (log_Warning, "OpenAL driver not compiled in, so using MixSDL"); driver = audio_DRIVER_MIXSDL; } if (driver == audio_DRIVER_MIXSDL) ret = mixSDL_Init (&audiodrv, flags); else ret = noSound_Init (&audiodrv, flags); #endif if (ret != 0) { log_add (log_Fatal, "Sound driver initialization failed.\n" "This may happen when a soundcard is " "not present or not available.\n" "NOTICE: Try running UQM with '--sound=none' option"); exit (EXIT_FAILURE); } return ret; } void unInitAudio (void) { audiodrv.Uninitialize (); } /* * General */ sint32 audio_GetError (void) { return audiodrv.GetError (); } /* * Sources */ void audio_GenSources (uint32 n, audio_Object *psrcobj) { audiodrv.GenSources (n, psrcobj); } void audio_DeleteSources (uint32 n, audio_Object *psrcobj) { audiodrv.DeleteSources (n, psrcobj); } bool audio_IsSource (audio_Object srcobj) { return audiodrv.IsSource (srcobj); } void audio_Sourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal value) { audiodrv.Sourcei (srcobj, audiodrv.EnumLookup[pname], value); } void audio_Sourcef (audio_Object srcobj, audio_SourceProp pname, float value) { audiodrv.Sourcef (srcobj, audiodrv.EnumLookup[pname], value); } void audio_Sourcefv (audio_Object srcobj, audio_SourceProp pname, float *value) { audiodrv.Sourcefv (srcobj, audiodrv.EnumLookup[pname], value); } void audio_GetSourcei (audio_Object srcobj, audio_SourceProp pname, audio_IntVal *value) { audiodrv.GetSourcei (srcobj, audiodrv.EnumLookup[pname], value); } void audio_GetSourcef (audio_Object srcobj, audio_SourceProp pname, float *value) { audiodrv.GetSourcef (srcobj, audiodrv.EnumLookup[pname], value); } void audio_SourceRewind (audio_Object srcobj) { audiodrv.SourceRewind (srcobj); } void audio_SourcePlay (audio_Object srcobj) { audiodrv.SourcePlay (srcobj); } void audio_SourcePause (audio_Object srcobj) { audiodrv.SourcePause (srcobj); } void audio_SourceStop (audio_Object srcobj) { audiodrv.SourceStop (srcobj); } void audio_SourceQueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj) { audiodrv.SourceQueueBuffers (srcobj, n, pbufobj); } void audio_SourceUnqueueBuffers (audio_Object srcobj, uint32 n, audio_Object* pbufobj) { audiodrv.SourceUnqueueBuffers (srcobj, n, pbufobj); } /* * Buffers */ void audio_GenBuffers (uint32 n, audio_Object *pbufobj) { audiodrv.GenBuffers (n, pbufobj); } void audio_DeleteBuffers (uint32 n, audio_Object *pbufobj) { audiodrv.DeleteBuffers (n, pbufobj); } bool audio_IsBuffer (audio_Object bufobj) { return audiodrv.IsBuffer (bufobj); } void audio_GetBufferi (audio_Object bufobj, audio_BufferProp pname, audio_IntVal *value) { audiodrv.GetBufferi (bufobj, audiodrv.EnumLookup[pname], value); } void audio_BufferData (audio_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq) { audiodrv.BufferData (bufobj, audiodrv.EnumLookup[format], data, size, freq); } uqm-0.6.2/sc2/src/sc2code/libs/log/0000755000175000017500000000000010552600274015332 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/log/uqmlog.h0000644000175000017500000000332510552135700017007 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UQMLOG_H #define _UQMLOG_H #include "port.h" #include "types.h" #include #include extern void log_init (int max_lines); extern void log_initThreads (void); extern int log_exit (int code); extern FILE * log_setOutput (FILE *out); // sets the new output stream and returns the previous one extern void log_setLevel (int level); extern void log_showBox (bool show, bool err); extern void log_captureLines (int num); #define LOG_CAPTURE_ALL 1000000 // unreasonably big number typedef enum { log_Nothing = 0, log_User, log_Fatal = log_User, log_Error, log_Warning, log_Info, log_Debug, log_All, } log_Level; extern void log_add (log_Level, const char *fmt, ...) PRINTF_FUNCTION(2, 3); extern void log_addV (log_Level, const char *fmt, va_list) VPRINTF_FUNCTION(2); extern void log_add_nothread (log_Level, const char *fmt, ...) PRINTF_FUNCTION(2, 3); extern void log_add_nothreadV (log_Level, const char *fmt, va_list) VPRINTF_FUNCTION(2); #endif /* _UQMLOG_H */ uqm-0.6.2/sc2/src/sc2code/libs/log/Makeinfo0000644000175000017500000000002610552135700017001 0ustar joeyjoeyuqm_CFILES="uqmlog.c" uqm-0.6.2/sc2/src/sc2code/libs/log/uqmlog.c0000644000175000017500000001542010552135700017001 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "uqmlog.h" #include #include #include #include #include #include #include "libs/threadlib.h" #ifndef MAX_LOG_ENTRY_SIZE # define MAX_LOG_ENTRY_SIZE 256 #endif #ifndef MAX_LOG_ENTRIES # define MAX_LOG_ENTRIES 128 #endif typedef char log_Entry[MAX_LOG_ENTRY_SIZE]; // static buffers in case we run out of memory static log_Entry queue[MAX_LOG_ENTRIES]; static log_Entry msgNoThread; static char msgBuf[16384]; static int maxLevel = log_Error; static int maxStreamLevel = log_Debug; static int maxDisp = 10; static int qtotal = 0; static int qhead = 0; static int qtail = 0; static volatile bool noThreadReady = false; static bool showBox = true; static bool errorBox = true; static FILE *streamOut; static volatile int qlock = 0; static Mutex qmutex; static void exitCallback (void); static void displayLog (bool isError); static void displayBox (const char *title, bool isError, const char *msg); static void lockQueue (void) { if (!qlock) return; LockMutex (qmutex); } static void unlockQueue (void) { if (!qlock) return; UnlockMutex (qmutex); } static void removeExcess (int room) { room = maxDisp - room; if (room < 0) room = 0; for ( ; qtotal > room; --qtotal, ++qtail) ; qtail %= MAX_LOG_ENTRIES; } static int acquireSlot (void) { int slot; lockQueue (); removeExcess (1); slot = qhead; qhead = (qhead + 1) % MAX_LOG_ENTRIES; ++qtotal; unlockQueue (); return slot; } // queues the non-threaded message when present static void queueNonThreaded (void) { int slot; // This is not perfect. A race condition still exists // between buffering the no-thread message and setting // the noThreadReady flag. Neither does this prevent // the fully or partially overwritten message (by // another competing thread). But it is 'good enough' if (!noThreadReady) return; noThreadReady = false; slot = acquireSlot (); memcpy (queue[slot], msgNoThread, sizeof (msgNoThread)); } void log_init (int max_lines) { int i; maxDisp = max_lines; streamOut = stderr; // pre-term queue strings for (i = 0; i < MAX_LOG_ENTRIES; ++i) queue[i][MAX_LOG_ENTRY_SIZE - 1] = '\0'; msgBuf[sizeof (msgBuf) - 1] = '\0'; msgNoThread[sizeof (msgNoThread) - 1] = '\0'; // install exit handlers atexit (exitCallback); } void log_initThreads (void) { qmutex = CreateMutex ("Logging Lock", SYNC_CLASS_RESOURCE); qlock = 1; } int log_exit (int code) { showBox = false; if (qlock) { qlock = 0; DestroyMutex (qmutex); } return code; } void log_setLevel (int level) { maxLevel = level; //maxStreamLevel = level; } FILE * log_setOutput (FILE *out) { FILE *old = streamOut; streamOut = out; return old; } void log_addV (log_Level level, const char *fmt, va_list list) { log_Entry full_msg; vsnprintf (full_msg, sizeof (full_msg) - 1, fmt, list); full_msg[sizeof (full_msg) - 1] = '\0'; if ((int)level <= maxStreamLevel) { fprintf (streamOut, "%s\n", full_msg); } if ((int)level <= maxLevel) { int slot; queueNonThreaded (); slot = acquireSlot (); memcpy (queue[slot], full_msg, sizeof (queue[0])); } } void log_add (log_Level level, const char *fmt, ...) { va_list list; va_start (list, fmt); log_addV (level, fmt, list); va_end (list); } // non-threaded version of 'add' // uses single-instance static storage with entry into the // queue delayed until the next threaded 'add' or 'exit' void log_add_nothreadV (log_Level level, const char *fmt, va_list list) { log_Entry full_msg; vsnprintf (full_msg, sizeof (full_msg) - 1, fmt, list); full_msg[sizeof (full_msg) - 1] = '\0'; if ((int)level <= maxStreamLevel) { fprintf (streamOut, "%s\n", full_msg); } if ((int)level <= maxLevel) { memcpy (msgNoThread, full_msg, sizeof (msgNoThread)); noThreadReady = true; } } void log_add_nothread (log_Level level, const char *fmt, ...) { va_list list; va_start (list, fmt); log_add_nothreadV (level, fmt, list); va_end (list); } void log_showBox (bool show, bool err) { showBox = show; errorBox = err; } // sets the maximum log lines captured for the final // display to the user on failure exit void log_captureLines (int num) { if (num > MAX_LOG_ENTRIES) num = MAX_LOG_ENTRIES; if (num < 1) num = 1; maxDisp = num; // remove any extra lines already on queue lockQueue (); removeExcess (0); unlockQueue (); } static void exitCallback (void) { if (showBox) displayLog (errorBox); log_exit (0); } static void displayLog (bool isError) { char *p = msgBuf; int left = sizeof (msgBuf) - 1; int len; int ptr; if (isError) { strcpy (p, "The Ur-Quan Masters encountered a fatal error.\n" "Part of the log follows:\n\n"); len = strlen (p); p += len; left -= len; } // Glue the log entries together // Locking is not a good idea at this point and we do not // really need it -- the worst that can happen is we get // an extra or an incomplete message for (ptr = qtail; ptr != qhead && left > 0; ptr = (ptr + 1) % MAX_LOG_ENTRIES) { len = strlen (queue[ptr]) + 1; if (len > left) len = left; memcpy (p, queue[ptr], len); p[len - 1] = '\n'; p += len; left -= len; } // Glue the non-threaded message if present if (noThreadReady) { noThreadReady = false; len = strlen (msgNoThread); if (len > left) len = left; memcpy (p, msgNoThread, len); p += len; left -= len; } *p = '\0'; displayBox ("The Ur-Quan Masters", isError, msgBuf); } #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) extern int __stdcall MessageBoxA (void *hWnd, const char* lpText, const char* lpCaption, uint32 uType); #define MB_ICONEXCLAMATION 0x00000030L #define MB_ICONASTERISK 0x00000040L static void displayBox (const char *title, bool isError, const char *msg) { MessageBoxA (0, msg, title, isError ? MB_ICONEXCLAMATION : MB_ICONASTERISK); } #elif defined(__APPLE__) static void displayBox (const char *title, bool isError, const char *msg) { // do something here } #else static void displayBox (const char *title, bool isError, const char *msg) { // do nothing here } #endif /* OS disjunction */ uqm-0.6.2/sc2/src/sc2code/libs/input/0000755000175000017500000000000010552600274015710 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/input/input_common.h0000600000175000017500000000200710543202043020547 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INPUT_COMMON_H #define INPUT_COMMON_H // driver for TFB_InitInput enum { TFB_INPUTDRIVER_SDL }; // flags for TFB_InitInput //#define TFB_INPUTFLAGS_ETC (1<<0) int TFB_InitInput (int driver, int flags); void TFB_UninitInput (void); #endif uqm-0.6.2/sc2/src/sc2code/libs/input/inpintrn.h0000600000175000017500000000154410543202043017706 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _INPINTRN_H #define _INPINTRN_H #include "inplib.h" #endif /* _INPINTRN_H */ uqm-0.6.2/sc2/src/sc2code/libs/input/input_common.c0000600000175000017500000000157310543202043020551 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "port.h" #include "input_common.h" #include "inpintrn.h" volatile BOOLEAN ExitRequested, GamePaused; uqm-0.6.2/sc2/src/sc2code/libs/input/Makeinfo0000600000175000017500000000005610543202043017345 0ustar joeyjoeyuqm_SUBDIRS="sdl" uqm_CFILES="input_common.c" uqm-0.6.2/sc2/src/sc2code/libs/input/sdl/0000755000175000017500000000000010552600274016472 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/input/sdl/input.c0000644000175000017500000003506310552045506020005 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include #include #include "libs/graphics/sdl/sdl_common.h" #include "libs/input/input_common.h" #include "libs/input/sdl/vcontrol.h" #include "libs/input/sdl/keynames.h" #include "misc.h" #include "controls.h" #include "libs/file.h" #include "libs/log.h" #include "libs/reslib.h" #include "options.h" #define KBDBUFSIZE (1 << 8) static int kbdhead=0, kbdtail=0; static wchar_t kbdbuf[KBDBUFSIZE]; static wchar_t lastchar; static int num_keys = 0; static int *kbdstate = NULL; // Holds all SDL keys +1 for holding invalid values static BOOLEAN InputInitialized = FALSE; static BOOLEAN _in_character_mode = FALSE; #define VCONTROL_VERSION 4 static VControl_NameBinding control_names[] = { { "Menu-Up", (int *)&ImmediateInputState.menu[KEY_MENU_UP] }, { "Menu-Down", (int *)&ImmediateInputState.menu[KEY_MENU_DOWN] }, { "Menu-Left", (int *)&ImmediateInputState.menu[KEY_MENU_LEFT] }, { "Menu-Right", (int *)&ImmediateInputState.menu[KEY_MENU_RIGHT] }, { "Menu-Select", (int *)&ImmediateInputState.menu[KEY_MENU_SELECT] }, { "Menu-Cancel", (int *)&ImmediateInputState.menu[KEY_MENU_CANCEL] }, { "Menu-Special", (int *)&ImmediateInputState.menu[KEY_MENU_SPECIAL] }, { "Menu-Page-Up", (int *)&ImmediateInputState.menu[KEY_MENU_PAGE_UP] }, { "Menu-Page-Down", (int *)&ImmediateInputState.menu[KEY_MENU_PAGE_DOWN] }, { "Menu-Home", (int *)&ImmediateInputState.menu[KEY_MENU_HOME] }, { "Menu-End", (int *)&ImmediateInputState.menu[KEY_MENU_END] }, { "Menu-Zoom-In", (int *)&ImmediateInputState.menu[KEY_MENU_ZOOM_IN] }, { "Menu-Zoom-Out", (int *)&ImmediateInputState.menu[KEY_MENU_ZOOM_OUT] }, { "Menu-Delete", (int *)&ImmediateInputState.menu[KEY_MENU_DELETE] }, { "Menu-Backspace", (int *)&ImmediateInputState.menu[KEY_MENU_BACKSPACE] }, { "Menu-Edit-Cancel", (int *)&ImmediateInputState.menu[KEY_MENU_EDIT_CANCEL] }, { "Menu-Search", (int *)&ImmediateInputState.menu[KEY_MENU_SEARCH] }, { "Menu-Next", (int *)&ImmediateInputState.menu[KEY_MENU_NEXT] }, { "Template-1-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_UP] }, { "Template-1-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_DOWN] }, { "Template-1-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_LEFT] }, { "Template-1-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_RIGHT] }, { "Template-1-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_WEAPON] }, { "Template-1-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_SPECIAL] }, { "Template-1-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_1][KEY_ESCAPE] }, { "Template-2-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_UP] }, { "Template-2-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_DOWN] }, { "Template-2-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_LEFT] }, { "Template-2-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_RIGHT] }, { "Template-2-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_WEAPON] }, { "Template-2-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_SPECIAL] }, { "Template-2-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_2][KEY_ESCAPE] }, { "Template-3-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_UP] }, { "Template-3-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_DOWN] }, { "Template-3-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_LEFT] }, { "Template-3-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_RIGHT] }, { "Template-3-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_WEAPON] }, { "Template-3-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_SPECIAL] }, { "Template-3-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_KB_3][KEY_ESCAPE] }, { "Template-4-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_UP] }, { "Template-4-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_DOWN] }, { "Template-4-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_LEFT] }, { "Template-4-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_RIGHT] }, { "Template-4-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_WEAPON] }, { "Template-4-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_SPECIAL] }, { "Template-4-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_1][KEY_ESCAPE] }, { "Template-5-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_UP] }, { "Template-5-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_DOWN] }, { "Template-5-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_LEFT] }, { "Template-5-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_RIGHT] }, { "Template-5-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_WEAPON] }, { "Template-5-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_SPECIAL] }, { "Template-5-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_2][KEY_ESCAPE] }, { "Template-6-Up", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_UP] }, { "Template-6-Down", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_DOWN] }, { "Template-6-Left", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_LEFT] }, { "Template-6-Right", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_RIGHT] }, { "Template-6-Weapon", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_WEAPON] }, { "Template-6-Special", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_SPECIAL] }, { "Template-6-Escape", (int *)&ImmediateInputState.key[CONTROL_TEMPLATE_JOY_3][KEY_ESCAPE] }, { "Pause", (int *)&ImmediateInputState.menu[KEY_PAUSE] }, { "Exit", (int *)&ImmediateInputState.menu[KEY_EXIT] }, { "Abort", (int *)&ImmediateInputState.menu[KEY_ABORT] }, { "Debug", (int *)&ImmediateInputState.menu[KEY_DEBUG] }, { "Illegal", NULL}}; static void initKeyConfig (void) { uio_Stream *fp; int i, errors; for (i = 0; i < 2; ++i) { if ((fp = res_OpenResFile (configDir, "keys.cfg", "rt")) == NULL) { if (copyFile (contentDir, "starcon.key", configDir, "keys.cfg") == -1) { log_add (log_Fatal, "Error: Could not copy default key config " "to user config dir: %s.", strerror (errno)); exit (EXIT_FAILURE); } log_add (log_Info, "Copying default key config file to user " "config dir."); if ((fp = res_OpenResFile (configDir, "keys.cfg", "rt")) == NULL) { log_add (log_Fatal, "Error: Could not open keys.cfg"); exit (EXIT_FAILURE); } } errors = VControl_ReadConfiguration (fp); res_CloseResFile (fp); if (errors || (VControl_GetConfigFileVersion () != VCONTROL_VERSION)) { bool do_rename = false; if (errors) log_add (log_Warning, "%d errors encountered in key configuration file.", errors); if (VControl_GetValidCount () == 0) { log_add (log_Error, "\nI didn't understand a single line in your configuration file."); log_add (log_Error, "This is likely because you're still using a 0.2 era or earlier keys.cfg."); do_rename = true; } if (VControl_GetConfigFileVersion () != VCONTROL_VERSION) { log_add (log_Error, "\nThe control scheme for UQM has changed since you last updated keys.cfg."); log_add (log_Error, "(I'm using control scheme version %d, while your config file appears to be\nfor version %d.)", VCONTROL_VERSION, VControl_GetConfigFileVersion ()); do_rename = true; } if (do_rename) { log_add (log_Error, "\nRenaming keys.cfg to keys.old and retrying."); if (fileExists2 (configDir, "keys.old")) uio_unlink (configDir, "keys.old"); if ((uio_rename (configDir, "keys.cfg", configDir, "keys.old")) == -1) { log_add (log_Fatal, "Error: Renaming failed!"); log_add (log_Fatal, "You must delete keys.cfg manually before you can run the game."); exit (EXIT_FAILURE); } continue; } log_add (log_Fatal, "\nRepair your keys.cfg file to continue."); exit (EXIT_FAILURE); } return; } log_add (log_Fatal, "Error: Something went wrong and we were looping again and again so aborting."); log_add (log_Fatal, "Possible cause is your content dir not being up-to-date."); exit (EXIT_FAILURE); } static void resetKeyboardState (void) { memset (kbdstate, 0, sizeof (int) * num_keys); ImmediateInputState.menu[KEY_MENU_ANY] = 0; } int TFB_InitInput (int driver, int flags) { int i; int nJoysticks; (void)driver; (void)flags; GamePaused = ExitRequested = FALSE; SDL_EnableUNICODE(1); (void)SDL_GetKeyState (&num_keys); kbdstate = (int *)HMalloc (sizeof (int) * (num_keys + 1)); #ifdef HAVE_JOYSTICK if ((SDL_InitSubSystem(SDL_INIT_JOYSTICK)) == -1) { log_add (log_Fatal, "Couldn't initialize joystick subsystem: %s", SDL_GetError()); exit (EXIT_FAILURE); } log_add (log_Info, "%i joysticks were found.", SDL_NumJoysticks ()); nJoysticks = SDL_NumJoysticks (); if (nJoysticks > 0) { log_add (log_Info, "The names of the joysticks are:"); for (i = 0; i < nJoysticks; i++) { log_add (log_Info, " %s", SDL_JoystickName (i)); } SDL_JoystickEventState (SDL_ENABLE); } #endif /* HAVE_JOYSTICK */ _in_character_mode = FALSE; resetKeyboardState (); /* Prepare the Virtual Controller system. */ VControl_Init (); VControl_RegisterNameTable (control_names); initKeyConfig (); VControl_ResetInput (); InputInitialized = TRUE; atexit (TFB_UninitInput); return 0; } void TFB_UninitInput (void) { VControl_Uninit (); HFree (kbdstate); } // XXX: not currently used -- character mode is always on void EnableCharacterMode (void) { kbdhead = kbdtail = 0; lastchar = 0; _in_character_mode = TRUE; VControl_ResetInput (); } // XXX: not currently used -- character mode is always on void DisableCharacterMode (void) { VControl_ResetInput (); _in_character_mode = FALSE; kbdhead = kbdtail = 0; lastchar = 0; } wchar_t GetNextCharacter (void) { wchar_t result; if (kbdhead == kbdtail) return 0; result = kbdbuf[kbdhead]; kbdhead = (kbdhead + 1) & (KBDBUFSIZE - 1); return result; } wchar_t GetLastCharacter (void) { return lastchar; } volatile int MouseButtonDown = 0; void ProcessMouseEvent (const SDL_Event *e) { switch (e->type) { case SDL_MOUSEBUTTONDOWN: MouseButtonDown = 1; break; case SDL_MOUSEBUTTONUP: MouseButtonDown = 0; break; default: break; } } void ProcessInputEvent (const SDL_Event *Event) { if (!InputInitialized) return; ProcessMouseEvent (Event); VControl_HandleEvent (Event); if (Event->type == SDL_KEYDOWN || Event->type == SDL_KEYUP) { // process character input event, if any SDLKey k = Event->key.keysym.sym; wchar_t map_key = Event->key.keysym.unicode; if (k < 0 || k > num_keys) k = num_keys; // for unknown keys if (Event->type == SDL_KEYDOWN) { int newtail; // dont care about the non-printable, non-char if (!map_key) return; kbdstate[k]++; newtail = (kbdtail + 1) & (KBDBUFSIZE - 1); // ignore the char if the buffer is full if (newtail != kbdhead) { kbdbuf[kbdtail] = map_key; kbdtail = newtail; lastchar = map_key; ImmediateInputState.menu[KEY_MENU_ANY]++; } } else if (Event->type == SDL_KEYUP) { if (kbdstate[k] == 0) { // something is fishy -- better to reset the // repeatable state to avoid big problems ImmediateInputState.menu[KEY_MENU_ANY] = 0; } else { kbdstate[k]--; if (ImmediateInputState.menu[KEY_MENU_ANY] > 0) ImmediateInputState.menu[KEY_MENU_ANY]--; } } } } void TFB_ResetControls (void) { VControl_ResetInput (); resetKeyboardState (); // flush character buffer kbdhead = kbdtail = 0; lastchar = 0; } void FlushInput (void) { TFB_ResetControls (); FlushInputState (); } void InterrogateInputState (int template, int control, int index, char *buffer, int maxlen) { int i; VCONTROL_GESTURE g; VControl_StartIter (&ImmediateInputState.key[template][control]); i = 0; while (VControl_NextBinding (&g)) { if (i++ < index) { continue; } switch (g.type) { case VCONTROL_KEY: snprintf (buffer, maxlen, "%s", VControl_code2name (g.gesture.key)); buffer[maxlen-1] = 0; break; case VCONTROL_JOYBUTTON: snprintf (buffer, maxlen, "[J%d B%d]", g.gesture.button.port, g.gesture.button.index + 1); buffer[maxlen-1] = 0; break; case VCONTROL_JOYAXIS: snprintf (buffer, maxlen, "[J%d A%d %c]", g.gesture.axis.port, g.gesture.axis.index, g.gesture.axis.polarity > 0 ? '+' : '-'); break; case VCONTROL_JOYHAT: snprintf (buffer, maxlen, "[J%d H%d %d]", g.gesture.hat.port, g.gesture.hat.index, g.gesture.hat.dir); break; default: /* Something we don't handle yet */ buffer[0] = 0; break; } return; } /* There aren't that many bindings, so return blank string */ buffer[0] = 0; } void RemoveInputState (int template, int control, int index) { int i; VCONTROL_GESTURE g; VControl_StartIter (&ImmediateInputState.key[template][control]); i = 0; while (VControl_NextBinding (&g)) { if (i++ < index) { continue; } VControl_RemoveGestureBinding (&g, &ImmediateInputState.key[template][control]); return; } /* No such gesture! */ return; } void RebindInputState (int template, int control, int index) { SDL_Event e; /* Remove the old binding on this spot */ RemoveInputState (template, control, index); /* Wait for the next interesting bit of user input */ VControl_ClearEvent (); while (!VControl_GetLastEvent (&e)) { TaskSwitch (); } /* And now, add the new binding. */ VControl_AddBinding (&e, &ImmediateInputState.key[template][control]); } void SaveKeyConfiguration (uio_DirHandle *path, const char *fname) { uio_Stream *f; f = res_OpenResFile (path, fname, "wb"); if (f) { VControl_Dump (f); res_CloseResFile (f); } } #endif uqm-0.6.2/sc2/src/sc2code/libs/input/sdl/keynames.c0000600000175000017500000001126710543202043020441 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "port.h" #include SDL_INCLUDE(SDL.h) #include #include "keynames.h" /* This code is adapted from the code in SDL_keysym.h. Though this * would almost certainly be fast if we were to use a direct char * * array, this technique permits us to be independent of the actual * character encoding to keysyms. */ /* These names are case-insensitive when compared, but we format * them to look pretty when output */ /* This version of Virtual Controller does not support SDLK_WORLD_* * keysyms or the Num/Caps/ScrollLock keys. SDL treats locking keys * specially, and we cannot treat them as normal keys. Pain, * tragedy. */ typedef struct vcontrol_keyname { /* const */ char *name; int code; } keyname; static keyname keynames[] = { {"Backspace", SDLK_BACKSPACE}, {"Tab", SDLK_TAB}, {"Clear", SDLK_CLEAR}, {"Return", SDLK_RETURN}, {"Pause", SDLK_PAUSE}, {"Escape", SDLK_ESCAPE}, {"Space", SDLK_SPACE}, {"!", SDLK_EXCLAIM}, {"\"", SDLK_QUOTEDBL}, {"Hash", SDLK_HASH}, {"$", SDLK_DOLLAR}, {"&", SDLK_AMPERSAND}, {"'", SDLK_QUOTE}, {"(", SDLK_LEFTPAREN}, {")", SDLK_RIGHTPAREN}, {"*", SDLK_ASTERISK}, {"+", SDLK_PLUS}, {",", SDLK_COMMA}, {"-", SDLK_MINUS}, {".", SDLK_PERIOD}, {"/", SDLK_SLASH}, {"0", SDLK_0}, {"1", SDLK_1}, {"2", SDLK_2}, {"3", SDLK_3}, {"4", SDLK_4}, {"5", SDLK_5}, {"6", SDLK_6}, {"7", SDLK_7}, {"8", SDLK_8}, {"9", SDLK_9}, {":", SDLK_COLON}, {";", SDLK_SEMICOLON}, {"<", SDLK_LESS}, {"=", SDLK_EQUALS}, {">", SDLK_GREATER}, {"?", SDLK_QUESTION}, {"@", SDLK_AT}, {"[", SDLK_LEFTBRACKET}, {"\\", SDLK_BACKSLASH}, {"]", SDLK_RIGHTBRACKET}, {"^", SDLK_CARET}, {"_", SDLK_UNDERSCORE}, {"`", SDLK_BACKQUOTE}, {"a", SDLK_a}, {"b", SDLK_b}, {"c", SDLK_c}, {"d", SDLK_d}, {"e", SDLK_e}, {"f", SDLK_f}, {"g", SDLK_g}, {"h", SDLK_h}, {"i", SDLK_i}, {"j", SDLK_j}, {"k", SDLK_k}, {"l", SDLK_l}, {"m", SDLK_m}, {"n", SDLK_n}, {"o", SDLK_o}, {"p", SDLK_p}, {"q", SDLK_q}, {"r", SDLK_r}, {"s", SDLK_s}, {"t", SDLK_t}, {"u", SDLK_u}, {"v", SDLK_v}, {"w", SDLK_w}, {"x", SDLK_x}, {"y", SDLK_y}, {"z", SDLK_z}, {"Delete", SDLK_DELETE}, {"Keypad-0", SDLK_KP0}, {"Keypad-1", SDLK_KP1}, {"Keypad-2", SDLK_KP2}, {"Keypad-3", SDLK_KP3}, {"Keypad-4", SDLK_KP4}, {"Keypad-5", SDLK_KP5}, {"Keypad-6", SDLK_KP6}, {"Keypad-7", SDLK_KP7}, {"Keypad-8", SDLK_KP8}, {"Keypad-9", SDLK_KP9}, {"Keypad-.", SDLK_KP_PERIOD}, {"Keypad-/", SDLK_KP_DIVIDE}, {"Keypad-*", SDLK_KP_MULTIPLY}, {"Keypad--", SDLK_KP_MINUS}, {"Keypad-+", SDLK_KP_PLUS}, {"Keypad-Enter", SDLK_KP_ENTER}, {"Keypad-=", SDLK_KP_EQUALS}, {"Up", SDLK_UP}, {"Down", SDLK_DOWN}, {"Right", SDLK_RIGHT}, {"Left", SDLK_LEFT}, {"Insert", SDLK_INSERT}, {"Home", SDLK_HOME}, {"End", SDLK_END}, {"PageUp", SDLK_PAGEUP}, {"PageDown", SDLK_PAGEDOWN}, {"F1", SDLK_F1}, {"F2", SDLK_F2}, {"F3", SDLK_F3}, {"F4", SDLK_F4}, {"F5", SDLK_F5}, {"F6", SDLK_F6}, {"F7", SDLK_F7}, {"F8", SDLK_F8}, {"F9", SDLK_F9}, {"F10", SDLK_F10}, {"F11", SDLK_F11}, {"F12", SDLK_F12}, {"F13", SDLK_F13}, {"F14", SDLK_F14}, {"F15", SDLK_F15}, {"RightShift", SDLK_RSHIFT}, {"LeftShift", SDLK_LSHIFT}, {"RightControl", SDLK_RCTRL}, {"LeftControl", SDLK_LCTRL}, {"RightAlt", SDLK_RALT}, {"LeftAlt", SDLK_LALT}, {"RightMeta", SDLK_RMETA}, {"LeftMeta", SDLK_LMETA}, {"RightSuper", SDLK_RSUPER}, {"LeftSuper", SDLK_LSUPER}, {"AltGr", SDLK_MODE}, {"Compose", SDLK_COMPOSE}, {"Help", SDLK_HELP}, {"Print", SDLK_PRINT}, {"SysReq", SDLK_SYSREQ}, {"Break", SDLK_BREAK}, {"Menu", SDLK_MENU}, {"Power", SDLK_POWER}, {"Euro", SDLK_EURO}, {"Undo", SDLK_UNDO}, {"Unknown", 0}}; /* Last element must have code zero */ char * VControl_code2name (int code) { int i = 0; while (1) { int test = keynames[i].code; if (test == code || !test) { return keynames[i].name; } ++i; } } int VControl_name2code (char *name) { int i = 0; while (1) { char *test = keynames[i].name; int code = keynames[i].code; if (!stricmp(test, name) || !code) { return code; } ++i; } } uqm-0.6.2/sc2/src/sc2code/libs/input/sdl/vcontrol_malloc.h0000600000175000017500000000154110543202043022021 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* re-#define these to use your own allocators. */ #include "misc.h" #define vctrl_malloc HMalloc #define vctrl_free HFree uqm-0.6.2/sc2/src/sc2code/libs/input/sdl/keynames.h0000600000175000017500000000153110543202043020437 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _KEYNAMES_H_ #define _KEYNAMES_H_ char *VControl_code2name (int code); int VControl_name2code (char *code); #endif uqm-0.6.2/sc2/src/sc2code/libs/input/sdl/vcontrol.h0000600000175000017500000001052110543202043020470 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _VCONTROL_H_ #define _VCONTROL_H_ #include "port.h" #include "libs/uio.h" #include SDL_INCLUDE(SDL.h) /* Initialization routines */ void VControl_Init (void); void VControl_Uninit (void); /* Structures for representing actual VControl Inputs. Returned by iterators and used to construct bindings. */ typedef enum { VCONTROL_KEY, VCONTROL_JOYAXIS, VCONTROL_JOYBUTTON, VCONTROL_JOYHAT, NUM_VCONTROL_GESTURES } VCONTROL_GESTURE_TYPE; typedef struct { VCONTROL_GESTURE_TYPE type; union { SDLKey key; struct { int port, index, polarity; } axis; struct { int port, index; } button; struct { int port, index; Uint8 dir; } hat; } gesture; } VCONTROL_GESTURE; /* Control of bindings */ int VControl_AddBinding (SDL_Event *e, int *target); void VControl_RemoveBinding (SDL_Event *e, int *target); int VControl_AddGestureBinding (VCONTROL_GESTURE *g, int *target); void VControl_RemoveGestureBinding (VCONTROL_GESTURE *g, int *target); int VControl_AddKeyBinding (SDLKey symbol, int *target); void VControl_RemoveKeyBinding (SDLKey symbol, int *target); int VControl_AddJoyAxisBinding (int port, int axis, int polarity, int *target); void VControl_RemoveJoyAxisBinding (int port, int axis, int polarity, int *target); int VControl_SetJoyThreshold (int port, int threshold); int VControl_AddJoyButtonBinding (int port, int button, int *target); void VControl_RemoveJoyButtonBinding (int port, int button, int *target); int VControl_AddJoyHatBinding (int port, int which, Uint8 dir, int *target); void VControl_RemoveJoyHatBinding (int port, int which, Uint8 dir, int *target); void VControl_RemoveAllBindings (void); /* The listener. Routines besides HandleEvent may be used to 'fake' inputs without * fabricating an SDL_Event. */ void VControl_HandleEvent (const SDL_Event *e); void VControl_ProcessKeyDown (SDLKey symbol); void VControl_ProcessKeyUp (SDLKey symbol); void VControl_ProcessJoyButtonDown (int port, int button); void VControl_ProcessJoyButtonUp (int port, int button); void VControl_ProcessJoyAxis (int port, int axis, int value); void VControl_ProcessJoyHat (int port, int which, Uint8 value); /* Force the input into the blank state. For preventing "sticky" keys. */ void VControl_ResetInput (void); /* Name control. To provide a table of names and bindings, declare * a persistent, unchanging array of VControl_NameBinding and end it * with a {0, 0} entry. Pass this array to VControl_RegisterNameTable. * Only one name table may be registered at a time; subsequent calls * replace the previous values. */ typedef struct vcontrol_namebinding { char *name; int *target; } VControl_NameBinding; void VControl_RegisterNameTable (VControl_NameBinding *table); /* Version number control */ int VControl_GetConfigFileVersion (void); void VControl_SetConfigFileVersion (int v); /* Dump a configuration file corresponding to the current bindings and names. */ void VControl_Dump (uio_Stream *out); void VControl_SaveFilename (uio_DirHandle *path, const char *fname); /* Read a configuration file. Returns number of errors encountered. */ int VControl_ReadConfiguration (uio_Stream *in); int VControl_GetErrorCount (void); int VControl_GetValidCount (void); /* Iterator control. Start an iteration with StartIter or StartIterByName; then call NextBindingName until it returns 0. Produces gestures. */ void VControl_StartIter (int *target); void VControl_StartIterByName (char *targetname); int VControl_NextBinding (VCONTROL_GESTURE *gesture); /* Tracking the "last interesting event." Used to poll to find new control keys. */ void VControl_ClearEvent (void); int VControl_GetLastEvent (SDL_Event *e); #endif uqm-0.6.2/sc2/src/sc2code/libs/input/sdl/vcontrol.c0000644000175000017500000010766710552045506020526 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "port.h" #include SDL_INCLUDE(SDL.h) #include #include #include #include "vcontrol.h" #include "vcontrol_malloc.h" #include "keynames.h" #include "libs/log.h" #include "libs/reslib.h" /* How many binding slots are allocated at once. */ #define POOL_CHUNK_SIZE 64 typedef struct vcontrol_keybinding { int *target; struct vcontrol_keypool *parent; struct vcontrol_keybinding *next; } keybinding; typedef struct vcontrol_keypool { keybinding pool[POOL_CHUNK_SIZE]; int remaining; struct vcontrol_keypool *next; } keypool; #ifdef HAVE_JOYSTICK typedef struct vcontrol_joystick_axis { keybinding *neg, *pos; int polarity; } axis_type; typedef struct vcontrol_joystick_hat { keybinding *left, *right, *up, *down; Uint8 last; } hat_type; typedef struct vcontrol_joystick { SDL_Joystick *stick; int numaxes, numbuttons, numhats; int threshold; axis_type *axes; keybinding **buttons; hat_type *hats; } joystick; static joystick *joysticks; #endif /* HAVE_JOYSTICK */ static int joycount; static int num_sdl_keys = 0; static keybinding **bindings = NULL; static keypool *pool; static VControl_NameBinding *nametable; /* Statistics variables - set by VControl_ReadConfiguration */ static int version, errors, validlines; /* Iterator temp variables */ static int *iter_target; static int iter_device, iter_index; /* Last interesting event */ static int event_ready; static SDL_Event last_interesting; static keypool * allocate_key_chunk (void) { keypool *x = vctrl_malloc (sizeof (keypool)); if (x) { int i; x->remaining = POOL_CHUNK_SIZE; x->next = NULL; for (i = 0; i < POOL_CHUNK_SIZE; i++) { x->pool[i].target = NULL; x->pool[i].next = NULL; x->pool[i].parent = x; } } return x; } static void free_key_pool (keypool *x) { if (x) { free_key_pool (x->next); vctrl_free (x); } } #ifdef HAVE_JOYSTICK static void create_joystick (int index) { SDL_Joystick *stick; int axes, buttons, hats; if (index >= joycount) { log_add (log_Warning, "VControl warning: Tried to open a non-existent joystick!"); return; } if (joysticks[index].stick) { // Joystick is already created. Return. return; } stick = SDL_JoystickOpen (index); if (stick) { joystick *x = &joysticks[index]; int j; log_add (log_Info, "VControl opened joystick: %s", SDL_JoystickName (index)); axes = SDL_JoystickNumAxes (stick); buttons = SDL_JoystickNumButtons (stick); hats = SDL_JoystickNumHats (stick); log_add (log_Info, "%d axes, %d buttons, %d hats.", axes, buttons, hats); x->numaxes = axes; x->numbuttons = buttons; x->numhats = hats; x->axes = vctrl_malloc (sizeof (axis_type) * axes); x->buttons = vctrl_malloc (sizeof (keybinding *) * buttons); x->hats = vctrl_malloc (sizeof (hat_type) * hats); for (j = 0; j < axes; j++) { x->axes[j].neg = x->axes[j].pos = NULL; } for (j = 0; j < hats; j++) { x->hats[j].left = x->hats[j].right = NULL; x->hats[j].up = x->hats[j].down = NULL; x->hats[j].last = SDL_HAT_CENTERED; } for (j = 0; j < buttons; j++) { x->buttons[j] = NULL; } x->stick = stick; } else { log_add (log_Warning, "VControl: Could not initialize joystick #%d", index); } } static void destroy_joystick (int index) { SDL_Joystick *stick = joysticks[index].stick; if (stick) { SDL_JoystickClose (stick); joysticks[index].stick = NULL; vctrl_free (joysticks[index].axes); vctrl_free (joysticks[index].buttons); vctrl_free (joysticks[index].hats); joysticks[index].numaxes = joysticks[index].numbuttons = 0; joysticks[index].axes = NULL; joysticks[index].buttons = NULL; joysticks[index].hats = NULL; } } #endif /* HAVE_JOYSTICK */ static void key_init (void) { int i; pool = allocate_key_chunk (); (void)SDL_GetKeyState (&num_sdl_keys); bindings = (keybinding **) vctrl_malloc (sizeof (keybinding *) * num_sdl_keys); for (i = 0; i < num_sdl_keys; i++) bindings[i] = NULL; #ifdef HAVE_JOYSTICK /* Prepare for possible joystick controls. We don't actually GRAB joysticks unless we're asked to make a joystick binding, though. */ joycount = SDL_NumJoysticks (); if (joycount) { joysticks = vctrl_malloc (sizeof (joystick) * joycount); for (i = 0; i < joycount; i++) { joysticks[i].stick = NULL; joysticks[i].numaxes = joysticks[i].numbuttons = 0; joysticks[i].axes = NULL; joysticks[i].buttons = NULL; } } else { joysticks = NULL; } #else joycount = 0; #endif /* HAVE_JOYSTICK */ } static void key_uninit (void) { int i; free_key_pool (pool); for (i = 0; i < num_sdl_keys; i++) bindings[i] = NULL; vctrl_free (bindings); pool = NULL; #ifdef HAVE_JOYSTICK for (i = 0; i < joycount; i++) destroy_joystick (i); vctrl_free (joysticks); #endif /* HAVE_JOYSTICK */ } static void name_init (void) { nametable = NULL; } static void name_uninit (void) { nametable = NULL; } void VControl_Init (void) { key_init (); name_init (); } void VControl_Uninit (void) { key_uninit (); name_uninit (); } int VControl_SetJoyThreshold (int port, int threshold) { #ifdef HAVE_JOYSTICK if (port >= 0 && port < joycount) { joysticks[port].threshold = threshold; return 0; } else #endif /* HAVE_JOYSTICK */ { // log_add (log_Warning, "VControl_SetJoyThreshold passed illegal port %d", port); return -1; } } static void add_binding (keybinding **newptr, int *target) { keybinding *newbinding; keypool *searchbase; int i; /* Acquire a pointer to the keybinding * that we'll be * overwriting. Along the way, ensure we haven't already * bound this symbol to this target. If we have, return.*/ while (*newptr != NULL) { if ((*newptr)->target == target) { return; } newptr = &((*newptr)->next); } /* Now hunt through the binding pool for a free binding. */ /* First, find a chunk with free spots in it */ searchbase = pool; while (searchbase->remaining == 0) { /* If we're completely full, allocate a new chunk */ if (searchbase->next == NULL) { searchbase->next = allocate_key_chunk (); } searchbase = searchbase->next; } /* Now find a free binding within it */ newbinding = NULL; for (i = 0; i < POOL_CHUNK_SIZE; i++) { if (searchbase->pool[i].target == NULL) { newbinding = &searchbase->pool[i]; break; } } /* Sanity check. */ if (!newbinding) { log_add (log_Warning, "add_binding failed to find a free binding slot!"); return; } newbinding->target = target; newbinding->next = NULL; *newptr = newbinding; searchbase->remaining--; } static void remove_binding (keybinding **ptr, int *target) { if (!(*ptr)) { /* Nothing bound to symbol; return. */ return; } else if ((*ptr)->target == target) { keybinding *todel = *ptr; *ptr = todel->next; todel->target = NULL; todel->next = NULL; todel->parent->remaining++; } else { keybinding *prev = *ptr; while (prev && prev->next != NULL) { if (prev->next->target == target) { keybinding *todel = prev->next; prev->next = todel->next; todel->target = NULL; todel->next = NULL; todel->parent->remaining++; } prev = prev->next; } } } static void activate (keybinding *i) { while (i != NULL) { *(i->target) = *(i->target)+1; i = i->next; } } static void deactivate (keybinding *i) { while (i != NULL) { if (*(i->target) > 0) { *(i->target) = *(i->target)-1; } i = i->next; } } int VControl_AddBinding (SDL_Event *e, int *target) { int result; switch (e->type) { case SDL_KEYDOWN: result = VControl_AddKeyBinding (e->key.keysym.sym, target); break; #ifdef HAVE_JOYSTICK case SDL_JOYAXISMOTION: result = VControl_AddJoyAxisBinding (e->jaxis.which, e->jaxis.axis, (e->jaxis.value < 0) ? -1 : 1, target); break; case SDL_JOYHATMOTION: result = VControl_AddJoyHatBinding (e->jhat.which, e->jhat.hat, e->jhat.value, target); break; case SDL_JOYBUTTONDOWN: result = VControl_AddJoyButtonBinding (e->jbutton.which, e->jbutton.button, target); break; #endif /* HAVE_JOYSTICK */ default: log_add (log_Warning, "VControl_AddBinding didn't understand argument event"); result = -1; break; } return result; } void VControl_RemoveBinding (SDL_Event *e, int *target) { switch (e->type) { case SDL_KEYDOWN: VControl_RemoveKeyBinding (e->key.keysym.sym, target); break; #ifdef HAVE_JOYSTICK case SDL_JOYAXISMOTION: VControl_RemoveJoyAxisBinding (e->jaxis.which, e->jaxis.axis, (e->jaxis.value < 0) ? -1 : 1, target); break; case SDL_JOYHATMOTION: VControl_RemoveJoyHatBinding (e->jhat.which, e->jhat.hat, e->jhat.value, target); break; case SDL_JOYBUTTONDOWN: VControl_RemoveJoyButtonBinding (e->jbutton.which, e->jbutton.button, target); break; #endif /* HAVE_JOYSTICK */ default: log_add (log_Warning, "VControl_RemoveBinding didn't understand argument event"); break; } } int VControl_AddGestureBinding (VCONTROL_GESTURE *g, int *target) { int result; switch (g->type) { case VCONTROL_KEY: result = VControl_AddKeyBinding (g->gesture.key, target); break; #ifdef HAVE_JOYSTICK case VCONTROL_JOYAXIS: result = VControl_AddJoyAxisBinding (g->gesture.axis.port, g->gesture.axis.index, (g->gesture.axis.polarity < 0) ? -1 : 1, target); break; case VCONTROL_JOYHAT: result = VControl_AddJoyHatBinding (g->gesture.hat.port, g->gesture.hat.index, g->gesture.hat.dir, target); break; case VCONTROL_JOYBUTTON: result = VControl_AddJoyButtonBinding (g->gesture.button.port, g->gesture.button.index, target); break; #endif /* HAVE_JOYSTICK */ default: log_add (log_Warning, "VControl_AddGestureBinding didn't understand argument gesture"); result = -1; break; } return result; } void VControl_RemoveGestureBinding (VCONTROL_GESTURE *g, int *target) { switch (g->type) { case VCONTROL_KEY: VControl_RemoveKeyBinding (g->gesture.key, target); break; #ifdef HAVE_JOYSTICK case VCONTROL_JOYAXIS: VControl_RemoveJoyAxisBinding (g->gesture.axis.port, g->gesture.axis.index, (g->gesture.axis.polarity < 0) ? -1 : 1, target); break; case VCONTROL_JOYHAT: VControl_RemoveJoyHatBinding (g->gesture.hat.port, g->gesture.hat.index, g->gesture.hat.dir, target); break; case VCONTROL_JOYBUTTON: VControl_RemoveJoyButtonBinding (g->gesture.button.port, g->gesture.button.index, target); break; #endif /* HAVE_JOYSTICK */ default: log_add (log_Warning, "VControl_RemoveGestureBinding didn't understand argument gesture"); break; } } int VControl_AddKeyBinding (SDLKey symbol, int *target) { if ((symbol < 0) || (symbol >= num_sdl_keys)) { log_add (log_Warning, "VControl: Illegal key index %d", symbol); return -1; } add_binding(&bindings[symbol], target); return 0; } void VControl_RemoveKeyBinding (SDLKey symbol, int *target) { if ((symbol < 0) || (symbol >= num_sdl_keys)) { log_add (log_Warning, "VControl: Illegal key index %d", symbol); return; } remove_binding (&bindings[symbol], target); } int VControl_AddJoyAxisBinding (int port, int axis, int polarity, int *target) { #ifdef HAVE_JOYSTICK if (port >= 0 && port < joycount) { joystick *j = &joysticks[port]; if (!(j->stick)) create_joystick (port); if ((axis >= 0) && (axis < j->numaxes)) { if (polarity < 0) { add_binding(&joysticks[port].axes[axis].neg, target); } else if (polarity > 0) { add_binding(&joysticks[port].axes[axis].pos, target); } else { log_add (log_Debug, "VControl: Attempted to bind to polarity zero"); return -1; } } else { // log_add (log_Debug, "VControl: Attempted to bind to illegal axis %d", axis); return -1; } } else #endif /* HAVE_JOYSTICK */ { // log_add (log_Debug, "VControl: Attempted to bind to illegal port %d", port); return -1; } return 0; } void VControl_RemoveJoyAxisBinding (int port, int axis, int polarity, int *target) { #ifdef HAVE_JOYSTICK if (port >= 0 && port < joycount) { joystick *j = &joysticks[port]; if (!(j->stick)) create_joystick (port); if ((axis >= 0) && (axis < j->numaxes)) { if (polarity < 0) { remove_binding(&joysticks[port].axes[axis].neg, target); } else if (polarity > 0) { remove_binding(&joysticks[port].axes[axis].pos, target); } else { log_add (log_Debug, "VControl: Attempted to unbind from polarity zero"); } } else { log_add (log_Debug, "VControl: Attempted to unbind from illegal axis %d", axis); } } else #endif /* HAVE_JOYSTICK */ { log_add (log_Debug, "VControl: Attempted to unbind from illegal port %d", port); } } int VControl_AddJoyButtonBinding (int port, int button, int *target) { #ifdef HAVE_JOYSTICK if (port >= 0 && port < joycount) { joystick *j = &joysticks[port]; if (!(j->stick)) create_joystick (port); if ((button >= 0) && (button < j->numbuttons)) { add_binding(&joysticks[port].buttons[button], target); return 0; } else { // log_add (log_Debug, "VControl: Attempted to bind to illegal button %d", button); return -1; } } else #endif /* HAVE_JOYSTICK */ { // log_add (log_Debug, "VControl: Attempted to bind to illegal port %d", port); return -1; } } void VControl_RemoveJoyButtonBinding (int port, int button, int *target) { #ifdef HAVE_JOYSTICK if (port >= 0 && port < joycount) { joystick *j = &joysticks[port]; if (!(j->stick)) create_joystick (port); if ((button >= 0) && (button < j->numbuttons)) { remove_binding (&joysticks[port].buttons[button], target); } else { log_add (log_Debug, "VControl: Attempted to unbind from illegal button %d", button); } } else #endif /* HAVE_JOYSTICK */ { log_add (log_Debug, "VControl: Attempted to unbind from illegal port %d", port); } } int VControl_AddJoyHatBinding (int port, int which, Uint8 dir, int *target) { #ifdef HAVE_JOYSTICK if (port >= 0 && port < joycount) { joystick *j = &joysticks[port]; if (!(j->stick)) create_joystick (port); if ((which >= 0) && (which < j->numhats)) { if (dir == SDL_HAT_LEFT) { add_binding(&joysticks[port].hats[which].left, target); } else if (dir == SDL_HAT_RIGHT) { add_binding(&joysticks[port].hats[which].right, target); } else if (dir == SDL_HAT_UP) { add_binding(&joysticks[port].hats[which].up, target); } else if (dir == SDL_HAT_DOWN) { add_binding(&joysticks[port].hats[which].down, target); } else { // log_add (log_Debug, "VControl: Attempted to bind to illegal direction"); return -1; } return 0; } else { // log_add (log_Debug, "VControl: Attempted to bind to illegal hat %d", which); return -1; } } else #endif /* HAVE_JOYSTICK */ { // log_add (log_Debug, "VControl: Attempted to bind to illegal port %d", port); return -1; } } void VControl_RemoveJoyHatBinding (int port, int which, Uint8 dir, int *target) { #ifdef HAVE_JOYSTICK if (port >= 0 && port < joycount) { joystick *j = &joysticks[port]; if (!(j->stick)) create_joystick (port); if ((which >= 0) && (which < j->numhats)) { if (dir == SDL_HAT_LEFT) { remove_binding(&joysticks[port].hats[which].left, target); } else if (dir == SDL_HAT_RIGHT) { remove_binding(&joysticks[port].hats[which].right, target); } else if (dir == SDL_HAT_UP) { remove_binding(&joysticks[port].hats[which].up, target); } else if (dir == SDL_HAT_DOWN) { remove_binding(&joysticks[port].hats[which].down, target); } else { log_add (log_Debug, "VControl: Attempted to unbind from illegal direction"); } } else { log_add (log_Debug, "VControl: Attempted to unbind from illegal hat %d", which); } } else #endif /* HAVE_JOYSTICK */ { log_add (log_Debug, "VControl: Attempted to unbind from illegal port %d", port); } } void VControl_RemoveAllBindings () { key_uninit (); key_init (); } void VControl_ProcessKeyDown (SDLKey symbol) { if ((symbol < 0) || (symbol >= num_sdl_keys)) { log_add (log_Warning, "VControl: Got unknown key index %d", symbol); return; } activate (bindings[symbol]); } void VControl_ProcessKeyUp (SDLKey symbol) { if ((symbol < 0) || (symbol >= num_sdl_keys)) return; deactivate (bindings[symbol]); } void VControl_ProcessJoyButtonDown (int port, int button) { #ifdef HAVE_JOYSTICK if (!joysticks[port].stick) return; activate (joysticks[port].buttons[button]); #endif /* HAVE_JOYSTICK */ } void VControl_ProcessJoyButtonUp (int port, int button) { #ifdef HAVE_JOYSTICK if (!joysticks[port].stick) return; deactivate (joysticks[port].buttons[button]); #endif /* HAVE_JOYSTICK */ } void VControl_ProcessJoyAxis (int port, int axis, int value) { #ifdef HAVE_JOYSTICK int t; if (!joysticks[port].stick) return; t = joysticks[port].threshold; if (value > t) { if (joysticks[port].axes[axis].polarity != 1) { if (joysticks[port].axes[axis].polarity == -1) { deactivate (joysticks[port].axes[axis].neg); } joysticks[port].axes[axis].polarity = 1; activate (joysticks[port].axes[axis].pos); } } else if (value < -t) { if (joysticks[port].axes[axis].polarity != -1) { if (joysticks[port].axes[axis].polarity == 1) { deactivate (joysticks[port].axes[axis].pos); } joysticks[port].axes[axis].polarity = -1; activate (joysticks[port].axes[axis].neg); } } else { if (joysticks[port].axes[axis].polarity == -1) { deactivate (joysticks[port].axes[axis].neg); } else if (joysticks[port].axes[axis].polarity == 1) { deactivate (joysticks[port].axes[axis].pos); } joysticks[port].axes[axis].polarity = 0; } #endif /* HAVE_JOYSTICK */ } void VControl_ProcessJoyHat (int port, int which, Uint8 value) { #ifdef HAVE_JOYSTICK Uint8 old; if (!joysticks[port].stick) return; old = joysticks[port].hats[which].last; if (!(old & SDL_HAT_LEFT) && (value & SDL_HAT_LEFT)) activate (joysticks[port].hats[which].left); if (!(old & SDL_HAT_RIGHT) && (value & SDL_HAT_RIGHT)) activate (joysticks[port].hats[which].right); if (!(old & SDL_HAT_UP) && (value & SDL_HAT_UP)) activate (joysticks[port].hats[which].up); if (!(old & SDL_HAT_DOWN) && (value & SDL_HAT_DOWN)) activate (joysticks[port].hats[which].down); if ((old & SDL_HAT_LEFT) && !(value & SDL_HAT_LEFT)) deactivate (joysticks[port].hats[which].left); if ((old & SDL_HAT_RIGHT) && !(value & SDL_HAT_RIGHT)) deactivate (joysticks[port].hats[which].right); if ((old & SDL_HAT_UP) && !(value & SDL_HAT_UP)) deactivate (joysticks[port].hats[which].up); if ((old & SDL_HAT_DOWN) && !(value & SDL_HAT_DOWN)) deactivate (joysticks[port].hats[which].down); joysticks[port].hats[which].last = value; #endif /* HAVE_JOYSTICK */ } void VControl_ResetInput () { /* Step through every valid entry in the binding pool and zero * them out. This will probably zero entries multiple times; * oh well, no harm done. */ keypool *base = pool; while (base != NULL) { int i; for (i = 0; i < POOL_CHUNK_SIZE; i++) { if(base->pool[i].target) { *(base->pool[i].target) = 0; } } base = base->next; } } void VControl_HandleEvent (const SDL_Event *e) { switch (e->type) { case SDL_KEYDOWN: VControl_ProcessKeyDown (e->key.keysym.sym); last_interesting = *e; event_ready = 1; break; case SDL_KEYUP: VControl_ProcessKeyUp (e->key.keysym.sym); break; #ifdef HAVE_JOYSTICK case SDL_JOYAXISMOTION: VControl_ProcessJoyAxis (e->jaxis.which, e->jaxis.axis, e->jaxis.value); if ((e->jaxis.value > 15000) || (e->jaxis.value < -15000)) { last_interesting = *e; event_ready = 1; } break; case SDL_JOYHATMOTION: VControl_ProcessJoyHat (e->jhat.which, e->jhat.hat, e->jhat.value); last_interesting = *e; event_ready = 1; break; case SDL_JOYBUTTONDOWN: VControl_ProcessJoyButtonDown (e->jbutton.which, e->jbutton.button); last_interesting = *e; event_ready = 1; break; case SDL_JOYBUTTONUP: VControl_ProcessJoyButtonUp (e->jbutton.which, e->jbutton.button); break; #endif /* HAVE_JOYSTICK */ default: break; } } void VControl_RegisterNameTable (VControl_NameBinding *table) { nametable = table; } static char * target2name (int *target) { VControl_NameBinding *b = nametable; while (b->target) { if (target == b->target) { return b->name; } ++b; } return NULL; } static int * name2target (char *name) { VControl_NameBinding *b = nametable; while (b->target) { if (!stricmp (name, b->name)) { return b->target; } ++b; } return NULL; } static void dump_keybindings (uio_Stream *out, keybinding *kb, char *name) { while (kb != NULL) { char *targetname = target2name (kb->target); WriteResFile (targetname, 1, strlen (targetname), out); PutResFileChar (':', out); PutResFileChar (' ', out); WriteResFile (name, 1, strlen (name), out); PutResFileNewline (out); kb = kb->next; } } void VControl_Dump (uio_Stream *out) { int i; char namebuffer[64]; sprintf (namebuffer, "version %d", version); WriteResFile (namebuffer, 1, strlen (namebuffer), out); PutResFileNewline (out); /* Print out keyboard bindings */ for (i = 0; i < num_sdl_keys; i++) { keybinding *kb = bindings[i]; if (kb != NULL) { sprintf (namebuffer, "key %s", VControl_code2name (i)); dump_keybindings (out, kb, namebuffer); } } #ifdef HAVE_JOYSTICK /* Print out joystick bindings */ for (i = 0; i < joycount; i++) { if (joysticks[i].stick) { int j; sprintf (namebuffer, "joystick %d threshold %d", i, joysticks[i].threshold); WriteResFile (namebuffer, 1, strlen (namebuffer), out); PutResFileNewline (out); for (j = 0; j < joysticks[i].numaxes; j++) { sprintf (namebuffer, "joystick %d axis %d negative", i, j); dump_keybindings (out, joysticks[i].axes[j].neg, namebuffer); sprintf (namebuffer, "joystick %d axis %d positive", i, j); dump_keybindings (out, joysticks[i].axes[j].pos, namebuffer); } for (j = 0; j < joysticks[i].numbuttons; j++) { keybinding *kb = joysticks[i].buttons[j]; if (kb != NULL) { sprintf (namebuffer, "joystick %d button %d", i, j); dump_keybindings (out, kb, namebuffer); } } for (j = 0; j < joysticks[i].numhats; j++) { sprintf (namebuffer, "joystick %d hat %d left", i, j); dump_keybindings (out, joysticks[i].hats[j].left, namebuffer); sprintf (namebuffer, "joystick %d hat %d right", i, j); dump_keybindings (out, joysticks[i].hats[j].right, namebuffer); sprintf (namebuffer, "joystick %d hat %d up", i, j); dump_keybindings (out, joysticks[i].hats[j].up, namebuffer); sprintf (namebuffer, "joystick %d hat %d down", i, j); dump_keybindings (out, joysticks[i].hats[j].down, namebuffer); } } } #endif /* HAVE_JOYSTICK */ #ifdef VCONTROL_DEBUG /* Print out allocation data */ { keypool bp = pool; i = 0; while (bp != NULL) { fprintf (out, "# Internal Debug: Chunk #%i: %d slots remaining.\n", i, bp->remaining); i++; bp = bp->next; } fprintf (out, "# Internal Debug: %d chunks allocated.\n", i); } #endif } /* Iterator routines. iter_target holds the target keybinding. iter_device is -1 for the keyboard, otherwise it is joystick #(iter_device/3). (iter_device%3) gives whether we're checking the joystick's axes (0), buttons (1), or hats (2). */ static int *iter_target; static int iter_device, iter_index; void VControl_StartIter (int *target) { iter_target = target; iter_device = -1; iter_index = 0; } void VControl_StartIterByName (char *targetname) { VControl_StartIter (name2target (targetname)); } int VControl_NextBinding (VCONTROL_GESTURE *gesture) { if ((gesture == NULL) || (iter_target == NULL) || iter_device >= (joycount * 3)) return 0; while (iter_device < (joycount * 3)) { if (iter_device == -1) /* keyboard */ { keybinding *kb = bindings[iter_index]; int done = 0; while (kb != NULL) { if (kb->target == iter_target) { gesture->type = VCONTROL_KEY; gesture->gesture.key = iter_index; done = 1; } kb = kb->next; } if (++iter_index == num_sdl_keys) { iter_device = 0; iter_index = 0; } if (done) return 1; } #ifdef HAVE_JOYSTICK else { int i = iter_device / 3; int t = iter_device % 3; if (!joysticks[i].stick) /* Joystick wasn't opened; this binding is dead */ { iter_device++; iter_index = 0; } else { int done = 0; switch (t) { case 0: { /* Axes */ int axis = iter_index / 2; int dir = iter_index % 2; if (axis >= joysticks[i].numaxes) { iter_device++; iter_index = 0; } else { keybinding *kb = (dir) ? joysticks[i].axes[axis].pos : joysticks[i].axes[axis].neg; while (kb != NULL) { if (kb->target == iter_target) { done = 1; gesture->type = VCONTROL_JOYAXIS; gesture->gesture.axis.port = i; gesture->gesture.axis.index = axis; gesture->gesture.axis.polarity = (dir) ? 1 : -1; } kb = kb->next; } iter_index++; } break; } case 1: { /* Buttons */ keybinding *kb = joysticks[i].buttons[iter_index]; if (iter_index >= joysticks[i].numbuttons) { iter_device++; iter_index = 0; } else { while (kb != NULL) { if (kb->target == iter_target) { gesture->type = VCONTROL_JOYBUTTON; gesture->gesture.button.port = i; gesture->gesture.button.index = iter_index; done = 1; } kb = kb->next; } iter_index++; } break; } case 2: { /* Hats */ int hat = iter_index / 4; int hatd = iter_index % 4; if (hat >= joysticks[i].numhats) { iter_device++; iter_index = 0; } else { keybinding *kb; Uint8 targetdir; switch (hatd) { case 0: kb = joysticks[i].hats[hat].left; targetdir = SDL_HAT_LEFT; break; case 1: kb = joysticks[i].hats[hat].right; targetdir = SDL_HAT_RIGHT; break; case 2: kb = joysticks[i].hats[hat].up; targetdir = SDL_HAT_UP; break; default: kb = joysticks[i].hats[hat].down; targetdir = SDL_HAT_DOWN; break; } while (kb != NULL) { if (kb->target == iter_target) { done = 1; gesture->type = VCONTROL_JOYHAT; gesture->gesture.hat.port = i; gesture->gesture.hat.index = hat; gesture->gesture.hat.dir = targetdir; } kb = kb->next; } iter_index++; } break; } } if (done) return 1; } } #endif /* HAVE_JOYSTICK */ } return 0; } /* Tracking the last interesting event */ void VControl_ClearEvent (void) { event_ready = 0; } int VControl_GetLastEvent (SDL_Event *e) { if (event_ready && e != NULL) { *e = last_interesting; } return event_ready; } /* Configuration file grammar is as follows: One command per line, * hashes introduce comments that persist to end of line. Blank lines * are ignored. * * Terminals are represented here as quoted strings, e.g. "foo" for * the literal string foo. These are matched case-insensitively. * Special terminals are: * * KEYNAME: This names a key, as defined in keynames.c. * IDNAME: This is an arbitrary string of alphanumerics, * case-insensitive, and ending with a colon. This * names an application-specific control value. * NUM: This is an unsigned integer. * EOF: End of file * * Nonterminals (the grammar itself) have the following productions: * * configline <- IDNAME binding * | "joystick" NUM "threshold" NUM * | "version" NUM * * binding <- "key" KEYNAME * | "joystick" NUM joybinding * * joybinding <- "axis" NUM polarity * | "button" NUM * | "hat" NUM direction * * polarity <- "positive" | "negative" * * dir <- "up" | "down" | "left" | "right" * * This grammar is amenable to simple recursive descent parsing; * in fact, it's fully LL(1). */ /* Actual maximum line and token sizes are two less than this, since * we need space for the \n\0 at the end */ #define LINE_SIZE 256 #define TOKEN_SIZE 64 typedef struct vcontrol_parse_state { char line[LINE_SIZE]; char token[TOKEN_SIZE]; int index; int error; int linenum; } parse_state; static void next_token (parse_state *state) { int index, base; state->token[0] = 0; /* skip preceding whitespace */ base = state->index; while (state->line[base] && isspace (state->line[base])) { base++; } index = 0; while (index < (TOKEN_SIZE-1) && state->line[base+index] && !isspace (state->line[base+index])) { state->token[index] = state->line[base+index]; index++; } state->token[index] = 0; /* If the token was too long, skip ahead until we get to whitespace */ while (state->line[base+index] && !isspace (state->line[base+index])) { index++; } state->index = base+index; } static void next_line (parse_state *state, uio_Stream *in) { int i, ch = 0; state->linenum++; for (i = 0; i < LINE_SIZE-1; i++) { if (uio_feof (in)) { break; } ch = uio_fgetc (in); if (ch == '#' || ch == '\n' || ch == EOF) { /* If this line is blank or all commented, include some * whitespace. This lets us detect EOF as a completely * blank line. */ if (i==0) { state->line[i] = '\n'; i++; } break; } state->line[i] = ch; } state->line[i] = '\0'; /* Skip to end of line */ while (ch != '\n' && !uio_feof (in)) { ch = uio_fgetc (in); } state->token[0] = 0; state->index = 0; state->error = 0; } static void expected_error (parse_state *state, char *expected) { log_add (log_Warning, "VControl: Expected '%s' on config file line %d", expected, state->linenum); state->error = 1; } static void consume (parse_state *state, char *expected) { if (stricmp (expected, state->token)) { expected_error (state, expected); } next_token (state); } static int consume_keyname (parse_state *state) { int keysym = VControl_name2code (state->token); if (!keysym) { log_add (log_Warning, "VControl: Illegal key name '%s' on config file line %d", state->token, state->linenum); state->error = 1; } next_token (state); return keysym; } static int * consume_idname (parse_state *state) { int *result = NULL; int index = 0; while (state->token[index]) { index++; } if (index == 0) { log_add (log_Debug, "VControl: Can't happen: blank token to consume_idname (line %d)", state->linenum); state->error = 1; return NULL; } index--; if (state->token[index] != ':') { expected_error (state, ":"); return NULL; } state->token[index] = 0; /* remove trailing colon */ result = name2target (state->token); if (!result) { log_add (log_Warning, "VControl: Illegal command type '%s' on config file line %d", state->token, state->linenum); state->error = 1; } next_token (state); return result; } static int consume_num (parse_state *state) { char *end; int result = strtol (state->token, &end, 10); if (*end != '\0') { log_add (log_Warning, "VControl: Expected integer on config line %d", state->linenum); state->error = 1; } next_token (state); return result; } static int consume_polarity (parse_state *state) { int result = 0; if (!stricmp (state->token, "positive")) { result = 1; } else if (!stricmp (state->token, "negative")) { result = -1; } else { expected_error (state, "positive' or 'negative"); } next_token (state); return result; } static Uint8 consume_dir (parse_state *state) { Uint8 result = 0; #ifdef HAVE_JOYSTICK if (!stricmp (state->token, "left")) { result = SDL_HAT_LEFT; } else if (!stricmp (state->token, "right")) { result = SDL_HAT_RIGHT; } else if (!stricmp (state->token, "up")) { result = SDL_HAT_UP; } else if (!stricmp (state->token, "down")) { result = SDL_HAT_DOWN; } else { expected_error (state, "left', 'right', 'up' or 'down"); } #endif /* HAVE_JOYSTICK */ next_token (state); return result; } static void parse_joybinding (parse_state *state, int *target) { int sticknum; consume (state, "joystick"); sticknum = consume_num (state); if (!state->error) { if (!stricmp (state->token, "axis")) { int axisnum; consume (state, "axis"); axisnum = consume_num (state); if (!state->error) { int polarity = consume_polarity (state); if (!state->error) { if (VControl_AddJoyAxisBinding (sticknum, axisnum, polarity, target)) { // Don't count this as an error // state->error = 1; } } } } else if (!stricmp (state->token, "button")) { int buttonnum; consume (state, "button"); buttonnum = consume_num (state); if (!state->error) { if (VControl_AddJoyButtonBinding (sticknum, buttonnum, target)) { // Don't count this as an error // state->error = 1; } } } else if (!stricmp (state->token, "hat")) { int hatnum; consume (state, "hat"); hatnum = consume_num (state); if (!state->error) { Uint8 dir = consume_dir (state); if (!state->error) { if (VControl_AddJoyHatBinding (sticknum, hatnum, dir, target)) { // Don't count this as an error // state->error = 1; } } } } else { expected_error (state, "axis', 'button', or 'hat"); } } } static void parse_binding (parse_state *state) { int *target = consume_idname (state); if (!state->error) { if (!stricmp (state->token, "key")) { /* Parse key binding */ int keysym; consume (state, "key"); keysym = consume_keyname (state); if (!state->error) { if (VControl_AddKeyBinding (keysym, target)) { state->error = 1; } } } else if (!stricmp (state->token, "joystick")) { parse_joybinding (state, target); } else { expected_error (state, "key' or 'joystick"); } } } static void parse_config_line (parse_state *state) { state->error = 0; next_token (state); if (!state->token[0]) { /* Blank line, skip it */ return; } if (!stricmp (state->token, "joystick")) { int sticknum, threshold = 0; consume (state, "joystick"); sticknum = consume_num (state); if (!state->error) consume (state, "threshold"); if (!state->error) threshold = consume_num (state); if (!state->error) { if (VControl_SetJoyThreshold (sticknum, threshold)) { // Don't count this as an error // state->error = 1; } } if (!state->error) { validlines++; } return; } if (!stricmp (state->token, "version")) { consume (state, "version"); version = consume_num (state); if (!state->error) { validlines++; } return; } /* Otherwise, it must be a binding */ parse_binding (state); if (!state->error) { validlines++; } } int VControl_ReadConfiguration (uio_Stream *in) { parse_state ps; if (!in) { log_add (log_Warning, "VControl: Invalid configuration file stream"); return 1; } ps.linenum = 0; errors = version = validlines = 0; while (1) { next_line (&ps, in); if (!ps.line[0]) break; parse_config_line (&ps); if (ps.error) { errors++; } } return errors; } int VControl_GetErrorCount (void) { return errors; } int VControl_GetValidCount (void) { return validlines; } int VControl_GetConfigFileVersion (void) { return version; } void VControl_SetConfigFileVersion (int v) { version = v; } #if 0 /* This was kinda handy for proving (lack of) buffer overrun * vulnerabilities, but there's no real need for it otherwise. */ void VControl_TokenizeFile (FILE *in) { parse_state ps; if (!in) { log_add (log_Warning, "VControl: Invalid configuration file stream"); return; } ps.linenum = 0; while (1) { _next_line (&ps, in); if (!ps.line[0]) break; printf ("%3d:", ps.linenum); while (1) { _next_token (&ps); if (!ps.token[0]) break; printf (" \"%s\"", ps.token); } printf ("\n"); } } #endif uqm-0.6.2/sc2/src/sc2code/libs/input/sdl/Makeinfo0000600000175000017500000000005310543202043020124 0ustar joeyjoeyuqm_CFILES="input.c keynames.c vcontrol.c" uqm-0.6.2/sc2/src/sc2code/libs/input/sdl/input.h0000600000175000017500000000157610543202043017773 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INPUT_H #define INPUT_H void FlushInput (void); void ProcessInputEvent (const SDL_Event *Event); #endif uqm-0.6.2/sc2/src/sc2code/libs/list.h0000600000175000017500000000141610543202055015662 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "list/list.h" uqm-0.6.2/sc2/src/sc2code/libs/mathlib.h0000600000175000017500000000164610543202055016334 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MATHLIB_H #define _MATHLIB_H #include "compiler.h" #include "math/random.h" extern COUNT square_root (DWORD value); #endif /* _MATHLIB_H */ uqm-0.6.2/sc2/src/sc2code/libs/declib.h0000600000175000017500000000266110543202055016134 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _DECLIB_H #define _DECLIB_H #include "libs/compiler.h" #define DECODE_REF PVOID enum { FILE_STREAM = 0, MEMORY_STREAM }; typedef BYTE STREAM_TYPE; enum { STREAM_READ = 0, STREAM_WRITE }; typedef BYTE STREAM_MODE; #endif /* _DECLIB_H */ #ifndef _DEC_PROTOS #define _DEC_PROTOS extern DECODE_REF copen (PVOID InStream, STREAM_TYPE SType, STREAM_MODE SMode); extern DWORD cclose (DECODE_REF DecodeRef); extern void cfilelength (DECODE_REF DecodeRef, DWORD *pfilelen); extern COUNT cread (PVOID pStr, COUNT size, COUNT count, DECODE_REF DecodeRef); extern COUNT cwrite (PVOID pStr, COUNT size, COUNT count, DECODE_REF DecodeRef); #endif /* _DEC_PROTOS */ uqm-0.6.2/sc2/src/sc2code/libs/heap.h0000600000175000017500000000003010543202055015613 0ustar joeyjoey#include "heap/heap.h" uqm-0.6.2/sc2/src/sc2code/libs/uio/0000755000175000017500000000000010552600274015345 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/uio/fstypes.h0000600000175000017500000000755210543202051017203 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _FSTYPES_H #define _FSTYPES_H typedef int uio_FileSystemID; #define uio_FSTYPE_STDIO 1 #define uio_FSTYPE_ZIP 2 #ifdef uio_INTERNAL #define uio_FS_FIRST_CUSTOM_ID 0x10 #ifndef uio_INTERNAL_PHYSICAL typedef void *uio_NativeHandle; #endif // 'forward' declarations typedef struct uio_FileSystemHandler uio_FileSystemHandler; typedef struct uio_FileSystemInfo uio_FileSystemInfo; #include #include #include "physical.h" #include "uioport.h" /* Structure describing how to access files _in_ a directory of a certain * type (not files _of_ a certain type.) Except for mount(). * in open(), the first arg points to the dir where the file should be * in, and the second arg is the name of that file (no path) */ struct uio_FileSystemHandler { int (*init) (void); int (*unInit) (void); void (*cleanup) (uio_PRoot *, int); // Called to cleanup memory. The second argument specifies // how thoroughly. struct uio_PRoot * (*mount) (uio_Handle *, int); int (*umount) (uio_PRoot *); void (*close) (uio_Handle *); // called when the last reference is closed, not // necessarilly each time when uio_close() is called int (*fstat) (uio_Handle *, struct stat *); int (*stat) (uio_PDirHandle *, const char *, struct stat *); uio_PDirHandle * (*mkdir) (uio_PDirHandle *, const char *, mode_t); uio_Handle * (*open) (uio_PDirHandle *, const char *, int, mode_t); ssize_t (*read) (uio_Handle *, void *, size_t); int (*rename) (uio_PDirHandle *, const char *, uio_PDirHandle *, const char *); int (*rmdir) (uio_PDirHandle *, const char *); off_t (*seek) (uio_Handle *, off_t, int); ssize_t (*write) (uio_Handle *, const void *, size_t); int (*unlink) (uio_PDirHandle *, const char *); uio_NativeEntriesContext (*openEntries) (uio_PDirHandle *); int (*readEntries) (uio_NativeEntriesContext *, char *, size_t); void (*closeEntries) (uio_NativeEntriesContext); uio_PDirEntryHandle * (*getPDirEntryHandle) ( const uio_PDirHandle *, const char *); void (*deletePRootExtra) (uio_PRootExtra pRootExtra); void (*deletePDirHandleExtra) ( uio_PDirHandleExtra pDirHandleExtra); void (*deletePFileHandleExtra) ( uio_PFileHandleExtra pFileHandleExtra); }; struct uio_FileSystemInfo { int ref; uio_FileSystemID id; char *name; // name of the file system uio_FileSystemHandler *handler; struct uio_FileSystemInfo *next; }; void uio_registerDefaultFileSystems(void); void uio_unRegisterDefaultFileSystems(void); uio_FileSystemID uio_registerFileSystem(uio_FileSystemID wantedID, const char *name, uio_FileSystemHandler *handler); int uio_unRegisterFileSystem(uio_FileSystemID id); uio_FileSystemHandler *uio_getFileSystemHandler(uio_FileSystemID id); uio_FileSystemInfo *uio_getFileSystemInfo(uio_FileSystemID id); #endif /* uio_INTERNAL */ #endif /* _FSTYPES_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/physical.c0000600000175000017500000001044010543202051017303 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include "physical.h" #ifdef uio_MEM_DEBUG # include "memdebug.h" #endif #include "uioport.h" static inline uio_PRoot *uio_PRoot_alloc(void); static inline void uio_PRoot_free(uio_PRoot *pRoot); // NB: ref counter is not incremented uio_PDirHandle * uio_PRoot_getRootDirHandle(uio_PRoot *pRoot) { return pRoot->rootDir; } void uio_PRoot_deletePRootExtra(uio_PRoot *pRoot) { if (pRoot->extra == NULL) return; assert(pRoot->handler->deletePRootExtra != NULL); pRoot->handler->deletePRootExtra(pRoot->extra); } // note: sets refMount count to 1 // set handlerRef count to 0 uio_PRoot * uio_PRoot_new(uio_PDirHandle *topDirHandle, uio_FileSystemHandler *handler, uio_Handle *handle, uio_PRootExtra extra, int flags) { uio_PRoot *pRoot; pRoot = uio_PRoot_alloc(); pRoot->mountRef = 1; pRoot->handleRef = 0; pRoot->rootDir = topDirHandle; pRoot->handler = handler; pRoot->handle = handle; pRoot->extra = extra; pRoot->flags = flags; #ifdef uio_PROOT_HAVE_CLOSE_HANDLERS pRoot->numCloseHandlers = 0; pRoot->closeHandlers = NULL; #endif return pRoot; } #ifdef uio_PROOT_HAVE_CLOSE_HANDLERS // Closehandlers code disabled. // It was only meant for internal use, but I don't need it any more. // Keeping it around for a while until I'm confident I won't need it in the // future. void uio_PRoot_addCloseHandler(uio_PRoot *pRoot, void (*fun)(void *), void *arg) { pRoot->numCloseHandlers++; pRoot->closeHandlers = uio_realloc(pRoot->closeHandlers, pRoot->numCloseHandlers * sizeof (uio_PRoot_CloseHandler)); pRoot->closeHandlers[pRoot->numCloseHandlers - 1].fun = fun; pRoot->closeHandlers[pRoot->numCloseHandlers - 1].arg = arg; } void uio_PRoot_callCloseHandlers(uio_PRoot *pRoot) { int i; i = pRoot->numCloseHandlers; while (i--) { uio_PRoot_CloseHandler *closeHandler; closeHandler = &pRoot->closeHandlers[i]; (closeHandler->fun)(closeHandler->arg); } } void uio_PRoot_removeCloseHandlers(uio_PRoot *pRoot) { pRoot->numCloseHandlers = 0; if (pRoot->closeHandlers != NULL) uio_free(pRoot->closeHandlers); pRoot->closeHandlers = NULL; } #endif static inline void uio_PRoot_delete(uio_PRoot *pRoot) { #ifdef uio_PROOT_HAVE_CLOSE_HANDLERS uio_PRoot_callCloseHandlers(pRoot); uio_PRoot_removeCloseHandlers(pRoot); #endif assert(pRoot->handler->umount != NULL); pRoot->handler->umount(pRoot); if (pRoot->handle) uio_Handle_unref(pRoot->handle); uio_PRoot_deletePRootExtra(pRoot); uio_PRoot_free(pRoot); } static inline uio_PRoot * uio_PRoot_alloc(void) { uio_PRoot *result = uio_malloc(sizeof (uio_PRoot)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_PRoot, (void *) result); #endif return result; } static inline void uio_PRoot_free(uio_PRoot *pRoot) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_PRoot, (void *) pRoot); #endif uio_free(pRoot); } void uio_PRoot_refHandle(uio_PRoot *pRoot) { pRoot->handleRef++; } void uio_PRoot_unrefHandle(uio_PRoot *pRoot) { assert(pRoot->handleRef > 0); pRoot->handleRef--; if (pRoot->handleRef == 0 && pRoot->mountRef == 0) uio_PRoot_delete(pRoot); } void uio_PRoot_refMount(uio_PRoot *pRoot) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugRef(uio_PRoot, (void *) pRoot); #endif pRoot->handleRef++; } void uio_PRoot_unrefMount(uio_PRoot *pRoot) { assert(pRoot->mountRef > 0); #ifdef uio_MEM_DEBUG uio_MemDebug_debugUnref(uio_PRoot, (void *) pRoot); #endif pRoot->mountRef--; if (pRoot->mountRef == 0 && pRoot->handleRef == 0) uio_PRoot_delete(pRoot); } uqm-0.6.2/sc2/src/sc2code/libs/uio/charhashtable.c0000600000175000017500000000430010543202051020256 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #define HASHTABLE_INTERNAL #include "charhashtable.h" #include "types.h" #include "uioport.h" static inline uio_uint32 CharHashTable_hash(CharHashTable_HashTable *hashTable, const char *string); static inline uio_bool CharHashTable_equal(CharHashTable_HashTable *hashTable, const char *key1, const char *key2); static inline char *CharHashTable_copy(CharHashTable_HashTable *hashTable, const char *key); static inline void CharHashTable_free(CharHashTable_HashTable *hashTable, char *key); #include "hashtable.c" static inline uio_uint32 CharHashTable_hash(CharHashTable_HashTable *hashTable, const char *key) { uio_uint32 hash; (void) hashTable; // Rotating hash, variation of something on the web which // wasn't original itself. hash = 0; // Hash was on that web page initialised as the length, // but that isn't known at this time. while (*key != '\0') { hash = (hash << 4) ^ (hash >> 28) ^ *key; key++; } return hash ^ (hash >> 10) ^ (hash >> 20); } static inline uio_bool CharHashTable_equal(CharHashTable_HashTable *hashTable, const char *key1, const char *key2) { (void) *hashTable; return strcmp(key1, key2) == 0; } static inline char * CharHashTable_copy(CharHashTable_HashTable *hashTable, const char *key) { (void) *hashTable; return uio_strdup(key); } static inline void CharHashTable_free(CharHashTable_HashTable *hashTable, char *key) { (void) *hashTable; uio_free(key); } uqm-0.6.2/sc2/src/sc2code/libs/uio/ioaux.c0000644000175000017500000007111110546776502016652 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ // auxiliary functions for use by io.c #include #include #include "ioaux.h" #include "iointrn.h" #include "uioport.h" #include "paths.h" static int copyError(int error, uio_FileSystemHandler *fromHandler, uio_Handle *fromHandle, uio_FileSystemHandler *toHandler, uio_Handle *toHandle, uio_PDirHandle *toDir, const char *toName, char *buf); /** * Follow a path starting from a specified physical dir for as long as * possible. * * @param[in] startPDirHandle The physical dir to start from. * @param[in] path The path to follow, relative to * 'startPDirHandle'. * @param[in] pathLen The string length of 'path'. * @param[out] endPDirHandle The physical dir where you end up after * following 'path' for as long as possible. Unmodified if an error * occurs. * @param[out] pathRest '*pathRest' will point into 'path' to the * start the part that was not matched. Unmodified if an error occurs. * * @retval 0 if the complete path was matched * @retval ENOENT if some component (the next one in '*pathRest') didn't * exist. * @retval ENODIR if a component (the next one in '*pathRest') did exist, * but wasn't a dir. * * @note It is allowed to have 'endPDirHandle' point to pDirHandle, but * care should be taken to keep a reference to the original so its * reference counter can be decremented. * @note It is allowed to have 'pathRest' point to 'path'. */ int uio_walkPhysicalPath(uio_PDirHandle *startPDirHandle, const char *path, size_t pathLen, uio_PDirHandle **endPDirHandle, const char **pathRest) { const char *pathEnd; const char *partStart, *partEnd; char *tempBuf; uio_PDirHandle *pDirHandle; uio_PDirEntryHandle *entry; int retVal; uio_PDirHandle_ref(startPDirHandle); pDirHandle = startPDirHandle; tempBuf = uio_alloca(strlen(path) + 1); pathEnd = path + pathLen; getFirstPathComponent(path, pathEnd, &partStart, &partEnd); for (;;) { if (partStart == pathEnd) { retVal = 0; break; } memcpy(tempBuf, partStart, partEnd - partStart); tempBuf[partEnd - partStart] = '\0'; entry = uio_getPDirEntryHandle(pDirHandle, tempBuf); if (entry == NULL) { retVal = ENOENT; break; } if (!uio_PDirEntryHandle_isDir(entry)) { uio_PDirEntryHandle_unref(entry); retVal = ENOTDIR; break; } uio_PDirHandle_unref(pDirHandle); pDirHandle = (uio_PDirHandle *) entry; getNextPathComponent(pathEnd, &partStart, &partEnd); } *pathRest = partStart; *endPDirHandle = pDirHandle; return retVal; } /** * Create a directory inside a physical directory. All non-existant * parent directories will be created as well. * * @param[in] pDirHandle The physical directory to which 'path' is relative * @param[in] path The path to the directory to create, relative to * 'pDirHandle' * @param[in] pathLen The string length of 'path'. * @param[in] mode The access mode for the newly created directories. * * @returns the new (physical) directory, or NULL if an error occurs, in * which case #errno will be set. */ uio_PDirHandle * uio_makePath(uio_PDirHandle *pDirHandle, const char *path, size_t pathLen, mode_t mode) { const char *rest, *start, *end; uio_PDirHandle *(*mkdirFun)(uio_PDirHandle *, const char *, mode_t); char *buf; const char *pathEnd; uio_PDirHandle *newPDirHandle; mkdirFun = pDirHandle->pRoot->handler->mkdir; if (mkdirFun == NULL) { errno = ENOSYS; return NULL; } pathEnd = path + pathLen; buf = uio_alloca(pathLen + 1); // worst case length uio_walkPhysicalPath(pDirHandle, path, pathLen, &pDirHandle, &rest); // The reference to the original pDirHandle is still kept // by the calling function; uio_PDirHandle_unref should not // be called for it. // Rest now points into 'path' to the part from where no physical // dir exists. getFirstPathComponent(rest, pathEnd, &start, &end); while (start < pathEnd) { memcpy(buf, start, end - start); buf[end - start] = '\0'; newPDirHandle = mkdirFun(pDirHandle, buf, mode); if (newPDirHandle == NULL) { int savedErrno = errno; uio_PDirHandle_unref(pDirHandle); errno = savedErrno; return NULL; } uio_PDirHandle_unref(pDirHandle); pDirHandle = newPDirHandle; getNextPathComponent(pathEnd, &start, &end); } return pDirHandle; } /** * Copy a file from one physical directory to another. * The copy will have the same file permissions as the original. * * @param[in] fromDir The physical directory where the file to copy is * located. * @param[in] fromName The name of the file to copy. * @param[in] toDir The physical directory where to put the copy. * @param[in] toName The name to use for the copy. * * @note It is up to the caller to make any relevant permissions checks. * * @note This function will fail if a file with the name in 'toName' already * exists, leaving the original file intact. If an error occurs during * copying, an attempt is made to remove the file that was to be the * copy. */ int uio_copyFilePhysical(uio_PDirHandle *fromDir, const char *fromName, uio_PDirHandle *toDir, const char *toName) { uio_FileSystemHandler *fromHandler, *toHandler; uio_Handle *fromHandle; uio_Handle *toHandle; #define BUFSIZE 0x10000 struct stat statBuf; char *buf, *bufPtr; ssize_t numInBuf, numWritten; fromHandler = fromDir->pRoot->handler; toHandler = toDir->pRoot->handler; if (toHandler->write == NULL || fromHandler->fstat == NULL || toHandler->unlink == NULL) { errno = ENOSYS; return -1; } fromHandle = (fromHandler->open)(fromDir, fromName, O_RDONLY, 0); if (fromHandle == NULL) { // errno is set return -1; } if ((fromHandler->fstat)(fromHandle, &statBuf) == -1) return copyError(errno, fromHandler, fromHandle, toHandler, NULL, NULL, NULL, NULL); toHandle = (toHandler->open)(toDir, toName, O_WRONLY | O_CREAT | O_EXCL, statBuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); if (toHandle == NULL) return copyError(errno, fromHandler, fromHandle, toHandler, NULL, NULL, NULL, NULL); buf = uio_malloc(BUFSIZE); // not allocated on the stack, as this function may be called // from a thread with little stack space. while (1) { numInBuf = (fromHandler->read)(fromHandle, buf, BUFSIZE); if (numInBuf == -1) { if (errno == EINTR) continue; return copyError (errno, fromHandler, fromHandle, toHandler, toHandle, toDir, toName, buf); } if (numInBuf == 0) break; bufPtr = buf; do { numWritten = (toHandler->write)(toHandle, bufPtr, numInBuf); if (numWritten == -1) { if (errno == EINTR) continue; return copyError (errno, fromHandler, fromHandle, toHandler, toHandle, toDir, toName, buf); } numInBuf -= numWritten; bufPtr += numWritten; } while (numInBuf > 0); } uio_free(buf); (toHandler->close)(toHandle); (fromHandler->close)(fromHandle); return 0; } /* * Closes fromHandle if it's not -1. * Closes fromHandle if it's not -1. * Removes 'toName' from 'toDir' if it's not NULL. * Frees 'buf' if not NULL. * Always returns -1. */ static int copyError(int error, uio_FileSystemHandler *fromHandler, uio_Handle *fromHandle, uio_FileSystemHandler *toHandler, uio_Handle *toHandle, uio_PDirHandle *toDir, const char *toName, char *buf) { #ifdef DEBUG fprintf(stderr, "Error while copying: %s\n", strerror(error)); #endif if (fromHandle != NULL) (fromHandler->close)(fromHandle); if (toHandle != NULL) (toHandler->close)(toHandle); if (toName != NULL) (toHandler->unlink)(toDir, toName); if (buf != NULL) uio_free(buf); errno = error; return -1; } /* * Description: find PDirHandle and MountInfo structures for reading and * writing for a path from a DirHandle. * This can be used for opening a file and creating directories. * Arguments: dirHandle - the directory to which the path is relative. * path - the path to the component that is to be accessed. * The last component does not have to exist. * flags - used to specify what kind of access is requested * Either O_RDONLY, O_RDWR, O_WRONLY. They may be * OR'd with other values accepted by open(). These * are ignored. * XXX: this is no longer true. * TODO: update this doc, and check uio_open() and * perhaps others (uio_mkdir()) for unnecessary * checks on O_CREAT and O_EXCL. * extraFlags - either 0 or uio_GPA_NOWRITE * When 0, the path will be created if it doesn't * exist in the writing location, but does exist * in the reading location. With uio_GPA_NOWRITE, it * won't be created, and -1 will be returned and errno * will be set to ENOENT. * mountInfoReadPtr - pointer to location where the pointer * to the MountInfo structure for the reading location * should be stored. * readPDirHandlePtr - pointer to the location where the pointer * to the PDirHandle used for reading should be stored. * readPRootPath - pointer to the location where the pointer * to the physical path to the reading location * is to be stored. * The caller is responsible for freeing this. * Ignored if NULL. * mountInfoWritePtr - pointer to location where the pointer * to the MountInfo structure for the writing location * should be stored. * writePDirHandlePtr - pointer to the location where the pointer * to the PDirHandle used for writing should be stored. * NULL if O_RDONLY was specified. * If this is the same dir as the one refered * to by readPDirHandlePtr, the handles will be the * same too. * writePRootPath - pointer to the location where the pointer * to the physical path to the writing location * is to be stored. * The caller is responsible for freeing this. * Ignored if NULL. * restPtr - pointer to the location where a newly created * string with as contents the last component of 'path' * is to be stored. * The caller is responsible for freeing this. * Ignored if NULL. * Returns: 0 - success * -1 - failure (errno set) * NB: This is the function that would most benefit from * the introduction of LDirs. * This is also the most messy function. It could * use some more comments, or a cleanup (if possible). */ int uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path, int flags, int extraFlags, uio_MountInfo **mountInfoReadPtr, uio_PDirHandle **readPDirHandlePtr, char **readPRootPathPtr, uio_MountInfo **mountInfoWritePtr, uio_PDirHandle **writePDirHandlePtr, char **writePRootPathPtr, char **restPtr) { char *fullPath; // path from dirHandle with 'path' added const char *pRootPath; // path from the pRoot of a physical tree const char *readPRootPath, *writePRootPath; const char *rest, *readRest; uio_MountTree *tree; uio_MountTreeItem *item; uio_MountTreeItem *readItem, *writeItem; uio_PDirHandle *readPDirHandle, *writePDirHandle, *pDirHandle; int retVal; uio_bool entryExists; // Set if the entry pointed to by path exists (including // the last component of the path) // 'path' is relative to dirHandle. // Fill 'fullPath' with the absolute path. if (uio_resolvePath(dirHandle, path, strlen(path), &fullPath) == -1) { // errno is set return -1; } // Walk the tree of mount points along 'fullPath'. // 'tree' will be the part of the tree where we end up when we can go // no further. tree->pLocs are all the mounts relevant there. // 'rest' will point within 'fullPath' to what is left, after we can // walk the tree of mountpoints no further. uio_findMountTree(dirHandle->repository->mountTree, fullPath, &tree, &rest); readItem = NULL; readPDirHandle = NULL; readPRootPath = NULL; writeItem = NULL; writePDirHandle = NULL; writePRootPath = NULL; readRest = NULL; // Satisfy compiler. entryExists = false; // try all the MountInfo structures in effect for this MountTree for (item = tree->pLocs; item != NULL; item = item->next) { pRootPath = uio_mountTreeItemRestPath(item, tree->lastComp, fullPath); retVal = uio_walkPhysicalPath(item->mountInfo->pDirHandle, pRootPath, strlen(pRootPath), &pDirHandle, &rest); // rest points inside fullPath if (retVal == 0) { // Even the last component appeared to be a dir. // As the last component did exist, we don't go on. uio_free(fullPath); uio_PDirHandle_unref(pDirHandle); if (readPDirHandle != NULL) uio_PDirHandle_unref(readPDirHandle); errno = EISDIR; return -1; } // check if this MountTreeItem is suitable for writing if (writeItem == NULL && !uio_mountInfoIsReadOnly(item->mountInfo)) writeItem = item; if (strchr(rest, '/') == NULL) { // There's only one dir component that was not matched. uio_PDirEntryHandle *entry; // This MountInfo will do for reading, if the file from the last // component is present in this dir. entry = uio_getPDirEntryHandle(pDirHandle, rest); if (entry != NULL) { // 'rest' exists, and it is not a dir, as otherwise // uio_getPDirEntryHandle wouldn't have stopped where it did. uio_PDirEntryHandle_unref(entry); readItem = item; if (readPDirHandle != NULL) uio_PDirHandle_unref(readPDirHandle); readPDirHandle = pDirHandle; readPRootPath = pRootPath; readRest = rest; entryExists = true; break; } else { // 'rest' doesn't exist // We're only interested in this dir if we want to write too. if (((flags & O_ACCMODE) != O_RDONLY) && readItem == NULL) { // Keep the first one. readItem = item; assert(readPDirHandle == NULL); readPDirHandle = pDirHandle; readPRootPath = pRootPath; readRest = rest; continue; } } } else { // There is more than one dir component that was not matched. // If the first component of the non-matched part is a file, // stop here and don't check lower dirs. if (retVal == ENOTDIR) { uio_free(fullPath); uio_PDirHandle_unref(pDirHandle); if (readPDirHandle != NULL) uio_PDirHandle_unref(readPDirHandle); errno = ENOTDIR; return -1; } } uio_PDirHandle_unref(pDirHandle); } // for // readItem is set to the first readItem for which the path completely // exists (including the final component). If there's no such readItem, // it is set to the first path for which the path exists, but without // the final component (entryExists is false in this case). If there's // no such path either, it's set to NULL. if (readItem == NULL) { uio_free(fullPath); errno = ENOENT; return -1; } if ((flags & O_ACCMODE) == O_RDONLY) { // write access is not needed *mountInfoReadPtr = readItem->mountInfo; *readPDirHandlePtr = readPDirHandle; if (readPRootPathPtr != NULL) *readPRootPathPtr = joinPathsAbsolute( readItem->mountInfo->dirName, readPRootPath); // Don't touch mountInfoWritePtr and writePDirHandlePtr. // they'd be NULL. *restPtr = uio_strdup(readRest); uio_free(fullPath); return 0; } else { if (entryExists) { if ((flags & O_CREAT) && (flags & O_EXCL)) { // An entry should be created, but it already exists and // it may not be overwritten. uio_PDirHandle_unref(readPDirHandle); uio_free(fullPath); errno = EEXIST; return -1; } } else { // Though the path to the entry existed (readPDirHandle is // set to it), the entry itself doesn't, so we can't use it // unless we intend to create it. if (flags & O_CREAT) { // The entry does not exist, but we can create it. // Handled below. } else { // O_CREAT was not specified, so we cannot create // this entry. uio_PDirHandle_unref(readPDirHandle); uio_free(fullPath); errno = ENOENT; return -1; } } } if (writeItem == readItem) { // The read directory is usable as write directory too. *mountInfoReadPtr = readItem->mountInfo; *readPDirHandlePtr = readPDirHandle; if (readPRootPathPtr != NULL) *readPRootPathPtr = joinPathsAbsolute( readItem->mountInfo->dirName, readPRootPath); *mountInfoWritePtr = writeItem->mountInfo; // writeItem == readItem uio_PDirHandle_ref(readPDirHandle); *writePDirHandlePtr = readPDirHandle; // No copy&paste error, the read PDirHandle is the write // pDirHandle too. if (writePRootPathPtr != NULL) *writePRootPathPtr = joinPathsAbsolute( writeItem->mountInfo->dirName, writePRootPath); if (restPtr != NULL) *restPtr = uio_strdup(readRest); uio_free(fullPath); return 0; } if (writeItem == NULL) { uio_free(fullPath); uio_PDirHandle_unref(readPDirHandle); errno = EPERM; // readItem is not NULL, so ENOENT would not be correct here. return -1; } // Left is the case where the write location is different from the // read location. pRootPath = uio_mountTreeItemRestPath(writeItem, tree->lastComp, fullPath); rest = strrchr(pRootPath, '/'); // rest points inside fullPath if (rest == NULL) { rest = pRootPath; uio_PDirHandle_ref(writeItem->mountInfo->pDirHandle); writePDirHandle = writeItem->mountInfo->pDirHandle; } else { // There exists no path for a write dir, so it will have to be created. // writeMountInfo indicates the physical tree where it should end up. if (extraFlags & uio_GPA_NOWRITE) { // The caller has specified that the path should not be created. uio_PDirHandle_unref(readPDirHandle); uio_free(fullPath); errno = ENOENT; return -1; } writePDirHandle = uio_makePath(writeItem->mountInfo->pDirHandle, pRootPath, rest - pRootPath, 0777); if (writePDirHandle == NULL) { int savedErrno; if (errno == ENOSYS) { // mkdir not supported. We want to report that we failed // because of an error in the underlying layer. // EIO sounds like the best choice. errno = EIO; } savedErrno = errno; uio_PDirHandle_unref(readPDirHandle); uio_free(fullPath); errno = savedErrno; return -1; } rest++; // skip the '/' } if (!entryExists) { // The path to the read dir exists, but the entry itself doesn't. // After we created the write dir, the same thing holds for // the write dir. As it occurs in an earlier MountItem, we'll use // the writeItem (and writePDirHandle) for reading too. readItem = writeItem; uio_PDirHandle_ref(writePDirHandle); uio_PDirHandle_unref(readPDirHandle); readPDirHandle = writePDirHandle; } *mountInfoReadPtr = readItem->mountInfo; *readPDirHandlePtr = readPDirHandle; if (readPRootPathPtr != NULL) *readPRootPathPtr = joinPathsAbsolute( readItem->mountInfo->dirName, readPRootPath); *mountInfoWritePtr = writeItem->mountInfo; *writePDirHandlePtr = writePDirHandle; if (writePRootPathPtr != NULL) *writePRootPathPtr = joinPathsAbsolute( writeItem->mountInfo->dirName, writePRootPath); if (restPtr != NULL) *restPtr = uio_strdup(rest); uio_free(fullPath); return 0; } // Get handles to the (existing) physical dirs that are effective in a // path 'path' relative from 'dirHandle' // returns the PDirHandles through '*pDirHandles'. It is NULL if none // were found. // If resItems != NULL, it returns the MountTreeItems belonging to those // PDIrHandles through *resItems. It is NULL if none were found. // numPDirHandles will contain the number of PDirHandles found. // returns 0 if everything went ok. // returns -1 in case of an error; errno is set. int uio_getPathPhysicalDirs(uio_DirHandle *dirHandle, const char *path, size_t pathLen, uio_PDirHandle ***resPDirHandles, int *resNumPDirHandles, uio_MountTreeItem ***resItems) { uio_PDirHandle **pDirHandles; char *fullPath; // path from dirHandle with 'path' added uio_MountTree *tree; const char *rest; uio_MountTreeItem *item, **items; const char *pRootPath; // path from the pRoot of a physical tree int numPDirHandles; int pDirI; // PDirHandle iterator // Determine the absolute path from 'path', which is relative to dirHandle. if (uio_resolvePath(dirHandle, path, pathLen, &fullPath) == -1) { // errno is set return -1; } // get the MountTree effective for the path uio_findMountTree(dirHandle->repository->mountTree, fullPath, &tree, &rest); // fill pDirHandles with all the PDirHandles for the path numPDirHandles = uio_mountTreeCountPLocs(tree); pDirHandles = uio_malloc(numPDirHandles * sizeof (uio_PDirHandle *)); if (resItems != NULL) { items = uio_malloc(numPDirHandles * sizeof (uio_MountTreeItem *)); } else { items = NULL; // satisfy compiler } pDirI = 0; for (item = tree->pLocs; item != NULL; item = item->next) { uio_PDirHandle *pDirHandle; pRootPath = uio_mountTreeItemRestPath(item, tree->lastComp, fullPath); switch (uio_walkPhysicalPath(item->mountInfo->pDirHandle, pRootPath, strlen(pRootPath), &pDirHandle, &rest)) { case 0: // complete path was matched pDirHandles[pDirI] = pDirHandle; if (resItems != NULL) items[pDirI] = item; pDirI++; continue; case ENOENT: // some component couldn't be matched uio_PDirHandle_unref(pDirHandle); continue; case ENOTDIR: // next component was not a dir // Don't look further at other mount Items. uio_PDirHandle_unref(pDirHandle); break; default: assert(false); uio_PDirHandle_unref(pDirHandle); continue; } break; } numPDirHandles = pDirI; uio_free(fullPath); *resPDirHandles = uio_realloc(pDirHandles, numPDirHandles * sizeof (uio_PDirHandle *)); if (resItems != NULL) *resItems = uio_realloc(items, numPDirHandles * sizeof (uio_MountTreeItem *)); *resNumPDirHandles = numPDirHandles; return 0; } // returns 0 if the path is valid and exists // returns -1 if the path is not valid or does not exist. // in this case errno will be set to: // ENOENT if some component didn't exist // ENOTDIR is some component exists, but is not a dir // something else (like EPATHTOOLONG) for internal errors // On success, 'resolvedPath' will be set to the absolute path as returned by // uio_resolvePath. int uio_verifyPath(uio_DirHandle *dirHandle, const char *path, char **resolvedPath) { uio_MountTree *tree; uio_MountTreeItem *item; const char *rest; int retVal; // TODO: "////", "/somedir//", and "//somedir" are accepted as valid // Determine the absolute path from 'path' which is relative to dirHandle. if (uio_resolvePath(dirHandle, path, strlen(path), resolvedPath) == -1) { // errno is set return -1; } // get the MountTree effective for the path uio_findMountTree(dirHandle->repository->mountTree, *resolvedPath, &tree, &rest); if (rest[0] == '\0') { // Complete match. Even if there are no pLocs in effect here // (which can only happen in case the mount Tree is empty and // we're viewing '/'). return 0; } // Try all the MountInfo structures in effect for this MountTree. for (item = tree->pLocs; item != NULL; item = item->next) { const char *pRootPath; uio_PDirHandle *pDirHandle; pRootPath = uio_mountTreeItemRestPath(item, tree->lastComp, *resolvedPath); retVal = uio_walkPhysicalPath(item->mountInfo->pDirHandle, pRootPath, strlen(pRootPath), &pDirHandle, &rest); uio_PDirHandle_unref(pDirHandle); switch (retVal) { case 0: // Complete match. We're done. return 0; case ENOTDIR: // A component is matched, but not as a dir. Failed. uio_free(*resolvedPath); errno = ENOTDIR; return -1; case ENOENT: // No match; try the next pLoc. continue; default: // Unknown error. Let's bail out just to be safe. #ifdef DEBUG fprintf(stderr, "Warning: Unknown error from " "uio_walkPhysicalPath: %s\n", strerror(retVal)); #endif uio_free(*resolvedPath); errno = retVal; return -1; } } // No match, exit with ENOENT. uio_free(*resolvedPath); errno = ENOENT; return -1; } /** * Determine the absolute path given a path relative to a given directory. * * @param[in] dirHandle The directory to which 'path' is relative. * @param[in] path The path, relative to 'dirHandle', to make * absolute. * @param[in] pathLen The string length of 'path'. * @param[out] destPath Filled with a newly allocated string containing * the sought absolute path. It will not contain a '/' as the first * or last character. It should be freed with uio_free(). * Unmodified if an error occurs. * * @returns the length of '*destPath', or -1 if an error occurs, in which * case #errno will be set. */ ssize_t uio_resolvePath(uio_DirHandle *dirHandle, const char *path, size_t pathLen, char **destPath) { size_t len; const char *pathEnd, *start, *end; int numUp; // number of ".." dirs still need to be matched. char *buffer; char *endBufPtr; uio_bool absolute; absolute = path[0] == '/'; pathEnd = path + pathLen; // Pass 1: count the amount of space needed len = 0; numUp = 0; for (getLastPathComponent(path, pathEnd, &start, &end); end > path; getPreviousPathComponent(path, &start, &end)) { if (start[0] == '.') { if (start + 1 == end) { // "." matched continue; } if (start[1] == '.' && start + 2 == end) { // ".." matched numUp++; continue; } } if (numUp > 0) { // last 'numUp' components were ".." numUp--; continue; } len += (end - start) + 1; // the 1 is for the '/' } // The part from 'dirHandle->path' to 'dirHandle->rootEnd' is // always copied (for a valid path). The rest we'll have to count. // (Note the 'rootEnd' in the initialiser of the for loop.) len += (dirHandle->rootEnd - dirHandle->path); if (!absolute) { for (getLastPath0Component(dirHandle->rootEnd, &start, &end); end > dirHandle->rootEnd; getPreviousPath0Component(dirHandle->rootEnd, &start, &end)) { if (numUp > 0) { numUp--; continue; } len += (end - start) + 1; // the 1 is for the '/' } } if (numUp > 0) { // too many ".." errno = ENOENT; return -1; } if (len == 0) { *destPath = uio_malloc(1); (*destPath)[0] = '\0'; return 0; } // len--; // we don't want a '/' at the start // len++; // for the terminating '\0' buffer = uio_malloc(len); // Pass 2: fill the buffer endBufPtr = buffer + len - 1; *endBufPtr = '\0'; numUp = 0; for (getLastPathComponent(path, pathEnd, &start, &end); end > path; getPreviousPathComponent(path, &start, &end)) { if (start[0] == '.') { if (start + 1 == end) { // "." matched continue; } if (start[1] == '.' && start + 2 == end) { // ".." matched numUp++; continue; } } if (numUp > 0) { // last 'numUp' components were ".." numUp--; continue; } endBufPtr -= (end - start); memcpy(endBufPtr, start, end - start); if (endBufPtr != buffer) { // We want no '/' at the beginning endBufPtr--; *endBufPtr = '/'; } else { // We're already done. We might as well take advantage of // the fact that we know that and exit immediatly: *destPath = buffer; return len; } } // copy the part from dirHandle->path to dirHandle->rootEnd endBufPtr -= (dirHandle->rootEnd - dirHandle->path); memcpy(endBufPtr, dirHandle->path, dirHandle->rootEnd - dirHandle->path); if (!absolute) { // copy (some of) the components from dirHandle->rootEnd on. for (getLastPath0Component(dirHandle->rootEnd, &start, &end); end > dirHandle->rootEnd; getPreviousPath0Component(dirHandle->rootEnd, &start, &end)) { if (numUp > 0) { numUp--; continue; } endBufPtr -= (end - start); memcpy(endBufPtr, start, end - start); if (endBufPtr != buffer) { // We want no '/' at the beginning endBufPtr--; *endBufPtr = '/'; } else { // We're already done. We might as well take advantage of // the fact that we know that and exit immediatly: break; } } } *destPath = buffer; return len; } uqm-0.6.2/sc2/src/sc2code/libs/uio/uioutils.c0000644000175000017500000001550010546776502017402 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include "uioutils.h" #include "mem.h" #include "paths.h" #include "uioport.h" /** * Concatenate two strings into a newly allocated buffer. * * @param[in] first The first (left) string, '\0' terminated. * @param[in] second The second (right) string, '\0' terminated. * * @returns A newly allocated string consisting of the concatenation of * 'first' and 'second', to be freed using uio_free(). */ char * strcata(const char *first, const char *second) { char *result, *resPtr; size_t firstLen, secondLen; firstLen = strlen(first); secondLen = strlen(second); result = uio_malloc(firstLen + secondLen + 1); resPtr = result; memcpy(resPtr, first, firstLen); resPtr += firstLen; memcpy(resPtr, second, secondLen); resPtr += secondLen; *resPtr = '\0'; return result; } // returns a copy of a generic array 'array' with 'element' inserted in // position 'insertPos' void * insertArray(const void *array, size_t oldNumElements, int insertPos, const void *element, size_t elementSize) { void *newArray, *newArrayPtr; const void *arrayPtr; size_t preInsertSize; newArray = uio_malloc((oldNumElements + 1) * elementSize); preInsertSize = insertPos * elementSize; memcpy(newArray, array, preInsertSize); newArrayPtr = (char *) newArray + preInsertSize; arrayPtr = (const char *) array + preInsertSize; memcpy(newArrayPtr, element, elementSize); newArrayPtr = (char *) newArrayPtr + elementSize; memcpy(newArrayPtr, arrayPtr, (oldNumElements - insertPos) * elementSize); return newArray; } // returns a copy of a pointer array 'array' with 'element' inserted in // position 'insertPos' void ** insertArrayPointer(const void **array, size_t oldNumElements, int insertPos, const void *element) { void **newArray, **newArrayPtr; const void **arrayPtr; size_t preInsertSize; newArray = uio_malloc((oldNumElements + 1) * sizeof (void *)); preInsertSize = insertPos * sizeof (void *); memcpy(newArray, array, preInsertSize); newArrayPtr = newArray + insertPos; arrayPtr = array + insertPos; *newArrayPtr = unconst(element); newArrayPtr++; memcpy(newArrayPtr, arrayPtr, (oldNumElements - insertPos) * sizeof (void *)); return newArray; } // returns a copy of a generic array 'array' with 'numExclude' elements, // starting from startpos, removed. void * excludeArray(const void *array, size_t oldNumElements, int startPos, int numExclude, size_t elementSize) { void *newArray, *newArrayPtr; const void *arrayPtr; size_t preExcludeSize; newArray = uio_malloc((oldNumElements - numExclude) * elementSize); preExcludeSize = startPos * elementSize; memcpy(newArray, array, preExcludeSize); newArrayPtr = (char *) newArray + preExcludeSize; arrayPtr = (const char *) array + (startPos + numExclude) * sizeof (elementSize); memcpy(newArrayPtr, arrayPtr, (oldNumElements - startPos - numExclude) * elementSize); return newArray; } // returns a copy of a pointer array 'array' with 'numExclude' elements, // starting from startpos, removed. void ** excludeArrayPointer(const void **array, size_t oldNumElements, int startPos, int numExclude) { void **newArray; newArray = uio_malloc((oldNumElements - numExclude) * sizeof (void *)); memcpy(newArray, array, startPos * sizeof (void *)); memcpy(&newArray[startPos], &array[startPos + numExclude], (oldNumElements - startPos - numExclude) * sizeof (void *)); return newArray; } // If the given DOS date/time is invalid, the result is unspecified, // but the function won't crash. time_t dosToUnixTime(uio_uint16 date, uio_uint16 tm) { // DOS date has the following format: // bits 0-4 specify the number of the day in the month (1-31). // bits 5-8 specify the number of the month in the year (1-12). // bits 9-15 specify the year number since 1980 (0-127) // DOS time has the fillowing format: // bits 0-4 specify the number of seconds/2 in the minute (0-29) // (only accurate on 2 seconds) // bits 5-10 specify the number of minutes in the hour (0-59) // bits 11-15 specify the number of hours since midnight (0-23) int year, month, day; int hours, minutes, seconds; long result; static const int daysUntilMonth[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 334, 334, 334, 334 }; // The last 4 entries are there so that there's no // invalid memory access if the date is invalid. year = date >> 9; month = ((date >> 5) - 1) & 0x0f; // Number in [0..15] day = (date - 1) & 0x1f; // Number in [0..31] hours = tm >> 11; minutes = (tm >> 5) & 0x3f; seconds = (tm & 0x1f) * 2; // Even number in [0..62] result = year * 365 + daysUntilMonth[month] + day; // Count the (non-leap) days in all those years // Add a leapday for each 4th year if (year % 4 == 0 && month <= 2) { // The given date is a leap-year but the leapday hasn't occured yet. result += year / 4; } else { result += 1 + year / 4; } // result now is the number of days between 1980-01-01 and the given day. // Add the days between 1970-01-01 and 1980-01-01 // (2 leapdays in this period) result += 365 * 10 + 2; result = (result * 24) + hours; // days to hours result = (result * 60) + minutes; // hours to minutes result = (result * 60) + seconds; // minutes to seconds return (time_t) result; } char * dosToUnixPath(const char *path) { const char *srcPtr; char *result, *dstPtr; size_t skip; result = uio_malloc(strlen(path) + 1); srcPtr = path; dstPtr = result; // A UNC path will look like this: "\\server\share/..."; the first two // characters will be backslashes, and the separator between the server // and the share too. The rest will be slashes. // The goal is that at every forward slash, the path should be // stat()'able. skip = uio_skipUNCServerShare(srcPtr); if (skip != 0) { char *slash; memcpy(dstPtr, srcPtr, skip); slash = memchr(srcPtr + 2, '/', skip - 2); if (slash != NULL) *slash = '\\'; srcPtr += skip; dstPtr += skip; } while (*srcPtr != '\0') { if (*srcPtr == '\\') { *dstPtr = '/'; } else *dstPtr = *srcPtr; srcPtr++; dstPtr++; } *dstPtr = '\0'; return result; } uqm-0.6.2/sc2/src/sc2code/libs/uio/zip/0000755000175000017500000000000010552600274016147 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/uio/zip/zip.h0000600000175000017500000000620610543202050017104 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ typedef struct zip_Handle *uio_NativeHandle; typedef void *uio_GPRootExtra; typedef struct zip_GPFileData *uio_GPFileExtra; typedef struct zip_GPFileData *uio_GPDirExtra; typedef struct uio_GPDirEntries_Iterator *uio_NativeEntriesContext; #define uio_INTERNAL_PHYSICAL #include "../gphys.h" #include "../iointrn.h" #include "../uioport.h" #include "../physical.h" #include "../types.h" #include "../fileblock.h" #include #include #include // zip_USE_HEADERS determinines what header for files within a .zip file // is used when building the directory structure. // Set to 'zip_USE_CENTRAL_HEADERS' to use the central directory header, // set to 'zip_USE_LOCAL_HEADERS' to use the local file header. // Central is highly adviced: it uses much less seeking, and hence is much // faster. #define zip_USE_HEADERS zip_USE_CENTRAL_HEADERS #define zip_USE_CENTRAL_HEADERS 1 #define zip_USE_LOCAL_HEADERS 2 typedef struct zip_GPFileData { off_t compressedSize; off_t uncompressedSize; uio_uint16 compressionFlags; uio_uint16 compressionMethod; #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS off_t headerOffset; // start of the local header for this file #endif off_t fileOffset; // start of the compressed data in the .zip file uid_t uid; gid_t gid; mode_t mode; time_t atime; // access time time_t mtime; // modification time time_t ctime; // change time } zip_GPFileData; typedef zip_GPFileData zip_GPDirData; // TODO: some of the fields from zip_GPFileData are not needed for // directories. A few bytes could be saved here by making a seperate // structure. typedef struct zip_Handle { uio_GPFile *file; z_stream zipStream; uio_FileBlock *fileBlock; off_t uncompressedOffset; // seek location in the uncompressed stream off_t compressedOffset; // seek location in the compressed stream, from the start // of the compressed file } zip_Handle; uio_PRoot *zip_mount(uio_Handle *handle, int flags); int zip_umount(struct uio_PRoot *); uio_Handle *zip_open(uio_PDirHandle *pDirHandle, const char *file, int flags, mode_t mode); void zip_close(uio_Handle *handle); int zip_fstat(uio_Handle *handle, struct stat *statBuf); int zip_stat(uio_PDirHandle *pDirHandle, const char *name, struct stat *statBuf); ssize_t zip_read(uio_Handle *handle, void *buf, size_t count); off_t zip_seek(uio_Handle *handle, off_t offset, int whence); uqm-0.6.2/sc2/src/sc2code/libs/uio/zip/zip.c0000600000175000017500000013065410543202050017104 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * This file makes use of zlib (http://www.gzip.org/zlib/) * * References: * The .zip format description from PKWare: * http://www.pkware.com/products/enterprise/white_papers/appnote.html * The .zip format description from InfoZip: * ftp://ftp.info-zip.org/pub/infozip/doc/appnote-011203-iz.zip */ #include #include #include #include #include "zip.h" #include "../physical.h" #include "../uioport.h" #include "../paths.h" #include "../uioutils.h" #ifdef uio_MEM_DEBUG # include "../memdebug.h" #endif static int zip_badFile(zip_GPFileData *gPFileData, char *fileName); static int zip_fillDirStructure(uio_GPDir *top, uio_Handle *handle); #if zip_USE_HEADERS == zip_USE_LOCAL_HEADERS static int zip_fillDirStructureLocal(uio_GPDir *top, uio_Handle *handle); static int zip_fillDirStructureLocalProcessEntry(uio_GPDir *topGPDir, uio_FileBlock *fileBlock, off_t *pos); #endif #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS static off_t zip_findEndOfCentralDirectoryRecord(uio_Handle *handle, uio_FileBlock *fileBlock); static int zip_fillDirStructureCentral(uio_GPDir *top, uio_Handle *handle); static int zip_fillDirStructureCentralProcessEntry(uio_GPDir *topGPDir, uio_FileBlock *fileBlock, off_t *pos); static int zip_updatePFileDataFromLocalFileHeader(zip_GPFileData *gPFileData, uio_FileBlock *fileBlock, int pos); int zip_updateFileDataFromLocalHeader(uio_Handle *handle, zip_GPFileData *gPFileData); #endif static int zip_fillDirStructureProcessExtraFields( uio_FileBlock *fileBlock, off_t extraFieldLength, zip_GPFileData *gPFileData, const char *path, off_t pos, uio_bool central); static inline int zip_foundFile(uio_GPDir *gPDir, const char *path, zip_GPFileData *gPFileData); static inline int zip_foundDir(uio_GPDir *gPDir, const char *dirName, zip_GPDirData *gPDirData); static int zip_initZipStream(z_stream *zipStream); static int zip_unInitZipStream(z_stream *zipStream); static int zip_reInitZipStream(z_stream *zipStream); static voidpf zip_alloc(voidpf opaque, uInt items, uInt size); static void zip_free(voidpf opaque, voidpf address); static inline zip_GPFileData * zip_GPFileData_new(void); static inline void zip_GPFileData_delete(zip_GPFileData *gPFileData); static inline zip_GPFileData *zip_GPFileData_alloc(void); static inline void zip_GPFileData_free(zip_GPFileData *gPFileData); static inline void zip_GPDirData_delete(zip_GPDirData *gPDirData); static inline void zip_GPDirData_free(zip_GPDirData *gPDirData); static ssize_t zip_readStored(uio_Handle *handle, void *buf, size_t count); static ssize_t zip_readDeflated(uio_Handle *handle, void *buf, size_t count); static off_t zip_seekStored(uio_Handle *handle, off_t offset); static off_t zip_seekDeflated(uio_Handle *handle, off_t offset); uio_FileSystemHandler zip_fileSystemHandler = { /* .init = */ NULL, /* .unInit = */ NULL, /* .cleanup = */ NULL, /* .mount = */ zip_mount, /* .umount = */ uio_GPRoot_umount, /* .close = */ zip_close, /* .fstat = */ zip_fstat, /* .stat = */ zip_stat, /* .mkdir = */ NULL, /* .open = */ zip_open, /* .read = */ zip_read, /* .rename = */ NULL, /* .rmdir = */ NULL, /* .seek = */ zip_seek, /* .write = */ NULL, /* .unlink = */ NULL, /* .openEntries = */ uio_GPDir_openEntries, /* .readEntries = */ uio_GPDir_readEntries, /* .closeEntries = */ uio_GPDir_closeEntries, /* .getPDirEntryHandle = */ uio_GPDir_getPDirEntryHandle, /* .deletePRootExtra = */ uio_GPRoot_delete, /* .deletePDirHandleExtra = */ uio_GPDirHandle_delete, /* .deletePFileHandleExtra = */ uio_GPFileHandle_delete, }; uio_GPRoot_Operations zip_GPRootOperations = { /* .fillGPDir = */ NULL, /* .deleteGPRootExtra = */ NULL, /* .deleteGPDirExtra = */ zip_GPDirData_delete, /* .deleteGPFileExtra = */ zip_GPFileData_delete, }; #define NUM_COMPRESSION_METHODS 11 /* * [0] = stored uncompressed * [1] = Shrunk * [2] = Reduced with compression factor 1 * [3] = Reduced with compression factor 2 * [4] = Reduced with compression factor 3 * [5] = Reduced with compression factor 4 * [6] = Imploded * [7] = Reserved for Tokenizing * [8] = Deflated * [9] = Deflate64 * [10] = "PKWARE Data Compression Library Imploding" */ static const uio_bool zip_compressionMethodSupported[NUM_COMPRESSION_METHODS] = { true, false, false, false, false, false, false, false, true, false, false }; typedef ssize_t (*zip_readFunctionType)(uio_Handle *handle, void *buf, size_t count); zip_readFunctionType zip_readMethods[NUM_COMPRESSION_METHODS] = { zip_readStored, NULL, NULL, NULL, NULL, NULL, NULL, NULL, zip_readDeflated, NULL, NULL }; typedef off_t (*zip_seekFunctionType)(uio_Handle *handle, off_t offset); zip_seekFunctionType zip_seekMethods[NUM_COMPRESSION_METHODS] = { zip_seekStored, NULL, NULL, NULL, NULL, NULL, NULL, NULL, zip_seekDeflated, NULL, NULL }; typedef enum { zip_OSType_FAT, zip_OSType_Amiga, zip_OSType_OpenVMS, zip_OSType_UNIX, zip_OSType_VMCMS, zip_OSType_AtariST, zip_OSType_HPFS, zip_OSType_HFS, zip_OSType_ZSystem, zip_OSType_CPM, zip_OSType_TOPS20, zip_OSType_NTFS, zip_OSType_QDOS, zip_OSType_Acorn, zip_OSType_VFAT, zip_OSType_MVS, zip_OSType_BeOS, zip_OSType_Tandem, zip_numOSTypes } zip_OSType; #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS static mode_t zip_makeFileMode(zip_OSType creatorOS, uio_uint32 modeBytes); #endif #define zip_INPUT_BUFFER_SIZE 0x10000 // TODO: make this configurable a la sysctl? #define zip_SEEK_BUFFER_SIZE zip_INPUT_BUFFER_SIZE void zip_close(uio_Handle *handle) { zip_Handle *zip_handle; #if defined(DEBUG) && DEBUG > 1 fprintf(stderr, "zip_close - handle=%p\n", (void *) handle); #endif zip_handle = handle->native; uio_GPFile_unref(zip_handle->file); zip_unInitZipStream(&zip_handle->zipStream); uio_closeFileBlock(zip_handle->fileBlock); uio_free(zip_handle); } static void zip_fillStat(struct stat *statBuf, const zip_GPFileData *gPFileData) { memset(statBuf, '\0', sizeof (struct stat)); statBuf->st_size = gPFileData->uncompressedSize; statBuf->st_uid = gPFileData->uid; statBuf->st_gid = gPFileData->gid; statBuf->st_mode = gPFileData->mode; statBuf->st_atime = gPFileData->atime; statBuf->st_mtime = gPFileData->mtime; statBuf->st_ctime = gPFileData->ctime; } int zip_fstat(uio_Handle *handle, struct stat *statBuf) { #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS if (handle->native->file->extra->fileOffset == -1) { // The local header wasn't read in yet. if (zip_updateFileDataFromLocalHeader(handle->root->handle, handle->native->file->extra) == -1) { // errno is set return -1; } } #endif zip_fillStat(statBuf, handle->native->file->extra); return 0; } int zip_stat(uio_PDirHandle *pDirHandle, const char *name, struct stat *statBuf) { uio_GPDirEntry *entry; if (name[0] == '.' && name[1] == '\0') { entry = (uio_GPDirEntry *) pDirHandle->extra; } else { entry = uio_GPDir_getGPDirEntry(pDirHandle->extra, name); if (entry == NULL) { errno = ENOENT; return -1; } } if (uio_GPDirEntry_isDir(entry) && entry->extra == NULL) { // No information about this directory was stored. // We'll have to make something up. memset(statBuf, '\0', sizeof (struct stat)); statBuf->st_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXOTH | S_IROTH | S_IWOTH | S_IXOTH; statBuf->st_uid = 0; statBuf->st_gid = 0; return 0; } #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS if (((zip_GPFileData *) entry->extra)->fileOffset == -1) { // The local header wasn't read in yet. if (zip_updateFileDataFromLocalHeader(pDirHandle->pRoot->handle, (zip_GPFileData *) entry->extra) == -1) { // errno is set return -1; } } #endif zip_fillStat(statBuf, (zip_GPFileData *) entry->extra); return 0; } /* * Function name: zip_open * Description: open a file in zip file * Arguments: pDirHandle - handle to the dir where to open the file * name - the name of the file to open * flags - flags, as to stdio open() * mode - mode, as to stdio open() * Returns: handle, as from stdio open() * If failed, errno is set and handle is -1. */ uio_Handle * zip_open(uio_PDirHandle *pDirHandle, const char *name, int flags, mode_t mode) { zip_Handle *handle; uio_GPFile *gPFile; #if defined(DEBUG) && DEBUG > 1 fprintf(stderr, "zip_open - pDirHandle=%p name=%s flags=%d mode=0%o\n", (void *) pDirHandle, name, flags, mode); #endif if ((flags & O_ACCMODE) != O_RDONLY) { errno = EACCES; return NULL; } gPFile = (uio_GPFile *) uio_GPDir_getGPDirEntry(pDirHandle->extra, name); if (gPFile == NULL) { errno = ENOENT; return NULL; } #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS if (gPFile->extra->fileOffset == -1) { // The local header wasn't read in yet. if (zip_updateFileDataFromLocalHeader(pDirHandle->pRoot->handle, gPFile->extra) == -1) { // errno is set return NULL; } } #endif handle = uio_malloc(sizeof (zip_Handle)); uio_GPFile_ref(gPFile); handle->file = gPFile; handle->fileBlock = uio_openFileBlock2(pDirHandle->pRoot->handle, gPFile->extra->fileOffset, gPFile->extra->compressedSize); if (handle->fileBlock == NULL) { // errno is set return NULL; } if (zip_initZipStream(&handle->zipStream) == -1) { uio_GPFile_unref(gPFile); uio_closeFileBlock(handle->fileBlock); return NULL; } handle->compressedOffset = 0; handle->uncompressedOffset = 0; (void) mode; return uio_Handle_new(pDirHandle->pRoot, handle, flags); } ssize_t zip_read(uio_Handle *handle, void *buf, size_t count) { ssize_t result; #if defined(DEBUG) && DEBUG > 1 fprintf(stderr, "zip_read - handle=%p buf=%p count=%d: ", (void *) handle, (void *) buf, count); #endif result = zip_readMethods[handle->native->file->extra->compressionMethod] (handle, buf, count); #if defined(DEBUG) && DEBUG > 1 fprintf(stderr, "%d\n", result); #endif return result; } static ssize_t zip_readStored(uio_Handle *handle, void *buf, size_t count) { int numBytes; zip_Handle *zipHandle; zipHandle = handle->native; numBytes = uio_copyFileBlock(zipHandle->fileBlock, zipHandle->uncompressedOffset, buf, count); if (numBytes == -1) { // errno is set return -1; } zipHandle->uncompressedOffset += numBytes; zipHandle->compressedOffset += numBytes; return numBytes; } static ssize_t zip_readDeflated(uio_Handle *handle, void *buf, size_t count) { zip_Handle *zipHandle; int inflateResult; zipHandle = handle->native; if (count > ((zip_GPFileData *) (zipHandle->file->extra))-> uncompressedSize - zipHandle->zipStream.total_out) count = ((zip_GPFileData *) (zipHandle->file->extra))-> uncompressedSize - zipHandle->zipStream.total_out; zipHandle->zipStream.next_out = (Bytef *) buf; zipHandle->zipStream.avail_out = count; while (zipHandle->zipStream.avail_out > 0) { if (zipHandle->zipStream.avail_in == 0) { ssize_t numBytes; numBytes = uio_accessFileBlock(zipHandle->fileBlock, zipHandle->compressedOffset, zip_INPUT_BUFFER_SIZE, (char **) &zipHandle->zipStream.next_in); if (numBytes == -1) { // errno is set return -1; } #if 0 if (numBytes == 0) { if (zipHandle->uncompressedOffset != zipHandle->file->extra->uncompressedSize) { // premature eof errno = EIO; return -1; } break; } #endif zipHandle->zipStream.avail_in = numBytes; zipHandle->compressedOffset += numBytes; } inflateResult = inflate(&zipHandle->zipStream, Z_SYNC_FLUSH); zipHandle->uncompressedOffset = zipHandle->zipStream.total_out; if (inflateResult == Z_STREAM_END) { // Everything is decompressed break; } if (inflateResult != Z_OK) { switch (inflateResult) { case Z_VERSION_ERROR: fprintf(stderr, "Error: Incompatible version problem for " " decompression.\n"); break; case Z_NEED_DICT: fprintf(stderr, "Error: Decompressing requires " "preset dictionary.\n"); break; case Z_DATA_ERROR: fprintf(stderr, "Error: Compressed file is corrupted.\n"); break; case Z_STREAM_ERROR: // This means zipHandle->zipStream is bad, which is // most likely an error in the code using zlib. fprintf(stderr, "Fatal: internal error using zlib.\n"); abort(); break; case Z_MEM_ERROR: fprintf(stderr, "Error: Not enough memory available " "while decompressing.\n"); break; case Z_BUF_ERROR: // No progress possible. Probably caused by premature // end of input file. fprintf(stderr, "Error: When decompressing: premature " "end of input file.\n"); errno = EIO; return -1; #if 0 // If this happens, either the input buffer is empty // or the output buffer is full. This should not happen. fprintf(stderr, "Fatal: internal error using zlib: " " no progress is possible in decompression.\n"); abort(); break; #endif default: fprintf(stderr, "Fatal: unknown error from inflate().\n"); abort(); } if (zipHandle->zipStream.msg != NULL) fprintf(stderr, "ZLib reports: %s\n", zipHandle->zipStream.msg); errno = EIO; // Using EIO to report an error in the backend. return -1; } } return count - zipHandle->zipStream.avail_out; } off_t zip_seek(uio_Handle *handle, off_t offset, int whence) { zip_Handle *zipHandle; #if defined(DEBUG) && DEBUG > 1 fprintf(stderr, "zip_seek - handle=%p offset=%d whence=%s\n", (void *) handle, (int) offset, whence == SEEK_SET ? "SEEK_SET" : whence == SEEK_CUR ? "SEEK_CUR" : whence == SEEK_END ? "SEEK_END" : "INVALID"); #endif zipHandle = handle->native; assert(whence == SEEK_SET || whence == SEEK_CUR || whence == SEEK_END); switch(whence) { case SEEK_SET: break; case SEEK_CUR: offset += zipHandle->uncompressedOffset; break; case SEEK_END: offset += zipHandle->file->extra->uncompressedSize; break; } if (offset < 0) { offset = 0; } else if (offset > zipHandle->file->extra->uncompressedSize) { offset = zipHandle->file->extra->uncompressedSize; } return zip_seekMethods[handle->native->file->extra->compressionMethod] (handle, offset); } static off_t zip_seekStored(uio_Handle *handle, off_t offset) { zip_Handle *zipHandle; zipHandle = handle->native; if (offset > zipHandle->file->extra->uncompressedSize) offset = zipHandle->file->extra->uncompressedSize; zipHandle->compressedOffset = offset; zipHandle->uncompressedOffset = offset; return offset; } static off_t zip_seekDeflated(uio_Handle *handle, off_t offset) { zip_Handle *zipHandle; zipHandle = handle->native; if (offset < zipHandle->uncompressedOffset) { // The new offset is earlier than the current offset. We need to // seek from the beginning. if (zip_reInitZipStream(&zipHandle->zipStream) == -1) { // Need to abort. Handle would get in an inconsistent state. // Should not fail anyhow. fprintf(stderr, "Fatal: Could not reinitialise zip stream: " "%s.\n", strerror(errno)); abort(); } zipHandle->compressedOffset = 0; zipHandle->uncompressedOffset = 0; } if (offset == zipHandle->uncompressedOffset) return offset; // Seek from the current position. { char *buffer; ssize_t numRead; size_t toRead; buffer = uio_malloc(zip_SEEK_BUFFER_SIZE); toRead = offset - zipHandle->uncompressedOffset; while (toRead > 0) { numRead = zip_read(handle, buffer, toRead < zip_SEEK_BUFFER_SIZE ? toRead : zip_SEEK_BUFFER_SIZE); if (numRead == -1) { fprintf(stderr, "Warning: Could not read zipped file: %s\n", strerror(errno)); break; // The current location is returned. } toRead -= numRead; } uio_free(buffer); } return zipHandle->uncompressedOffset; } uio_PRoot * zip_mount(uio_Handle *handle, int flags) { uio_PRoot *result; uio_PDirHandle *rootDirHandle; if ((flags & uio_MOUNT_RDONLY) != uio_MOUNT_RDONLY) { errno = EACCES; return NULL; } uio_Handle_ref(handle); result = uio_GPRoot_makePRoot( uio_getFileSystemHandler(uio_FSTYPE_ZIP), flags, &zip_GPRootOperations, NULL, uio_GPRoot_PERSISTENT, handle, NULL, uio_GPDir_COMPLETE); rootDirHandle = uio_PRoot_getRootDirHandle(result); if (zip_fillDirStructure(rootDirHandle->extra, handle) == -1) { int savedErrno = errno; #ifdef DEBUG fprintf(stderr, "Error: failed to read the zip directory " "structure - %d.\n", errno); #endif uio_GPRoot_umount(result); errno = savedErrno; return NULL; } return result; } static int zip_fillDirStructure(uio_GPDir *top, uio_Handle *handle) { #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS return zip_fillDirStructureCentral(top, handle); #endif #if zip_USE_HEADERS == zip_USE_LOCAL_HEADERS return zip_fillDirStructureLocal(top, handle); #endif } #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS static int zip_fillDirStructureCentral(uio_GPDir *top, uio_Handle *handle) { uio_FileBlock *fileBlock; off_t pos; char *buf; ssize_t numBytes; uio_uint16 numEntries; // TODO: use numEntries to initialise the hash table // to a smart size off_t eocdr; off_t startCentralDir; fileBlock = uio_openFileBlock(handle); if (fileBlock == NULL) { // errno is set goto err; } // first find the 'End of Central Directory Record' eocdr = zip_findEndOfCentralDirectoryRecord(handle, fileBlock); if (eocdr == -1) { // errno is set goto err; } numBytes = uio_accessFileBlock(fileBlock, eocdr, 22, &buf); if (numBytes == -1) { // errno is set goto err; } if (numBytes != 22) { errno = EIO; goto err; } numEntries = makeUInt16(buf[10], buf[11]); if (numEntries == 0xffff) { fprintf(stderr, "Error: Zip64 .zip files are not supported.\n"); errno = ENOSYS; goto err; } startCentralDir = makeUInt32(buf[16], buf[17], buf[18], buf[19]); pos = startCentralDir; while (numEntries--) { if (zip_fillDirStructureCentralProcessEntry(top, fileBlock, &pos) == -1) { // errno is set goto err; } } uio_closeFileBlock(fileBlock); return 0; err: { int savedErrno = errno; if (fileBlock != NULL) uio_closeFileBlock(fileBlock); errno = savedErrno; return -1; } } static int zip_fillDirStructureCentralProcessEntry(uio_GPDir *topGPDir, uio_FileBlock *fileBlock, off_t *pos) { char *buf; zip_GPFileData *gPFileData; ssize_t numBytes; uio_uint32 signature; uio_uint16 lastModTime; uio_uint16 lastModDate; uio_uint32 crc; uio_uint16 fileNameLength; uio_uint16 extraFieldLength; uio_uint16 fileCommentLength; char *fileName; zip_OSType creatorOS; off_t nextEntryOffset; numBytes = uio_accessFileBlock(fileBlock, *pos, 46, &buf); if (numBytes != 46) return zip_badFile(NULL, NULL); signature = makeUInt32(buf[0], buf[1], buf[2], buf[3]); if (signature != 0x02014b50) { fprintf(stderr, "Error: Premature end of central directory.\n"); errno = EIO; return -1; } gPFileData = zip_GPFileData_new(); creatorOS = (zip_OSType) buf[5]; gPFileData->compressionFlags = makeUInt16(buf[8], buf[9]); gPFileData->compressionMethod = makeUInt16(buf[10], buf[11]); lastModTime = makeUInt16(buf[12], buf[13]); lastModDate = makeUInt16(buf[14], buf[15]); gPFileData->atime = (time_t) 0; gPFileData->mtime = dosToUnixTime(lastModDate, lastModTime); gPFileData->ctime = (time_t) 0; crc = makeUInt32(buf[16], buf[17], buf[18], buf[19]); gPFileData->compressedSize = makeUInt32(buf[20], buf[21], buf[22], buf[23]); gPFileData->uncompressedSize = makeUInt32(buf[24], buf[25], buf[26], buf[27]); fileNameLength = makeUInt16(buf[28], buf[29]); extraFieldLength = makeUInt16(buf[30], buf[31]); fileCommentLength = makeUInt16(buf[32], buf[33]); gPFileData->uid = 0; gPFileData->gid = 0; gPFileData->mode = zip_makeFileMode(creatorOS, makeUInt32(buf[38], buf[39], buf[40], buf[41])); gPFileData->headerOffset = (off_t) makeSInt32(buf[42], buf[43], buf[44], buf[45]); gPFileData->fileOffset = (off_t) -1; *pos += 46; nextEntryOffset = *pos + fileNameLength + extraFieldLength + fileCommentLength; numBytes = uio_accessFileBlock(fileBlock, *pos, fileNameLength, &buf); if (numBytes != fileNameLength) return zip_badFile(gPFileData, NULL); fileName = uio_malloc(fileNameLength + 1); memcpy(fileName, buf, fileNameLength); fileName[fileNameLength] = '\0'; *pos += fileNameLength; if (gPFileData->compressionMethod >= NUM_COMPRESSION_METHODS || !zip_compressionMethodSupported[gPFileData->compressionMethod]) { fprintf(stderr, "Warning: File '%s' is compressed with " "unsupported method %d - skipped.\n", fileName, gPFileData->compressionMethod); *pos = nextEntryOffset; zip_GPFileData_delete(gPFileData); return 0; } if (gPFileData->compressedSize == (off_t) 0xffffffff || gPFileData->uncompressedSize == (off_t) 0xffffffff || gPFileData->headerOffset < 0) { fprintf(stderr, "Warning: Skipping Zip64 file '%s'\n", fileName); *pos = nextEntryOffset; zip_GPFileData_delete(gPFileData); return 0; } if (isBitSet(gPFileData->compressionFlags, 0)) { fprintf(stderr, "Warning: Skipping encrypted file '%s'\n", fileName); *pos = nextEntryOffset; zip_GPFileData_delete(gPFileData); return 0; } switch (zip_fillDirStructureProcessExtraFields(fileBlock, extraFieldLength, gPFileData, fileName, *pos, true)) { case 0: // file is ok break; case 1: // file is not acceptable - skip file *pos = nextEntryOffset; zip_GPFileData_delete(gPFileData); uio_free(fileName); return 0; case -1: return zip_badFile(gPFileData, fileName); } *pos += extraFieldLength; // If ctime or atime is 0, they will be filled in when the local // file header is read. if (S_ISREG(gPFileData->mode)) { if (zip_foundFile(topGPDir, fileName, gPFileData) == -1) { if (errno == EISDIR) { zip_GPFileData_delete(gPFileData); uio_free(fileName); return 0; } return zip_badFile(gPFileData, fileName); } #if defined(DEBUG) && DEBUG > 1 fprintf(stderr, "Debug: Found file '%s'.\n", fileName); #endif } else if (S_ISDIR(gPFileData->mode)) { if (fileName[fileNameLength - 1] == '/') fileName[fileNameLength - 1] = '\0'; if (zip_foundDir(topGPDir, fileName, gPFileData) == -1) { if (errno == EISDIR) { fprintf(stderr, "Warning: file '%s' already exists as a dir - " "skipped.\n", fileName); zip_GPFileData_delete(gPFileData); uio_free(fileName); return 0; } return zip_badFile(gPFileData, fileName); } #if defined(DEBUG) && DEBUG > 1 fprintf(stderr, "Debug: Found dir '%s'.\n", fileName); #endif } else { fprintf(stderr, "Warning: '%s' is not a regular file, nor a " "directory - skipped.\n", fileName); zip_GPFileData_delete(gPFileData); uio_free(fileName); return 0; } uio_free(fileName); return 0; } static off_t zip_findEndOfCentralDirectoryRecord(uio_Handle *handle, uio_FileBlock *fileBlock) { off_t fileSize; off_t endPos, startPos; char *buf, *bufPtr; ssize_t bufLen; struct stat statBuf; if (uio_fstat(handle, &statBuf) == -1) { // errno is set return -1; } fileSize = statBuf.st_size; startPos = fileSize - 0xffff - 22; // max comment and record size if (startPos < 0) startPos = 0; endPos = fileSize - 22; // last position to be checked bufLen = uio_accessFileBlock(fileBlock, startPos, endPos - startPos + 4, &buf); if (bufLen == -1) { int savedErrno = errno; fprintf(stderr, "Error: Read error while searching for " "'end-of-central-directory record'.\n"); errno = savedErrno; return -1; } if (bufLen != endPos - startPos + 4) { fprintf(stderr, "Error: Read error while searching for " "'end-of-central-directory record'.\n"); errno = EIO; return -1; } bufPtr = buf + (endPos - startPos); while (1) { if (bufPtr < buf) { fprintf(stderr, "Error: Zip file corrupt; could not find " "'end-of-central-directory record'.\n"); errno = EIO; return -1; } if (bufPtr[0] == 0x50 && bufPtr[1] == 0x4b && bufPtr[2] == 0x05 && bufPtr[3] == 0x06) break; bufPtr--; } return startPos + (bufPtr - buf); } static mode_t zip_makeFileMode(zip_OSType creatorOS, uio_uint32 modeBytes) { switch (creatorOS) { case zip_OSType_FAT: case zip_OSType_NTFS: case zip_OSType_VFAT: { // Only the least signigicant byte is relevant. mode_t mode; if (modeBytes == 0) { // File came from standard input return S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; } if (modeBytes & 0x10) { // Directory mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; } else { // Regular file mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; } if (modeBytes & 0x01) { // readonly return mode; } else { // Write allowed return mode | S_IWUSR | S_IWGRP | S_IWOTH; } } case zip_OSType_UNIX: return (mode_t) (modeBytes >> 16); default: fprintf(stderr, "Warning: file created by unknown OS.\n"); return S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; } } // If the data is read from the central directory, certain data // will need to be updated from the local directory when it is needed. // This function does that. // returns 0 for success, -1 for error (errno is set) // NB: Only the fields that may offer new information are checked. // the fields that were already read from the central directory // aren't verified. static int zip_updatePFileDataFromLocalFileHeader(zip_GPFileData *gPFileData, uio_FileBlock *fileBlock, int pos) { ssize_t numBytes; char *buf; uio_uint32 signature; uio_uint16 fileNameLength; uio_uint16 extraFieldLength; numBytes = uio_accessFileBlock(fileBlock, pos, 30, &buf); if (numBytes != 30) { errno = EIO; return -1; } signature = makeUInt32(buf[0], buf[1], buf[2], buf[3]); if (signature != 0x04034b50) { errno = EIO; return -1; } fileNameLength = makeUInt16(buf[26], buf[27]); extraFieldLength = makeUInt16(buf[28], buf[29]); pos += 30 + fileNameLength; switch (zip_fillDirStructureProcessExtraFields(fileBlock, extraFieldLength, gPFileData, "", pos, false)) { case 0: // file is ok break; case 1: // File is not acceptable (but according to the central header // it was) fprintf(stderr, "Warning: according to the central directory " "of a zip file, some file inside is acceptable, " "but according to the local header it isn't.\n"); errno = EIO; return -1; case -1: errno = EIO; return -1; } pos += extraFieldLength; gPFileData->fileOffset = pos; return 0; } #endif /* zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS */ #if zip_USE_HEADERS == zip_USE_LOCAL_HEADERS static int zip_fillDirStructureLocal(uio_GPDir *top, uio_Handle *handle) { uio_FileBlock *fileBlock; off_t pos; char *buf; ssize_t numBytes; pos = uio_lseek(handle, 0, SEEK_SET); if (pos == -1) { int savedErrno = errno; errno = savedErrno; return -1; } if (pos != 0) { errno = EIO; // Using EIO to report an error in the backend. return -1; } // We read all the files from the beginning of the zip file to the end. // (the directory record at the end of the file is ignored) fileBlock = uio_openFileBlock(handle); if (fileBlock == NULL) { // errno is set return -1; } pos = 0; while (1) { uio_uint32 signature; numBytes = uio_accessFileBlock(fileBlock, pos, 4, &buf); if (numBytes == -1) goto err; if (numBytes != 4) break; signature = makeUInt32(buf[0], buf[1], buf[2], buf[3]); if (signature != 0x04034b50) { // End of file data reached. break; } pos += 4; if (zip_fillDirStructureLocalProcessEntry(top, fileBlock, &pos) == -1) goto err; } uio_closeFileBlock(fileBlock); return 0; err: { int savedErrno = errno; uio_closeFileBlock(fileBlock); errno = savedErrno; return -1; } } static int zip_fillDirStructureLocalProcessEntry(uio_GPDir *topGPDir, uio_FileBlock *fileBlock, off_t *pos) { char *buf; zip_GPFileData *gPFileData; ssize_t numBytes; uio_uint16 lastModTime; uio_uint16 lastModDate; uio_uint32 crc; uio_uint16 fileNameLength; uio_uint16 extraFieldLength; char *fileName; off_t nextEntryOffset; numBytes = uio_accessFileBlock(fileBlock, *pos, 26, &buf); if (numBytes != 26) return zip_badFile(NULL, NULL); gPFileData = zip_GPFileData_new(); gPFileData->compressionFlags = makeUInt16(buf[2], buf[3]); gPFileData->compressionMethod = makeUInt16(buf[4], buf[5]); lastModTime = makeUInt16(buf[6], buf[7]); lastModDate = makeUInt16(buf[8], buf[9]); gPFileData->atime = (time_t) 0; gPFileData->mtime = dosToUnixTime(lastModDate, lastModTime); gPFileData->ctime = (time_t) 0; gPFileData->uid = 0; gPFileData->gid = 0; gPFileData->mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; if (!isBitSet(gPFileData->compressionFlags, 3)) { // If bit 3 is not set, this info will be in the data descriptor // behind the file data. crc = makeUInt32(buf[10], buf[11], buf[12], buf[13]); gPFileData->compressedSize = makeUInt32(buf[14], buf[15], buf[16], buf[17]); gPFileData->uncompressedSize = makeUInt32(buf[18], buf[19], buf[20], buf[21]); } fileNameLength = makeUInt16(buf[22], buf[23]); extraFieldLength = makeUInt16(buf[24], buf[25]); *pos += 26; nextEntryOffset = *pos + fileNameLength + extraFieldLength + gPFileData->compressedSize; if (isBitSet(gPFileData->compressionFlags, 3)) { // There's a data descriptor present behind the file data. nextEntryOffset += 16; } if (gPFileData->compressionMethod >= NUM_COMPRESSION_METHODS || !zip_compressionMethodSupported[gPFileData->compressionMethod]) { fprintf(stderr, "Warning: File '%s' is compressed with " "unsupported method %d - skipped.\n", fileName, gPFileData->compressionMethod); *pos = nextEntryOffset; zip_GPFileData_delete(gPFileData); return 0; } if (gPFileData->compressedSize == (off_t) 0xffffffff || gPFileData->uncompressedSize == (off_t) 0xffffffff) { fprintf(stderr, "Warning: Skipping Zip64 file '%s'\n", fileName); *pos = nextEntryOffset; zip_GPFileData_delete(gPFileData); return 0; } if (isBitSet(gPFileData->compressionFlags, 0)) { fprintf(stderr, "Warning: Skipping encrypted file '%s'\n", fileName); *pos = nextEntryOffset; zip_GPFileData_delete(gPFileData); return 0; } numBytes = uio_accessFileBlock(fileBlock, *pos, fileNameLength, &buf); if (numBytes != fileNameLength) return zip_badFile(gPFileData, NULL); *pos += fileNameLength; if (buf[fileNameLength - 1] == '/') { gPFileData->mode |= S_IFDIR; fileNameLength--; } else gPFileData->mode |= S_IFREG; fileName = uio_malloc(fileNameLength + 1); memcpy(fileName, buf, fileNameLength); fileName[fileNameLength] = '\0'; switch (zip_fillDirStructureProcessExtraFields(fileBlock, extraFieldLength, gPFileData, fileName, *pos, false)) { case 0: // file is ok break; case 1: // file is not acceptable - skip file *pos = nextEntryOffset; zip_GPFileData_delete(gPFileData); uio_free(fileName); return 0; case -1: return zip_badFile(gPFileData, fileName); } *pos += extraFieldLength; gPFileData->fileOffset = *pos; *pos += gPFileData->compressedSize; if (isBitSet(gPFileData->compressionFlags, 3)) { // Now comes a data descriptor. // The PKWare version (which was never used) misses the signature. // The InfoZip version is used below. uio_uint32 signature; numBytes = uio_accessFileBlock(fileBlock, *pos, 16, &buf); if (numBytes != 16) return zip_badFile(gPFileData, fileName); signature = makeUInt32(buf[0], buf[1], buf[2], buf[3]); if (signature != 0x08074b50) return zip_badFile(gPFileData, fileName); crc = makeUInt32(buf[4], buf[5], buf[6], buf[7]); gPFileData->compressedSize = makeUInt32(buf[8], buf[9], buf[10], buf[11]); gPFileData->uncompressedSize = makeUInt32(buf[12], buf[13], buf[14], buf[15]); } if (gPFileData->ctime == (time_t) 0) gPFileData->ctime = gPFileData->mtime; if (gPFileData->atime == (time_t) 0) gPFileData->atime = gPFileData->mtime; if (S_ISREG(gPFileData->mode)) { if (zip_foundFile(topGPDir, fileName, gPFileData) == -1) { if (errno == EISDIR) { zip_GPFileData_delete(gPFileData); uio_free(fileName); return 0; } return zip_badFile(gPFileData, fileName); } #if defined(DEBUG) && DEBUG > 1 fprintf(stderr, "Debug: Found file '%s'.\n", fileName); #endif } else if (S_ISDIR(gPFileData->mode)) { if (fileName[fileNameLength - 1] == '/') fileName[fileNameLength - 1] = '\0'; if (zip_foundDir(topGPDir, fileName, gPFileData) == -1) { if (errno == EISDIR) { fprintf(stderr, "Warning: file '%s' already exists as a dir - " "skipped.\n", fileName); zip_GPFileData_delete(gPFileData); uio_free(fileName); return 0; } return zip_badFile(gPFileData, fileName); } #if defined(DEBUG) && DEBUG > 1 fprintf(stderr, "Debug: Found dir '%s'.\n", fileName); #endif } else { fprintf(stderr, "Warning: '%s' is not a regular file, nor a " "directory - skipped.\n", fileName); zip_GPFileData_delete(gPFileData); uio_free(fileName); return 0; } uio_free(fileName); return 0; } #endif /* zip_USE_HEADERS == zip_USE_LOCAL_HEADERS */ #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS int zip_updateFileDataFromLocalHeader(uio_Handle *handle, zip_GPFileData *gPFileData) { uio_FileBlock *fileBlock; fileBlock = uio_openFileBlock(handle); if (fileBlock == NULL) { // errno is set return -1; } if (zip_updatePFileDataFromLocalFileHeader(gPFileData, fileBlock, gPFileData->headerOffset) == -1) { int savedErrno = errno; uio_closeFileBlock(fileBlock); errno = savedErrno; return -1; } if (gPFileData->ctime == (time_t) 0) gPFileData->ctime = gPFileData->mtime; if (gPFileData->atime == (time_t) 0) gPFileData->atime = gPFileData->mtime; uio_closeFileBlock(fileBlock); return 0; } #endif // If the zip file is bad, -1 is returned (no errno set!) // If the file in the zip file should be skipped, 1 is returned. // If the file in the zip file is ok, 0 is returned. static int zip_fillDirStructureProcessExtraFields(uio_FileBlock *fileBlock, off_t extraFieldLength, zip_GPFileData *gPFileData, const char *fileName, off_t pos, uio_bool central) { off_t posEnd; uio_uint16 headerID; ssize_t dataSize; ssize_t numBytes; char *buf; posEnd = pos + extraFieldLength; while (pos < posEnd) { numBytes = uio_accessFileBlock(fileBlock, pos, 4, &buf); if (numBytes != 4) return -1; headerID = makeUInt16(buf[0], buf[1]); dataSize = (ssize_t) makeUInt16(buf[2], buf[3]); pos += 4; numBytes = uio_accessFileBlock(fileBlock, pos, dataSize, &buf); if (numBytes != dataSize) return -1; switch(headerID) { case 0x000d: // 'Unix0' // fallthrough case 0x5855: // 'Unix1' gPFileData->atime = (time_t) makeUInt32( buf[0], buf[1], buf[2], buf[3]); gPFileData->mtime = (time_t) makeUInt32( buf[4], buf[5], buf[6], buf[7]); if (central) break; if (dataSize > 8) { gPFileData->uid = (uid_t) makeUInt16(buf[8], buf[9]); gPFileData->gid = (uid_t) makeUInt16(buf[10], buf[11]); } // Unix0 has an extra (ignored) field at the end. break; case 0x5455: { // 'time' uio_uint8 flags; const char *bufPtr; flags = buf[0]; bufPtr = buf + 1; if (isBitSet(flags, 0)) { // modification time is present gPFileData->mtime = (time_t) makeUInt32( bufPtr[0], bufPtr[1], bufPtr[2], bufPtr[3]); bufPtr += 4; } // The flags field, even in the central header, specifies what // is present in the local header. // The central header only contains a field for the mtime // when it is present in the local header too, and // never contains fields for other times. if (central) break; if (isBitSet(flags, 1)) { // modification time is present gPFileData->atime = (time_t) makeUInt32( bufPtr[0], bufPtr[1], bufPtr[2], bufPtr[3]); bufPtr += 4; } // Creation time and possible other times are skipped. break; } case 0x7855: // 'Unix2' if (central) break; gPFileData->uid = (uid_t) makeUInt16(buf[0], buf[1]); gPFileData->gid = (uid_t) makeUInt16(buf[2], buf[3]); break; case 0x756e: { // 'Unix3' mode_t mode; mode = (mode_t) makeUInt16(buf[4], buf[5]); if (!S_ISREG(mode) && !S_ISDIR(mode)) { fprintf(stderr, "Warning: Skipping '%s'; not a regular " "file, nor a directory.\n", fileName); return 1; } gPFileData->uid = (uid_t) makeUInt16(buf[10], buf[11]); gPFileData->gid = (uid_t) makeUInt16(buf[12], buf[13]); break; } default: #ifdef DEBUG fprintf(stderr, "Debug: Extra field 0x%04x unsupported, " "used for file '%s' - ignored.\n", headerID, fileName); #endif break; } // switch pos += dataSize; } // while if (pos != posEnd) return -1; return 0; } static int zip_badFile(zip_GPFileData *gPFileData, char *fileName) { fprintf(stderr, "Error: Bad file format for .zip file.\n"); if (gPFileData != NULL) zip_GPFileData_delete(gPFileData); if (fileName != NULL) uio_free(fileName); errno = EINVAL; // Is this the best choice? return -1; } static inline int zip_foundFile(uio_GPDir *gPDir, const char *path, zip_GPFileData *gPFileData) { uio_GPFile *file; size_t pathLen; const char *rest; const char *pathEnd; const char *start, *end; char *buf; if (path[0] == '/') path++; pathLen = strlen(path); if (path[pathLen - 1] == '/') { fprintf(stderr, "Warning: '%s' is not a valid file name - skipped.\n", path); errno = EISDIR; return -1; } pathEnd = path + pathLen; switch (uio_walkGPPath(gPDir, path, pathLen, &gPDir, &rest)) { case 0: // The entire path was matched. The last part was not supposed // to be a dir. fprintf(stderr, "Warning: '%s' already exists as a dir - " "skipped.\n", path); errno = EISDIR; return -1; case ENOTDIR: fprintf(stderr, "Warning: A component to '%s' is not a " "directory - file skipped.\n", path); errno = ENOTDIR; return -1; case ENOENT: break; } buf = uio_malloc(pathLen + 1); getFirstPathComponent(rest, pathEnd, &start, &end); while (1) { uio_GPDir *newGPDir; if (end == start || (end - start == 1 && start[0] == '.') || (end - start == 2 && start[0] == '.' && start[1] == '.')) { fprintf(stderr, "Warning: file '%s' has an invalid path - " "skipped.\n", path); uio_free(buf); errno = EINVAL; return -1; } if (end == pathEnd) { // This is the last component; it should be the name of the dir. rest = start; break; } memcpy(buf, start, end - start); buf[end - start] = '\0'; newGPDir = uio_GPDir_prepareSubDir(gPDir, buf); newGPDir->flags |= uio_GPDir_COMPLETE; // It will be complete when we're done adding // all files, and it won't be used before that. uio_GPDir_commitSubDir(gPDir, buf, newGPDir); gPDir = newGPDir; getNextPathComponent(pathEnd, &start, &end); } uio_free(buf); file = uio_GPFile_new(gPDir->pRoot, (uio_GPFileExtra) gPFileData, uio_gPFileFlagsFromPRootFlags(gPDir->pRoot->flags)); uio_GPDir_addFile(gPDir, rest, file); return 0; } static inline int zip_foundDir(uio_GPDir *gPDir, const char *path, zip_GPDirData *gPDirData) { size_t pathLen; const char *pathEnd; const char *rest; const char *start, *end; char *buf; if (path[0] == '/') path++; pathLen = strlen(path); pathEnd = path + pathLen; switch (uio_walkGPPath(gPDir, path, pathLen, &gPDir, &rest)) { case 0: // The dir already exists. Only need to add gPDirData if (gPDir->extra != NULL) { fprintf(stderr, "Warning: '%s' is present more than once " "in the zip file. The last entry will be used.\n", path); zip_GPDirData_delete(gPDir->extra); } gPDir->extra = gPDirData; return 0; case ENOTDIR: fprintf(stderr, "Warning: A component of '%s' is not a " "directory - file skipped.\n", path); errno = ENOTDIR; return -1; case ENOENT: break; } buf = uio_malloc(pathLen + 1); getFirstPathComponent(rest, pathEnd, &start, &end); while (start < pathEnd) { uio_GPDir *newGPDir; if (end == start || (end - start == 1 && start[0] == '.') || (end - start == 2 && start[0] == '.' && start[1] == '.')) { fprintf(stderr, "Warning: directory '%s' has an invalid path - " "skipped.\n", path); uio_free(buf); errno = EINVAL; return -1; } memcpy(buf, start, end - start); buf[end - start] = '\0'; newGPDir = uio_GPDir_prepareSubDir(gPDir, buf); newGPDir->flags |= uio_GPDir_COMPLETE; // It will be complete when we're done adding // all files, and it won't be used before that. uio_GPDir_commitSubDir(gPDir, buf, newGPDir); gPDir = newGPDir; getNextPathComponent(pathEnd, &start, &end); } gPDir->extra = gPDirData; uio_free(buf); return 0; } static int zip_initZipStream(z_stream *zipStream) { int retVal; zipStream->next_in = Z_NULL; zipStream->avail_in = 0; zipStream->zalloc = zip_alloc; zipStream->zfree = zip_free; zipStream->opaque = NULL; retVal = inflateInit2(zipStream, -MAX_WBITS); // Negative window size means that no zlib header is present. // This feature is undocumented in zlib, but it's used // in the minizip program from the zlib contrib dir. // The absolute value is used as real Window size. if (retVal != Z_OK) { switch (retVal) { case Z_MEM_ERROR: fprintf(stderr, "Error: Not enough memory available for " " decompression.\n"); break; case Z_VERSION_ERROR: fprintf(stderr, "Error: Incompatible version problem for " " decompression.\n"); break; default: fprintf(stderr, "Fatal: unknown error from inflateInit().\n"); abort(); } if (zipStream->msg != NULL) fprintf(stderr, "ZLib reports: %s\n", zipStream->msg); errno = EIO; // Using EIO to report an error in the backend. return -1; } return 0; } static int zip_unInitZipStream(z_stream *zipStream) { int retVal; retVal = inflateEnd(zipStream); if (retVal != Z_OK) { switch (retVal) { case Z_STREAM_ERROR: // This means zipStream is bad, which is most likely an // error in the code using zlib. fprintf(stderr, "Fatal: internal error using zlib.\n"); abort(); break; default: fprintf(stderr, "Fatal: unknown error from inflateEnd().\n"); abort(); } if (zipStream->msg != NULL) fprintf(stderr, "ZLib reports: %s\n", zipStream->msg); errno = EIO; // Using EIO to report an error in the backend. return -1; } return 0; } static int zip_reInitZipStream(z_stream *zipStream) { int retVal; zipStream->next_in = Z_NULL; zipStream->avail_in = 0; retVal = inflateReset(zipStream); if (retVal != Z_OK) { switch (retVal) { case Z_STREAM_ERROR: // This means zipStream is bad, which is most likely an // error in the code using zlib. fprintf(stderr, "Fatal: internal error using zlib.\n"); abort(); break; default: fprintf(stderr, "Fatal: unknown error from inflateInit().\n"); abort(); } if (zipStream->msg != NULL) fprintf(stderr, "ZLib reports: %s\n", zipStream->msg); errno = EIO; // Using EIO to report an error in the backend. return -1; } return 0; } // Used internally by zlib for allocating memory. static voidpf zip_alloc(voidpf opaque, uInt items, uInt size) { (void) opaque; return (voidpf) uio_calloc((size_t) items, (size_t) size); } // Used internally by zlib for freeing memory. static void zip_free(voidpf opaque, voidpf address) { (void) opaque; uio_free((void *) address); } static inline zip_GPFileData * zip_GPFileData_new(void) { return zip_GPFileData_alloc(); } static inline void zip_GPFileData_delete(zip_GPFileData *gPFileData) { zip_GPFileData_free(gPFileData); } static inline zip_GPFileData * zip_GPFileData_alloc(void) { zip_GPFileData *result = uio_malloc(sizeof (zip_GPFileData)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(zip_GPFileData, (void *) result); #endif return result; } static inline void zip_GPFileData_free(zip_GPFileData *gPFileData) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(zip_GPFileData, (void *) gPFileData); #endif uio_free(gPFileData); } static inline void zip_GPDirData_delete(zip_GPDirData *gPDirData) { zip_GPDirData_free(gPDirData); } static inline void zip_GPDirData_free(zip_GPDirData *gPDirData) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(zip_GPFileData, (void *) gPDirData); #endif uio_free(gPDirData); } uqm-0.6.2/sc2/src/sc2code/libs/uio/zip/Makeinfo0000600000175000017500000000002510543202050017576 0ustar joeyjoeyuqm_CFILES="zip.c" uqm-0.6.2/sc2/src/sc2code/libs/uio/utils.c0000600000175000017500000002270110543202051016632 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include "iointrn.h" #include "ioaux.h" #include "utils.h" static int uio_copyError(uio_Handle *srcHandle, uio_Handle *dstHandle, uio_DirHandle *unlinkHandle, const char *unlinkPath, uio_uint8 *buf); struct uio_StdioAccessHandle { uio_DirHandle *tempRoot; char *tempDirName; uio_DirHandle *tempDir; char *fileName; char *stdioPath; }; static inline uio_StdioAccessHandle *uio_StdioAccessHandle_new( uio_DirHandle *tempRoot, char *tempDirName, uio_DirHandle *tempDir, char *fileName, char *stdioPath); static inline void uio_StdioAccessHandle_delete( uio_StdioAccessHandle *handle); static inline uio_StdioAccessHandle *uio_StdioAccessHandle_alloc(void); static inline void uio_StdioAccessHandle_free(uio_StdioAccessHandle *handle); /* * Copy a file with path srcName to a file with name newName. * If the destination already exists, the operation fails. * Links are followed. * Special files (fifos, char devices, block devices, etc) will be * read as long as there is data available and the destination will be * a regular file with that data. * The new file will have the same permissions as the old. * If an error occurs during copying, an attempt will be made to * remove the copy. */ int uio_copyFile(uio_DirHandle *srcDir, const char *srcName, uio_DirHandle *dstDir, const char *newName) { uio_Handle *src, *dst; struct stat sb; #define BUFSIZE 65536 uio_uint8 *buf, *bufPtr; ssize_t numInBuf, numWritten; src = uio_open(srcDir, srcName, O_RDONLY #ifdef WIN32 | O_BINARY #endif , 0); if (src == NULL) return -1; if (uio_fstat(src, &sb) == -1) return uio_copyError(src, NULL, NULL, NULL, NULL); dst = uio_open(dstDir, newName, O_WRONLY | O_CREAT | O_EXCL #ifdef WIN32 | O_BINARY #endif , sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); if (dst == NULL) return uio_copyError(src, NULL, NULL, NULL, NULL); buf = uio_malloc(BUFSIZE); // This was originally a statically allocated buffer, // but as this function might be run from a thread with // a small Stack, this is better. while (1) { numInBuf = uio_read(src, buf, BUFSIZE); if (numInBuf == -1) { if (errno == EINTR) continue; return uio_copyError(src, dst, dstDir, newName, buf); } if (numInBuf == 0) break; bufPtr = buf; do { numWritten = uio_write(dst, bufPtr, numInBuf); if (numWritten == -1) { if (errno == EINTR) continue; return uio_copyError(src, dst, dstDir, newName, buf); } numInBuf -= numWritten; bufPtr += numWritten; } while (numInBuf > 0); } uio_free(buf); uio_close(src); uio_close(dst); errno = 0; return 0; } /* * Closes srcHandle if it's not -1. * Closes dstHandle if it's not -1. * Removes unlinkpath from the unlinkHandle dir if it's not NULL. * Frees 'buf' if not NULL. * Always returns -1. * errno is what was before the call. */ static int uio_copyError(uio_Handle *srcHandle, uio_Handle *dstHandle, uio_DirHandle *unlinkHandle, const char *unlinkPath, uio_uint8 *buf) { int savedErrno; savedErrno = errno; #ifdef DEBUG fprintf(stderr, "Error while copying: %s\n", strerror(errno)); #endif if (srcHandle != NULL) uio_close(srcHandle); if (dstHandle != NULL) uio_close(dstHandle); if (unlinkPath != NULL) uio_unlink(unlinkHandle, unlinkPath); if (buf != NULL) uio_free(buf); errno = savedErrno; return -1; } #define NUM_TEMP_RETRIES 16 // Retry this many times to create a temporary dir, before giving // up. If undefined, keep trying indefinately. uio_StdioAccessHandle * uio_getStdioAccess(uio_DirHandle *dir, const char *path, int flags, uio_DirHandle *tempDir) { int res; uio_MountHandle *mountHandle; const char *name; char *newPath; char *tempDirName; uio_DirHandle *newDir; uio_FileSystemID fsID; res = uio_getFileLocation(dir, path, flags, &mountHandle, &newPath); if (res == -1) { // errno is set return NULL; } fsID = uio_getMountFileSystemType(mountHandle); if (fsID == uio_FSTYPE_STDIO) { // Current location is usable. return uio_StdioAccessHandle_new(NULL, NULL, NULL, NULL, newPath); } uio_free(newPath); { uio_uint32 dirNum; int i; // Current location is not usable. Create a directory with a // generated name, as a temporary location to store a copy of // the file. dirNum = (uio_uint32) time(NULL); tempDirName = uio_malloc(sizeof "01234567"); for (i = 0; ; i++) { #ifdef NUM_TEMP_RETRIES if (i >= NUM_TEMP_RETRIES) { // Using ENOSPC to report that we couldn't create a // temporary dir, getting EEXIST. uio_free(tempDirName); errno = ENOSPC; return NULL; } #endif sprintf(tempDirName, "%08lx", (unsigned long) dirNum + i); res = uio_mkdir(tempDir, tempDirName, 0700); if (res == -1) { int savedErrno; if (errno == EEXIST) continue; savedErrno = errno; #ifdef DEBUG fprintf(stderr, "Error: Could not create temporary dir: %s\n", strerror(errno)); #endif uio_free(tempDirName); errno = savedErrno; return NULL; } break; } newDir = uio_openDirRelative(tempDir, tempDirName, 0); if (newDir == NULL) { #ifdef DEBUG fprintf(stderr, "Error: Could not open temporary dir: %s\n", strerror(errno)); #endif res = uio_rmdir(tempDir, tempDirName); #ifdef DEBUG if (res == -1) fprintf(stderr, "Warning: Could not remove temporary dir: " "%s.\n", strerror(errno)); #endif uio_free(tempDirName); errno = EIO; return NULL; } // Get the last component of path. This should be the file to // access. name = strrchr(path, '/'); if (name == NULL) name = path; // Copy the file res = uio_copyFile(dir, path, newDir, name); if (res == -1) { int savedErrno = errno; #ifdef DEBUG fprintf(stderr, "Error: Could not copy file to temporary dir: " "%s\n", strerror(errno)); #endif uio_closeDir(newDir); uio_free(tempDirName); errno = savedErrno; return NULL; } } res = uio_getFileLocation(newDir, name, flags, &mountHandle, &newPath); if (res == -1) { int savedErrno = errno; fprintf(stderr, "Error: uio_getStdioAccess: Could not get location " "of temporary dir: %s.\n", strerror(errno)); uio_closeDir(newDir); uio_free(tempDirName); errno = savedErrno; return NULL; } fsID = uio_getMountFileSystemType(mountHandle); if (fsID != uio_FSTYPE_STDIO) { // Temp dir isn't on a stdio fs either. fprintf(stderr, "Error: uio_getStdioAccess: Temporary file location " "isn't on a stdio filesystem.\n"); uio_closeDir(newDir); uio_free(tempDirName); uio_free(newPath); // errno = EXDEV; errno = EINVAL; return NULL; } uio_DirHandle_ref(tempDir); return uio_StdioAccessHandle_new(tempDir, tempDirName, newDir, uio_strdup(name), newPath); } void uio_releaseStdioAccess(uio_StdioAccessHandle *handle) { if (handle->tempDir != NULL) { if (uio_unlink(handle->tempDir, handle->fileName) == -1) { #ifdef DEBUG fprintf(stderr, "Error: Could not remove temporary file: " "%s\n", strerror(errno)); #endif } // Need to free this handle in advance. There should be no handles // to a dir left when removing it. uio_DirHandle_unref(handle->tempDir); handle->tempDir = NULL; if (uio_rmdir(handle->tempRoot, handle->tempDirName) == -1) { #ifdef DEBUG fprintf(stderr, "Error: Could not remove temporary directory: " "%s\n", strerror(errno)); #endif } } uio_StdioAccessHandle_delete(handle); } const char * uio_StdioAccessHandle_getPath(uio_StdioAccessHandle *handle) { return (const char *) handle->stdioPath; } // references to tempRoot and tempDir are not increased. // no copies of arguments are made. // By calling this function control of the values is transfered to // the handle. static inline uio_StdioAccessHandle * uio_StdioAccessHandle_new( uio_DirHandle *tempRoot, char *tempDirName, uio_DirHandle *tempDir, char *fileName, char *stdioPath) { uio_StdioAccessHandle *result; result = uio_StdioAccessHandle_alloc(); result->tempRoot = tempRoot; result->tempDirName = tempDirName; result->tempDir = tempDir; result->fileName = fileName; result->stdioPath = stdioPath; return result; } static inline void uio_StdioAccessHandle_delete(uio_StdioAccessHandle *handle) { if (handle->tempDir != NULL) uio_DirHandle_unref(handle->tempDir); if (handle->fileName != NULL) uio_free(handle->fileName); if (handle->tempRoot != NULL) uio_DirHandle_unref(handle->tempRoot); if (handle->tempDirName != NULL) uio_free(handle->tempDirName); uio_free(handle->stdioPath); uio_StdioAccessHandle_free(handle); } static inline uio_StdioAccessHandle * uio_StdioAccessHandle_alloc(void) { return uio_malloc(sizeof (uio_StdioAccessHandle)); } static inline void uio_StdioAccessHandle_free(uio_StdioAccessHandle *handle) { uio_free(handle); } uqm-0.6.2/sc2/src/sc2code/libs/uio/uioport.h0000600000175000017500000000742410543202051017205 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _UIOPORT_H #define _UIOPORT_H #ifdef _MSC_VER # include #else # include #endif // Compilation related #ifndef inline # ifdef _MSC_VER # define inline __inline # else # define inline __inline__ # endif #endif // Paths #ifdef WIN32 # include # define PATH_MAX _MAX_PATH # define NAME_MAX _MAX_FNAME // _MAX_DIR and FILENAME_MAX could also be candidates. // If anyone can tell me which one matches NAME_MAX, please // let me know. #else # include /* PATH_MAX is per POSIX defined in , but: * "A definition of one of the values from Table 2.6 shall bea * omitted from on specific implementations where the * corresponding value is equal to or greater than the * stated minimum, but where the value can vary depending * on the file to which it is applied. The actual value supported * for a specific pathname shall be provided by the pathconf() * function." * _POSIX_NAME_MAX will provide a minimum (14). * This is relevant (at least) for Solaris. */ # ifndef NAME_MAX # define NAME_MAX _POSIX_NAME_MAX # endif #endif // User ids #ifdef WIN32 typedef short uid_t; typedef short gid_t; #endif // Some types #ifdef _MSC_VER typedef int ssize_t; typedef unsigned short mode_t; #endif // Directories #include #ifdef WIN32 # ifdef _MSC_VER # define MKDIR(name, mode) ((void) mode, _mkdir(name)) # else # define MKDIR(name, mode) ((void) mode, mkdir(name)) # endif #else # define MKDIR mkdir #endif #ifdef _MSC_VER # include # define chdir _chdir # define getcwd _getcwd # define chdir _chdir # define getcwd _getcwd # define access _access # define F_OK 0 # define W_OK 2 # define R_OK 4 # define open _open # define read _read # define rmdir _rmdir # define lseek _lseek # define lstat _lstat # define fstat _fstat # define S_IRUSR S_IREAD # define S_IWUSR S_IWRITE # define S_IXUSR S_IEXEC # define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) # define S_IRGRP 0 # define S_IWGRP 0 # define S_IXGRP 0 # define S_IROTH 0 # define S_IWOTH 0 # define S_IXOTH 0 # define S_IRWXG 0 # define S_IRWXO 0 # define S_ISUID 0 # define S_ISGID 0 # define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) # define S_IFMT _S_IFMT # define S_IFREG _S_IFREG # define S_IFCHR _S_IFCHR # define S_IFDIR _S_IFDIR # define S_ISDIR(mode) (((mode) & _S_IFMT) == _S_IFDIR) # define S_ISREG(mode) (((mode) & _S_IFMT) == _S_IFREG) # define write _write # define stat _stat # define unlink _unlink #elif defined (__MINGW32__) # define S_IRGRP 0 # define S_IWGRP 0 # define S_IXGRP 0 # define S_IROTH 0 # define S_IWOTH 0 # define S_IXOTH 0 # define S_IRWXG 0 # define S_IRWXO 0 # define S_ISUID 0 # define S_ISGID 0 # define S_IFMT _S_IFMT # define S_IFREG _S_IFREG # define S_IFCHR _S_IFCHR # define S_IFDIR _S_IFDIR #endif // Memory related: #ifdef WIN32 # ifdef __MINGW32__ # include # elif defined (_MSC_VER) # define alloca _alloca # endif #elif defined(__linux__) || defined(__svr4__) # include #endif #endif /* _UIOPORT_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/defaultfs.c0000600000175000017500000000240110543202051017442 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "defaultfs.h" #include "uioport.h" extern uio_FileSystemHandler stdio_fileSystemHandler; #ifdef HAVE_ZIP extern uio_FileSystemHandler zip_fileSystemHandler; #endif const uio_DefaultFileSystemSetup defaultFileSystems[] = { { uio_FSTYPE_STDIO, "stdio", &stdio_fileSystemHandler }, #ifdef HAVE_ZIP { uio_FSTYPE_ZIP, "zip", &zip_fileSystemHandler }, #endif }; int uio_numDefaultFileSystems(void) { return sizeof defaultFileSystems / sizeof defaultFileSystems[0]; } uqm-0.6.2/sc2/src/sc2code/libs/uio/paths.h0000644000175000017500000000615110546776502016653 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _PATHS_H #define _PATHS_H typedef struct uio_PathComp uio_PathComp; #include "types.h" #include "uioport.h" #include struct uio_PathComp { char *name; // The name of this path component, 0-terminated size_t nameLen; // The length of the 'name' field, for fast lookups. struct uio_PathComp *next; // Next component in the path. struct uio_PathComp *up; // Previous component in the path. }; void getFirstPathComponent(const char *dir, const char *dirEnd, const char **startComp, const char **endComp); void getFirstPath0Component(const char *dir, const char **startComp, const char **endComp); void getNextPathComponent(const char *dirEnd, const char **startComp, const char **endComp); void getNextPath0Component(const char **startComp, const char **endComp); void getLastPathComponent(const char *dir, const char *dirEnd, const char **startComp, const char **endComp); void getLastPath0Component(const char *dir, const char **startComp, const char **endComp); void getPreviousPathComponent(const char *dir, const char **startComp, const char **endComp); #define getPreviousPath0Component getPreviousPathComponent char *joinPaths(const char *first, const char *second); char *joinPathsAbsolute(const char *first, const char *second); uio_bool validPathName(const char *path, size_t len); size_t uio_skipUNCServerShare(const char *inPath); size_t uio_getUNCServerShare(const char *inPath, char **outPath, size_t *outLen); #ifdef WIN32 static inline int isDriveLetter(int c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } #endif static inline int isPathDelimiter(int c) { #ifdef WIN32 return c == '/' || c == '\\'; #else return c == '/'; #endif } int decomposePath(const char *path, uio_PathComp **pathComp, uio_bool *isAbsolute); void composePath(const uio_PathComp *pathComp, uio_bool absolute, char **path, size_t *pathLen); uio_PathComp *uio_PathComp_new(char *name, size_t nameLen, uio_PathComp *upComp); void uio_PathComp_delete(uio_PathComp *pathComp); int uio_countPathComps(const uio_PathComp *comp); uio_PathComp *uio_lastPathComp(uio_PathComp *comp); uio_PathComp *uio_makePathComps(const char *path, uio_PathComp *upComp); void uio_printPathComp(FILE *outStream, const uio_PathComp *comp); void uio_printPathToComp(FILE *outStream, const uio_PathComp *comp); #endif /* _PATHS_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/iointrn.h0000644000175000017500000001120110545750177017205 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _IOINTERN_H #define _IOINTERN_H #define uio_INTERNAL typedef struct uio_PDirEntryHandle uio_PDirEntryHandle; typedef struct uio_PDirHandle uio_PDirHandle; typedef struct uio_PFileHandle uio_PFileHandle; typedef struct uio_EntriesContext uio_EntriesContext; #ifndef uio_INTERNAL_PHYSICAL typedef void *uio_PDirHandleExtra; typedef void *uio_PFileHandleExtra; #endif #include "io.h" #include "uioport.h" #include "physical.h" #include "mount.h" #include "mounttree.h" #include "match.h" #include "mem.h" struct uio_Handle { int ref; struct uio_PRoot *root; uio_NativeHandle native; int openFlags; // need to know whether the handle is a RO or RW handle. }; struct uio_DirHandle { int ref; struct uio_Repository *repository; char *path; // does not contain any '.' or '..'; does not start or end // with a / char *rootEnd; // points to the end of the part of path that is considered // the root dir. (you can't use '..' to get above the root dir) }; struct uio_MountHandle { struct uio_Repository *repository; struct uio_MountInfo *mountInfo; }; struct uio_DirList { const char **names; int numNames; char *buffer; }; #define uio_PHandle_COMMON \ int flags; \ int ref; \ uio_PRoot *pRoot; #define uio_PDirEntryHandle_TYPE_REG 0x0000 #define uio_PDirEntryHandle_TYPE_DIR 0x0001 #define uio_PDirEntryHandle_TYPEMASK 0x0001 struct uio_PDirEntryHandle { uio_PHandle_COMMON }; struct uio_PDirHandle { uio_PHandle_COMMON uio_PDirHandleExtra extra; }; struct uio_PFileHandle { uio_PHandle_COMMON uio_PFileHandleExtra extra; }; struct uio_EntriesContext { uio_PRoot *pRoot; uio_NativeEntriesContext native; }; uio_Handle *uio_Handle_new(uio_PRoot *root, uio_NativeHandle native, int openFlags); void uio_Handle_delete(uio_Handle *handle); void uio_DirHandle_delete(uio_DirHandle *dirHandle); uio_PDirEntryHandle *uio_getPDirEntryHandle( const uio_PDirHandle *dirHandle, const char *name); void uio_PDirHandle_deletePDirHandleExtra(uio_PDirHandle *pDirHandle); void uio_PFileHandle_deletePFileHandleExtra(uio_PFileHandle *pFileHandle); uio_PDirHandle *uio_PDirHandle_new(uio_PRoot *pRoot, uio_PDirHandleExtra extra); uio_PFileHandle *uio_PFileHandle_new(uio_PRoot *pRoot, uio_PFileHandleExtra extra); void uio_PDirEntryHandle_delete(uio_PDirEntryHandle *pDirEntryHandle); void uio_PDirHandle_delete(uio_PDirHandle *pDirHandle); void uio_PFileHandle_delete(uio_PFileHandle *pFileHandle); static inline void uio_Handle_ref(uio_Handle *handle) { handle->ref++; } static inline void uio_Handle_unref(uio_Handle *handle) { assert(handle->ref > 0); handle->ref--; if (handle->ref == 0) uio_Handle_delete(handle); } static inline void uio_DirHandle_ref(uio_DirHandle *dirHandle) { dirHandle->ref++; } static inline void uio_DirHandle_unref(uio_DirHandle *dirHandle) { assert(dirHandle->ref > 0); dirHandle->ref--; if (dirHandle->ref == 0) uio_DirHandle_delete(dirHandle); } static inline uio_bool uio_PDirEntryHandle_isDir(const uio_PDirEntryHandle *handle) { return (handle->flags & uio_PDirEntryHandle_TYPEMASK) == uio_PDirEntryHandle_TYPE_DIR; } static inline void uio_PDirEntryHandle_ref(uio_PDirEntryHandle *handle) { handle->ref++; } static inline void uio_PDirEntryHandle_unref(uio_PDirEntryHandle *handle) { assert(handle->ref > 0); handle->ref--; if (handle->ref == 0) uio_PDirEntryHandle_delete(handle); } static inline void uio_PDirHandle_ref(uio_PDirHandle *handle) { handle->ref++; } static inline void uio_PDirHandle_unref(uio_PDirHandle *handle) { assert(handle->ref > 0); handle->ref--; if (handle->ref == 0) uio_PDirHandle_delete(handle); } static inline void uio_PFileHandle_ref(uio_PFileHandle *handle) { handle->ref++; } static inline void uio_PFileHandle_unref(uio_PFileHandle *handle) { assert(handle->ref > 0); handle->ref--; if (handle->ref == 0) uio_PFileHandle_delete(handle); } #endif /* _IOINTERN_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/debug.c0000644000175000017500000005340010546776502016614 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include #ifdef __unix__ # include #endif #include "debug.h" #include "uioport.h" #include "io.h" #include "utils.h" #include "types.h" #include "mem.h" #include "uioutils.h" #ifdef uio_MEM_DEBUG # include "memdebug.h" #endif #define LINEBUFLEN 1024 typedef struct DebugContext { uio_bool exit; FILE *in; FILE *out; FILE *err; uio_DirHandle *cwd; } DebugContext; typedef struct { const char *name; int (*fun)(DebugContext *, int, char *[]); } DebugCommand; #ifdef STAND_ALONE void initRepository(void); void unInitRepository(void); #endif static int debugCmdCat(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdCd(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdExec(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdExit(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdLs(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdMem(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdMkDir(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdMount(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdMv(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdPwd(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdRm(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdRmDir(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdStat(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdWriteTest(DebugContext *debugContext, int argc, char *argv[]); static int debugCmdFwriteTest(DebugContext *debugContext, int argc, char *argv[]); static void makeArgs(char *lineBuf, int *argc, char ***argv); static int debugCallCommand(DebugContext *debugContext, int argc, char *argv[]); uio_MountHandle * debugMountOne(uio_Repository *destRep, const char *mountPoint, uio_FileSystemID fsType, uio_DirHandle *sourceDir, const char *sourcePath, const char *inPath, uio_AutoMount **autoMount, int flags, uio_MountHandle *relative); // In alphabetic order: DebugCommand debugCommands[] = { { "cat", debugCmdCat }, { "cd", debugCmdCd }, { "exec", debugCmdExec }, { "exit", debugCmdExit }, { "fwritetest", debugCmdFwriteTest }, { "ls", debugCmdLs }, { "mem", debugCmdMem }, { "mkdir", debugCmdMkDir }, { "mount", debugCmdMount }, { "mv", debugCmdMv }, { "pwd", debugCmdPwd }, { "rm", debugCmdRm }, { "rmdir", debugCmdRmDir }, { "stat", debugCmdStat }, { "writetest", debugCmdWriteTest }, }; #ifndef STAND_ALONE extern uio_Repository *repository; #else uio_Repository *repository; uio_MountHandle *mountHandles[9]; // TODO: remove (this is just a test) int main(int argc, char *argv[]) { initRepository(); uio_debugInteractive(stdin, stdout, stderr); unInitRepository(); (void) argc; (void) argv; return EXIT_SUCCESS; } uio_MountHandle * debugMountOne(uio_Repository *destRep, const char *mountPoint, uio_FileSystemID fsType, uio_DirHandle *sourceDir, const char *sourcePath, const char *inPath, uio_AutoMount **autoMount, int flags, uio_MountHandle *relative) { uio_MountHandle *mountHandle; mountHandle = uio_mountDir(destRep, mountPoint, fsType, sourceDir, sourcePath, inPath, autoMount, flags, relative); if (mountHandle == NULL) { int savedErrno = errno; fprintf(stderr, "Could not mount '%s' and graft '%s' from that " "into the repository at '%s': %s\n", sourcePath, inPath, mountPoint, strerror(errno)); errno = savedErrno; } return mountHandle; } void initRepository(void) { static uio_AutoMount autoMountZip = { .pattern = "*.zip", .matchType = match_MATCH_SUFFIX, .fileSystemID = uio_FSTYPE_ZIP, .mountFlags = uio_MOUNT_BELOW | uio_MOUNT_RDONLY }; static uio_AutoMount *autoMount[] = { &autoMountZip, NULL }; uio_init(); repository = uio_openRepository(0); memset(&mountHandles, '\0', sizeof mountHandles); #if 1 mountHandles[0] = debugMountOne(repository, "/", uio_FSTYPE_STDIO, NULL, NULL, "/home/svdb/cvs/sc2/content", autoMount, uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL); #endif #if 1 mountHandles[1] = debugMountOne(repository, "/", uio_FSTYPE_STDIO, NULL, NULL, "/home/svdb/cvs/sc2/src/sc2code/ships", autoMount, uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL); #endif #if 1 mountHandles[2] = debugMountOne(repository, "/", uio_FSTYPE_STDIO, NULL, NULL, "/tmp/vfstest", autoMount, uio_MOUNT_TOP, NULL); #endif #if 1 mountHandles[3] = debugMountOne(repository, "/", uio_FSTYPE_STDIO, NULL, NULL, "/tmp/vfstest2", autoMount, uio_MOUNT_TOP, NULL); #endif // TODO: should work too: #if 0 mountHandle[4] = debugMountOne(repository, "/zip/", uio_FSTYPE_ZIP, NULL, NULL, "/ziptest/foo.zip", autoMount, uio_MOUNT_TOP, NULL); #endif { uio_DirHandle *rootDir; rootDir = uio_openDir(repository, "/", 0); if (rootDir == NULL) { fprintf(stderr, "Could not open '/' dir.\n"); } else { #if 1 mountHandles[4] = debugMountOne(repository, "/example/", uio_FSTYPE_ZIP, rootDir, "/example2.zip", "/", autoMount, uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL); #endif #if 1 mountHandles[5] = debugMountOne(repository, "/example/", uio_FSTYPE_ZIP, rootDir, "/example/example.zip", "/", autoMount, uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL); #endif #if 1 mountHandles[6] = debugMountOne(repository, "/zip/", uio_FSTYPE_ZIP, rootDir, "/voice.zip", "/", autoMount, uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL); #endif #if 1 mountHandles[7] = debugMountOne(repository, "/foo/", uio_FSTYPE_ZIP, rootDir, "/foo2.zip", "/", autoMount, uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL); #endif uio_closeDir(rootDir); } } mountHandles[8] = debugMountOne(repository, "/tmp/", uio_FSTYPE_STDIO, NULL, NULL, "/tmp/", autoMount, uio_MOUNT_TOP, NULL); #if 1 mountHandles[8] = debugMountOne(repository, "/root/root/", uio_FSTYPE_STDIO, NULL, NULL, "/", autoMount, uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL); #endif } void unInitRepository(void) { #if 1 int i; // uio_printMountTree(stderr, repository->mountTree, 0); // fprintf(stderr, "\n"); for (i = 7; i >= 0; i--) { if (mountHandles[i] != NULL) uio_unmountDir(mountHandles[i]); // uio_printMountTree(stderr, repository->mountTree, 0); // uio_printMounts(stderr, repository); // fprintf(stderr, "\n"); } #endif uio_closeRepository(repository); uio_unInit(); } #endif /* STAND_ALONE */ void uio_debugInteractive(FILE *in, FILE *out, FILE *err) { char lineBuf[LINEBUFLEN]; size_t lineLen; int argc; char **argv; DebugContext debugContext; uio_bool interactive; memset(&debugContext, '\0', sizeof (DebugContext)); debugContext.exit = false; debugContext.in = in; debugContext.out = out; debugContext.err = err; debugContext.cwd = uio_openDir(repository, "/", 0); if (debugContext.cwd == NULL) { fprintf(err, "Fatal: Could not open working dir.\n"); abort(); } interactive = isatty(fileno(in)); do { if (interactive) fprintf(out, "> "); if (fgets(lineBuf, LINEBUFLEN, in) == NULL) { if (feof(in)) { // user pressed ^D break; } // error occured clearerr(in); continue; } lineLen = strlen(lineBuf); if (lineBuf[lineLen - 1] != '\n' && lineBuf[lineLen - 1] != '\r') { fprintf(err, "Too long command line.\n"); // TODO: read until EOL continue; } makeArgs(lineBuf, &argc, &argv); if (argc == 0) { uio_free(argv); continue; } debugCallCommand(&debugContext, argc, argv); uio_free(argv); } while (!debugContext.exit); if (interactive) fprintf(out, "\n"); uio_closeDir(debugContext.cwd); } static void makeArgs(char *lineBuf, int *argc, char ***argv) { int numArg; char **args; char *ptr; numArg = 0; ptr = lineBuf; while(true) { while (isspace((int) *ptr)) ptr++; if (*ptr == '\0') break; numArg++; while (!isspace((int) *ptr)) ptr++; } args = uio_malloc((numArg + 1) * sizeof (char *)); numArg = 0; ptr = lineBuf; while(true) { while (isspace((int) *ptr)) ptr++; if (*ptr == '\0') break; args[numArg] = ptr; numArg++; while (!isspace((int) *ptr)) ptr++; if (*ptr == '\0') break; *ptr = '\0'; ptr++; } args[numArg] = NULL; *argv = args; *argc = numArg; } static int debugCallCommand(DebugContext *debugContext, int argc, char *argv[]) { int i; int numDebugCommands; i = 0; numDebugCommands = sizeof debugCommands / sizeof debugCommands[0]; // could be improved with binary search while(1) { if (i == numDebugCommands) { fprintf(debugContext->err, "Invalid command.\n"); return 1; } if (strcmp(argv[0], debugCommands[i].name) == 0) break; i++; } return debugCommands[i].fun(debugContext, argc, argv); } static int debugCmdCat(DebugContext *debugContext, int argc, char *argv[]) { uio_Handle *handle; #define READBUFSIZE 0x10000 char readBuf[READBUFSIZE]; char *bufPtr; ssize_t numInBuf, numWritten; size_t totalWritten; if (argc != 2) { fprintf(debugContext->err, "Invalid number of arguments.\n"); return 1; } handle = uio_open(debugContext->cwd, argv[1], O_RDONLY #ifdef WIN32 | O_BINARY #endif , 0); if (handle == NULL) { fprintf(debugContext->err, "Could not open file: %s\n", strerror(errno)); return 1; } totalWritten = 0; while (1) { numInBuf = uio_read(handle, readBuf, READBUFSIZE); if (numInBuf == -1) { if (errno == EINTR) continue; fprintf(debugContext->err, "Could not read from file: %s\n", strerror(errno)); uio_close(handle); return 1; } if (numInBuf == 0) break; bufPtr = readBuf; do { numWritten = write(fileno(debugContext->out), bufPtr, numInBuf); if (numWritten == -1) { if (errno == EINTR) continue; fprintf(debugContext->err, "Could not read from file: %s\n", strerror(errno)); uio_close(handle); } numInBuf -= numWritten; bufPtr += numWritten; totalWritten += numWritten; } while (numInBuf > 0); } fprintf(debugContext->out, "[%u bytes]\n", (unsigned int) totalWritten); uio_close(handle); return 0; } static int debugCmdCd(DebugContext *debugContext, int argc, char *argv[]) { uio_DirHandle *newWd; if (argc != 2) { fprintf(debugContext->err, "Invalid number of arguments.\n"); return 1; } newWd = uio_openDirRelative(debugContext->cwd, argv[1], 0); if (newWd == NULL) { fprintf(debugContext->err, "Could not access new dir: %s\n", strerror(errno)); return 1; } uio_closeDir(debugContext->cwd); debugContext->cwd = newWd; return 0; } static int debugCmdExec(DebugContext *debugContext, int argc, char *argv[]) { int i; const char **newArgs; int errCode = 0; uio_StdioAccessHandle **handles; uio_DirHandle *tempDir; if (argc < 2) { fprintf(debugContext->err, "Invalid number of arguments.\n"); return 1; } tempDir = uio_openDirRelative(debugContext->cwd, "/tmp", 0); if (tempDir == 0) { fprintf(debugContext->err, "Could not open temp dir: %s.\n", strerror(errno)); return 1; } newArgs = uio_malloc(argc * sizeof (char *)); newArgs[0] = argv[1]; handles = uio_malloc(argc * sizeof (uio_StdioAccessHandle *)); handles[0] = NULL; for (i = 2; i < argc; i++) { #if 0 if (argv[i][0] == '-') { // Don't try to parse arguments that start with '-'. // They are probably option flags. newArgs[i - 1] = argv[i]; } #endif handles[i - 1] = uio_getStdioAccess(debugContext->cwd, argv[i], O_RDONLY, tempDir); if (handles[i - 1] == NULL) { if (errno == ENOENT) { // No match; we keep what's typed litterally. newArgs[i - 1] = argv[i]; continue; } // error fprintf(debugContext->err, "Cannot execute: Cannot get stdio access to %s: %s.\n", argv[i], strerror(errno)); errCode = 1; argc = i + 1; goto err; } newArgs[i - 1] = uio_StdioAccessHandle_getPath(handles[i - 1]); } newArgs[argc - 1] = NULL; fprintf(debugContext->err, "Executing: %s", newArgs[0]); for (i = 1; i < argc - 1; i++) fprintf(debugContext->err, " %s", newArgs[i]); fprintf(debugContext->err, "\n"); #ifdef __unix__ { pid_t pid; pid = fork(); switch (pid) { case -1: fprintf(debugContext->err, "Error: fork() failed: %s.\n", strerror(errno)); break; case 0: // child execvp(newArgs[0], (char * const *) newArgs); fprintf(debugContext->err, "Error: execvp() failed: %s.\n", strerror(errno)); _exit(EXIT_FAILURE); break; default: { // parent int status; pid_t retVal; while (1) { retVal = waitpid(pid, &status, 0); if (retVal != -1) break; if (errno != EINTR) { fprintf(debugContext->err, "Error: waitpid() " "failed: %s\n", strerror(errno)); break; } } if (retVal == -1) break; if (WIFEXITED(status)) { fprintf(debugContext->err, "Exit status: %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { fprintf(debugContext->err, "Terminated on signal %d.\n", WTERMSIG(status)); } else { fprintf(debugContext->err, "Error: weird exit status.\n"); } break; } } } #else fprintf(debugContext->err, "Cannot execute: not supported on this " "platform.\n"); #endif err: for (i = 1; i < argc - 1; i++) { if (handles[i] != NULL) uio_releaseStdioAccess(handles[i]); } uio_free(handles); uio_free((void *) newArgs); uio_closeDir(tempDir); return errCode; } static int debugCmdExit(DebugContext *debugContext, int argc, char *argv[]) { debugContext->exit = true; (void) argc; (void) argv; return 0; } static int debugCmdFwriteTest(DebugContext *debugContext, int argc, char *argv[]) { uio_Stream *stream; const char testString[] = "0123456789\n"; if (argc != 2) { fprintf(debugContext->err, "Invalid number of arguments.\n"); return 1; } stream = uio_fopen(debugContext->cwd, argv[1], "w+b"); if (stream == NULL) { fprintf(debugContext->err, "Could not open file: %s\n", strerror(errno)); goto err; } if (uio_fwrite(testString, strlen(testString), 1, stream) != 1) { fprintf(debugContext->err, "uio_fwrite() failed: %s\n", strerror(errno)); goto err; } if (uio_fputs(testString, stream) == EOF) { fprintf(debugContext->err, "uio_fputs() failed: %s\n", strerror(errno)); goto err; } if (uio_fseek(stream, 15, SEEK_SET) != 0) { fprintf(debugContext->err, "uio_fseek() failed: %s\n", strerror(errno)); goto err; } if (uio_fputc('A', stream) != 'A') { fprintf(debugContext->err, "uio_fputc() failed: %s\n", strerror(errno)); goto err; } if (uio_fseek(stream, 0, SEEK_SET) != 0) { fprintf(debugContext->err, "uio_fseek() failed: %s\n", strerror(errno)); goto err; } { char buf[6]; char *ptr; int i; i = 1; while (1) { ptr = uio_fgets(buf, sizeof buf, stream); if (ptr == NULL) break; fprintf(debugContext->out, "%d: [%s]\n", i, ptr); i++; } if (uio_ferror(stream)) { fprintf(debugContext->err, "uio_fgets() failed: %s\n", strerror(errno)); goto err; } uio_clearerr(stream); } if (uio_fseek(stream, 4, SEEK_END) != 0) { fprintf(debugContext->err, "uio_fseek() failed: %s\n", strerror(errno)); goto err; } { char buf[2000]; memset(buf, 'Q', sizeof buf); if (uio_fwrite(buf, 100, 20, stream) != 20) { fprintf(debugContext->err, "uio_fwrite() failed: %s\n", strerror(errno)); goto err; } } if (uio_fseek(stream, 5, SEEK_SET) != 0) { fprintf(debugContext->err, "uio_fseek() failed: %s\n", strerror(errno)); goto err; } if (uio_fputc('B', stream) != 'B') { fprintf(debugContext->err, "uio_fputc() failed: %s\n", strerror(errno)); goto err; } uio_fclose(stream); return 0; err: uio_fclose(stream); return 1; } static int listOneDir(DebugContext *debugContext, const char *arg) { uio_DirList *dirList; int i; const char *pattern; const char *cpath; if (arg[0] == '\0') { cpath = arg; pattern = "*"; } else { pattern = strrchr(arg, '/'); if (pattern == NULL) { cpath = ""; pattern = arg; } else if (pattern[1] == '\0') { // argument ends on / cpath = arg; pattern = "*"; } else { if (pattern == arg) { cpath = "/"; } else { char *path; path = uio_alloca(pattern - arg + 1); memcpy(path, arg, pattern - arg); path[pattern - arg] = '\0'; cpath = path; } pattern++; } } #ifdef HAVE_GLOB dirList = uio_getDirList(debugContext->cwd, cpath, pattern, match_MATCH_GLOB); #else if (pattern[0] == '*' && pattern[1] == '\0') { dirList = uio_getDirList(debugContext->cwd, cpath, "", match_MATCH_PREFIX); } else { dirList = uio_getDirList(debugContext->cwd, cpath, pattern, match_MATCH_LITTERAL); } #endif if (dirList == NULL) { fprintf(debugContext->out, "Error in uio_getDirList(): %s.\n", strerror(errno)); return 1; } for (i = 0; i < dirList->numNames; i++) fprintf(debugContext->out, "%s\n", dirList->names[i]); uio_DirList_free(dirList); return 0; } static int debugCmdLs(DebugContext *debugContext, int argc, char *argv[]) { int argI; int retVal; if (argc == 1) return listOneDir(debugContext, unconst("")); for (argI = 1; argI < argc; argI++) { retVal = listOneDir(debugContext, argv[argI]); if (retVal != 0) return retVal; } return 0; } static int debugCmdMem(DebugContext *debugContext, int argc, char *argv[]) { #ifdef uio_MEM_DEBUG uio_MemDebug_printPointers(debugContext->out); #else fprintf(debugContext->out, "Memory debugging not compiled in.\n"); #endif (void) argc; (void) argv; return 0; } static int debugCmdMkDir(DebugContext *debugContext, int argc, char *argv[]) { int retVal; if (argc != 2) { fprintf(debugContext->err, "Invalid number of arguments.\n"); return 1; } retVal = uio_mkdir(debugContext->cwd, argv[1], 0777); if (retVal == -1) { fprintf(debugContext->err, "Could not create directory: %s\n", strerror(errno)); return 1; } return 0; } static int debugCmdMount(DebugContext *debugContext, int argc, char *argv[]) { if (argc == 1) { uio_printMounts(debugContext->out, repository); // uio_printMountTree(debugContext->out, repository->mountTree, 0); } (void) argv; return 0; } static int debugCmdMv(DebugContext *debugContext, int argc, char *argv[]) { int retVal; if (argc != 3) { fprintf(debugContext->err, "Invalid number of arguments.\n"); return 1; } retVal = uio_rename(debugContext->cwd, argv[1], debugContext->cwd, argv[2]); if (retVal == -1) { fprintf(debugContext->err, "Could not rename: %s\n", strerror(errno)); return 1; } return 0; } static int debugCmdPwd(DebugContext *debugContext, int argc, char *argv[]) { uio_DirHandle_print(debugContext->cwd, debugContext->out); (void) argc; (void) argv; return 0; } static int debugCmdRm(DebugContext *debugContext, int argc, char *argv[]) { int retVal; if (argc != 2) { fprintf(debugContext->err, "Invalid number of arguments.\n"); return 1; } retVal = uio_unlink(debugContext->cwd, argv[1]); if (retVal == -1) { fprintf(debugContext->err, "Could not remove file: %s\n", strerror(errno)); return 1; } return 0; } static int debugCmdRmDir(DebugContext *debugContext, int argc, char *argv[]) { int retVal; if (argc != 2) { fprintf(debugContext->err, "Invalid number of arguments.\n"); return 1; } retVal = uio_rmdir(debugContext->cwd, argv[1]); if (retVal == -1) { fprintf(debugContext->err, "Could not remove directory: %s\n", strerror(errno)); return 1; } return 0; } static int debugCmdStat(DebugContext *debugContext, int argc, char *argv[]) { struct stat statBuf; if (argc != 2) { fprintf(debugContext->err, "Invalid number of arguments.\n"); return 1; } if (uio_stat(debugContext->cwd, argv[1], &statBuf) == -1) { // errno is set int savedErrno; savedErrno = errno; fprintf(debugContext->err, "Could not stat file: %s\n", strerror(errno)); errno = savedErrno; return 1; } fprintf(debugContext->out, "size %ld bytes\n" "uid %d gid %d mode 0%o\n", (unsigned long) statBuf.st_size, (unsigned int) statBuf.st_uid, (unsigned int) statBuf.st_gid, (unsigned int) statBuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID)); // Can't do these next three in one fprintf, as ctime uses a static buffer // that is overwritten with each call. fprintf(debugContext->out, "last access: %s", ctime(&statBuf.st_atime)); fprintf(debugContext->out, "last modification: %s", ctime(&statBuf.st_mtime)); fprintf(debugContext->out, "last status change: %s", ctime(&statBuf.st_ctime)); return 0; } static int debugCmdWriteTest(DebugContext *debugContext, int argc, char *argv[]) { uio_Handle *handle; const char testString[] = "Hello world!\n"; if (argc != 2) { fprintf(debugContext->err, "Invalid number of arguments.\n"); return 1; } handle = uio_open(debugContext->cwd, argv[1], O_WRONLY | O_CREAT | O_EXCL #ifdef WIN32 | O_BINARY #endif , 0644); if (handle == NULL) { fprintf(debugContext->err, "Could not open file: %s\n", strerror(errno)); return 1; } if (uio_write(handle, testString, sizeof testString) == -1) { fprintf(debugContext->err, "Write failed: %s\n", strerror(errno)); return 1; } uio_close(handle); return 0; } uqm-0.6.2/sc2/src/sc2code/libs/uio/stdio/0000755000175000017500000000000010552600274016467 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/uio/stdio/stdio.h0000644000175000017500000000677710546776501020015 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ typedef struct stdio_Handle *uio_NativeHandle; typedef void *uio_GPRootExtra; typedef struct stdio_GPDirData *uio_GPDirExtra; typedef void *uio_GPFileExtra; typedef struct stdio_EntriesIterator stdio_EntriesIterator; typedef stdio_EntriesIterator *uio_NativeEntriesContext; #define uio_INTERNAL_PHYSICAL #include "../gphys.h" #include "../iointrn.h" #include "../uioport.h" #include "../fstypes.h" #include "../physical.h" #include #ifndef WIN32 # include #endif typedef struct stdio_GPDirData { // The reason that names are stored is that in the system filesystem // you need names to refer to files and directories. // (you could keep a file descriptor to each one, but that would // mean a lot of open file descriptors, and for some it won't even // be enough). // This is not needed for all filesystems; therefor this info is not // in uio_GPDir itself. // The reasons for including upDir here are similar. char *name; char *cachedPath; uio_GPDir *upDir; } stdio_GPDirData; typedef struct stdio_Handle { int fd; } stdio_Handle; #ifdef WIN32 struct stdio_EntriesIterator { long dirHandle; struct _finddata_t findData; int status; }; #endif #ifndef WIN32 struct stdio_EntriesIterator { DIR *dirHandle; struct dirent *entry; struct dirent *direntBuffer; int status; }; #endif uio_PRoot *stdio_mount(uio_Handle *handle, int flags); int stdio_umount(uio_PRoot *); uio_PDirHandle *stdio_mkdir(uio_PDirHandle *pDirHandle, const char *name, mode_t mode); uio_Handle *stdio_open(uio_PDirHandle *pDirHandle, const char *file, int flags, mode_t mode); void stdio_close(uio_Handle *handle); int stdio_fstat(uio_Handle *handle, struct stat *statBuf); int stdio_stat(uio_PDirHandle *pDirHandle, const char *name, struct stat *statBuf); ssize_t stdio_read(uio_Handle *handle, void *buf, size_t count); int stdio_rename(uio_PDirHandle *oldPDirHandle, const char *oldName, uio_PDirHandle *newPDirHandle, const char *newName); int stdio_rmdir(uio_PDirHandle *pDirHandle, const char *name); off_t stdio_seek(uio_Handle *handle, off_t offset, int whence); ssize_t stdio_write(uio_Handle *handle, const void *buf, size_t count); int stdio_unlink(uio_PDirHandle *pDirHandle, const char *name); stdio_EntriesIterator *stdio_openEntries(uio_PDirHandle *pDirHandle); int stdio_readEntries(stdio_EntriesIterator **iterator, char *buf, size_t len); void stdio_closeEntries(stdio_EntriesIterator *iterator); #ifdef WIN32 stdio_EntriesIterator *stdio_EntriesIterator_new(long dirHandle); #else stdio_EntriesIterator *stdio_EntriesIterator_new(DIR *dirHandle); #endif void stdio_EntriesIterator_delete(stdio_EntriesIterator *iterator); uio_PDirEntryHandle *stdio_getPDirEntryHandle( const uio_PDirHandle *pDirHandle, const char *name); uqm-0.6.2/sc2/src/sc2code/libs/uio/stdio/stdio.c0000644000175000017500000004631010546776501017773 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ // The GPDir structures and functions are used for caching only. #ifdef __svr4__ # define _POSIX_PTHREAD_SEMANTICS // For the POSIX variant of readdir_r() #endif #include "./stdio.h" #ifdef WIN32 # include #else # include # include # define _POSIX_THREAD_SAFEFUNCTIONS // for readdir_r # include #endif #include #include #include #include #include #include #include "../uioport.h" #include "../paths.h" #include "../mem.h" #include "../physical.h" #ifdef uio_MEM_DEBUG # include "../memdebug.h" #endif static inline uio_GPFile *stdio_addFile(uio_GPDir *gPDir, const char *fileName); static inline uio_GPDir *stdio_addDir(uio_GPDir *gPDir, const char *dirName); static char *stdio_getPath(uio_GPDir *gPDir); static stdio_GPDirData *stdio_GPDirData_new(char *name, char *cachedPath, uio_GPDir *upDir); static void stdio_GPDirData_delete(stdio_GPDirData *gPDirData); static inline stdio_GPDirData *stdio_GPDirData_alloc(void); static inline void stdio_GPDirData_free(stdio_GPDirData *gPDirData); static inline stdio_EntriesIterator *stdio_EntriesIterator_alloc(void); static inline void stdio_EntriesIterator_free( stdio_EntriesIterator *iterator); uio_FileSystemHandler stdio_fileSystemHandler = { /* .init = */ NULL, /* .unInit = */ NULL, /* .cleanup = */ NULL, /* .mount = */ stdio_mount, /* .umount = */ uio_GPRoot_umount, /* .close = */ stdio_close, /* .fstat = */ stdio_fstat, /* .stat = */ stdio_stat, /* .mkdir = */ stdio_mkdir, /* .open = */ stdio_open, /* .read = */ stdio_read, /* .rename = */ stdio_rename, /* .rmdir = */ stdio_rmdir, /* .seek = */ stdio_seek, /* .write = */ stdio_write, /* .unlink = */ stdio_unlink, /* .openEntries = */ stdio_openEntries, /* .readEntries = */ stdio_readEntries, /* .closeEntries = */ stdio_closeEntries, /* .getPDirEntryHandle = */ stdio_getPDirEntryHandle, /* .deletePRootExtra = */ uio_GPRoot_delete, /* .deletePDirHandleExtra = */ uio_GPDirHandle_delete, /* .deletePFileHandleExtra = */ uio_GPFileHandle_delete, }; uio_GPRoot_Operations stdio_GPRootOperations = { /* .fillGPDir = */ NULL, /* .deleteGPRootExtra = */ NULL, /* .deleteGPDirExtra = */ stdio_GPDirData_delete, /* .deleteGPFileExtra = */ NULL, }; void stdio_close(uio_Handle *handle) { int fd; int result; fd = handle->native->fd; uio_free(handle->native); while (1) { result = close(fd); if (result == 0) break; if (errno != EINTR) { fprintf(stderr, "Warning: Error while closing socket: %s\n", strerror(errno)); break; } } } int stdio_fstat(uio_Handle *handle, struct stat *statBuf) { return fstat(handle->native->fd, statBuf); } int stdio_stat(uio_PDirHandle *pDirHandle, const char *name, struct stat *statBuf) { char *path; int result; path = joinPaths(stdio_getPath(pDirHandle->extra), name); if (path == NULL) { // errno is set return -1; } result = stat(path, statBuf); if (result == -1) { int savedErrno = errno; uio_free(path); errno = savedErrno; return -1; } uio_free(path); return result; } uio_PDirHandle * stdio_mkdir(uio_PDirHandle *pDirHandle, const char *name, mode_t mode) { char *path; uio_GPDir *newGPDir; path = joinPaths(stdio_getPath(pDirHandle->extra), name); if (path == NULL) { // errno is set return NULL; } if (MKDIR(path, mode) == -1) { int savedErrno = errno; uio_free(path); errno = savedErrno; return NULL; } uio_free(path); newGPDir = stdio_addDir(pDirHandle->extra, name); uio_GPDir_ref(newGPDir); return uio_PDirHandle_new(pDirHandle->pRoot, newGPDir); } /* * Function name: stdio_open * Description: open a file from a normal stdio environment * Arguments: gPDir - the dir where to open the file * file - the name of the file to open * flags - flags, as to stdio open() * mode - mode, as to stdio open() * Returns: handle, for use in functions accessing the opened file. * If failed, errno is set and handle is -1. */ uio_Handle * stdio_open(uio_PDirHandle *pDirHandle, const char *file, int flags, mode_t mode) { stdio_Handle *handle; char *path; int fd; path = joinPaths(stdio_getPath(pDirHandle->extra), file); if (path == NULL) { // errno is set return NULL; } fd = open(path, flags, mode); if (fd == -1) { int save_errno; save_errno = errno; uio_free(path); errno = save_errno; return NULL; } uio_free(path); #if 0 if (flags & O_CREAT) { if (uio_GPDir_getGPDirEntry(pDirHandle->extra, file) == NULL) stdio_addFile(pDirHandle->extra, file); } #endif handle = uio_malloc(sizeof (stdio_Handle)); handle->fd = fd; return uio_Handle_new(pDirHandle->pRoot, handle, flags); } ssize_t stdio_read(uio_Handle *handle, void *buf, size_t count) { return read(handle->native->fd, buf, count); } int stdio_rename(uio_PDirHandle *oldPDirHandle, const char *oldName, uio_PDirHandle *newPDirHandle, const char *newName) { char *newPath, *oldPath; int result; oldPath = joinPaths(stdio_getPath(oldPDirHandle->extra), oldName); if (oldPath == NULL) { // errno is set return -1; } newPath = joinPaths(stdio_getPath(newPDirHandle->extra), newName); if (newPath == NULL) { // errno is set uio_free(oldPath); return -1; } result = rename(oldPath, newPath); if (result == -1) { int savedErrno = errno; uio_free(oldPath); uio_free(newPath); errno = savedErrno; return -1; } uio_free(oldPath); uio_free(newPath); { // update the GPDir structure uio_GPDirEntry *entry; // TODO: add locking entry = uio_GPDir_getGPDirEntry(oldPDirHandle->extra, oldName); if (entry != NULL) { uio_GPDirEntries_remove(oldPDirHandle->extra->entries, oldName); uio_GPDirEntries_add(newPDirHandle->extra->entries, newName, entry); } } return result; } int stdio_rmdir(uio_PDirHandle *pDirHandle, const char *name) { char *path; int result; path = joinPaths(stdio_getPath(pDirHandle->extra), name); if (path == NULL) { // errno is set return -1; } result = rmdir(path); if (result == -1) { int savedErrno = errno; uio_free(path); errno = savedErrno; return -1; } uio_free(path); uio_GPDir_removeSubDir(pDirHandle->extra, name); return result; } off_t stdio_seek(uio_Handle *handle, off_t offset, int whence) { return lseek(handle->native->fd, offset, whence); } ssize_t stdio_write(uio_Handle *handle, const void *buf, size_t count) { return write(handle->native->fd, buf, count); } int stdio_unlink(uio_PDirHandle *pDirHandle, const char *name) { char *path; int result; path = joinPaths(stdio_getPath(pDirHandle->extra), name); if (path == NULL) { // errno is set return -1; } result = unlink(path); if (result == -1) { int savedErrno = errno; uio_free(path); errno = savedErrno; return -1; } uio_free(path); uio_GPDir_removeFile(pDirHandle->extra, name); return result; } uio_PDirEntryHandle * stdio_getPDirEntryHandle(const uio_PDirHandle *pDirHandle, const char *name) { uio_PDirEntryHandle *result; const char *pathUpTo; char *path; struct stat statBuf; #ifdef WIN32 char driveName[3]; #endif #ifdef WIN32 if (pDirHandle->extra->extra->upDir == NULL) { // Top dir. Contains only drive letters and UNC \\server\share // parts. if (isDriveLetter(name[0]) && name[1] == ':' && name[2] == '\0') { driveName[0] = tolower(name[0]); driveName[1] = ':'; driveName[2] = '\0'; name = driveName; } else { size_t uncLen; uncLen = uio_skipUNCServerShare(name); if (name[uncLen] != '\0') { // 'name' contains neither a drive letter, nor the // first part of a UNC path. return NULL; } } } #endif result = uio_GPDir_getPDirEntryHandle(pDirHandle, name); if (result != NULL) return result; #ifdef WIN32 if (pDirHandle->extra->extra->upDir == NULL) { // Need to create a 'directory' for the drive letter or UNC // "\\server\share" part. // It's no problem if we happen to create a dir for a non-existing // drive. It should just produce an empty dir. uio_GPDir *gPDir; gPDir = stdio_addDir(pDirHandle->extra, name); uio_GPDir_ref(gPDir); return (uio_PDirEntryHandle *) uio_PDirHandle_new( pDirHandle->pRoot, gPDir); } #endif pathUpTo = stdio_getPath(pDirHandle->extra); if (pathUpTo == NULL) { // errno is set return NULL; } path = joinPaths(pathUpTo, name); if (path == NULL) { // errno is set return NULL; } if (stat(path, &statBuf) == -1) { uio_free(path); return NULL; } uio_free(path); if (S_ISREG(statBuf.st_mode)) { uio_GPFile *gPFile; gPFile = stdio_addFile(pDirHandle->extra, name); uio_GPFile_ref(gPFile); return (uio_PDirEntryHandle *) uio_PFileHandle_new( pDirHandle->pRoot, gPFile); } else if (S_ISDIR(statBuf.st_mode)) { uio_GPDir *gPDir; gPDir = stdio_addDir(pDirHandle->extra, name); uio_GPDir_ref(gPDir); return (uio_PDirEntryHandle *) uio_PDirHandle_new( pDirHandle->pRoot, gPDir); } else { #ifdef DEBUG fprintf(stderr, "Warning: Attempt to access '%s' from '%s', " "which is not a regular file, nor a directory.\n", name, pathUpTo); #endif return NULL; } } uio_PRoot * stdio_mount(uio_Handle *handle, int flags) { uio_PRoot *result; stdio_GPDirData *extra; assert (handle == NULL); extra = stdio_GPDirData_new( uio_strdup("") /* name */, #ifdef WIN32 // In MS Windows, full paths start with a drive letter. uio_strdup("") /* cached path */, #else uio_strdup("/") /* cached path */, #endif NULL /* parent dir */); result = uio_GPRoot_makePRoot( uio_getFileSystemHandler(uio_FSTYPE_STDIO), flags, &stdio_GPRootOperations, NULL, uio_GPRoot_PERSISTENT, handle, extra, 0); uio_GPDir_setComplete(result->rootDir->extra, true); return result; } #ifdef WIN32 stdio_EntriesIterator * stdio_openEntries(uio_PDirHandle *pDirHandle) { const char *dirPath; char path[PATH_MAX]; char *pathEnd; size_t dirPathLen; stdio_EntriesIterator *iterator; // uio_GPDir_access(pDirHandle->extra); dirPath = stdio_getPath(pDirHandle->extra); if (dirPath == NULL) { // errno is set return NULL; } dirPathLen = strlen(dirPath); if (dirPathLen > PATH_MAX - 3) { // dirPath ++ '/' ++ '*' ++ '\0' errno = ENAMETOOLONG; return NULL; } memcpy(path, dirPath, dirPathLen); pathEnd = path + dirPathLen; pathEnd[0] = '/'; pathEnd[1] = '*'; pathEnd[2] = '\0'; iterator = stdio_EntriesIterator_new(0); iterator->dirHandle = _findfirst(path, &iterator->findData); if (iterator->dirHandle == 1) { if (errno != ENOENT) { stdio_EntriesIterator_delete(iterator); return NULL; } iterator->status = 1; } else iterator->status = 0; return iterator; } #endif #ifndef WIN32 stdio_EntriesIterator * stdio_openEntries(uio_PDirHandle *pDirHandle) { const char *dirPath; DIR *dirHandle; stdio_EntriesIterator *result; // uio_GPDir_access(pDirHandle->extra); dirPath = stdio_getPath(pDirHandle->extra); if (dirPath == NULL) { // errno is set return NULL; } dirHandle = opendir(dirPath); if (dirHandle == NULL) { // errno is set; return NULL; } result = stdio_EntriesIterator_new(dirHandle); result->status = readdir_r(dirHandle, result->direntBuffer, &result->entry); #ifndef WIN32 # ifdef DEBUG if (result->status != 0) { fprintf(stderr, "Warning: readdir_r() failed: %s\n", strerror(result->status)); } # endif #endif return result; } #endif // the start of 'buf' will be filled with pointers to strings // those strings are stored elsewhere in buf. // The function returns the number of strings passed along, or -1 for error. // If there are no more entries, the last pointer will be NULL. // (this pointer counts towards the return value) int stdio_readEntries(stdio_EntriesIterator **iteratorPtr, char *buf, size_t len) { char *end; char **start; int num; const char *name; size_t nameLen; stdio_EntriesIterator *iterator; iterator = *iteratorPtr; // buf will be filled like this: // The start of buf will contain pointers to char *, // the end will contain the actual char[] that those pointers point to. // The start and the end will grow towards eachother. start = (char **) buf; end = buf + len; num = 0; #ifdef WIN32 for (; iterator->status == 0; iterator->status = _findnext(iterator->dirHandle, &iterator->findData)) #else for (; iterator->status == 0 && iterator->entry != NULL; iterator->status = readdir_r(iterator->dirHandle, iterator->direntBuffer, &iterator->entry)) #endif { #ifdef WIN32 name = iterator->findData.name; #else name = iterator->entry->d_name; #endif if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) { // skip directories "." and ".." continue; } nameLen = strlen(name) + 1; // Does this work with systems that need memory access to be // aligned on a certain number of bytes? if ((size_t) (sizeof (char *) + nameLen) > (size_t) (end - (char *) start)) { // Not enough room to fit the pointer (at the beginning) and // the string (at the end). return num; } end -= nameLen; memcpy(end, name, nameLen); *start = end; start++; num++; } #ifndef WIN32 # ifdef DEBUG if (iterator->status != 0) { fprintf(stderr, "Warning: readdir_r() failed: %s\n", strerror(iterator->status)); } # endif #endif if (sizeof (char *) > (size_t) (end - (char *) start)) { // not enough room to fit the NULL pointer. // It will have to be reported seperately the next time. return num; } *start = NULL; num++; return num; } void stdio_closeEntries(stdio_EntriesIterator *iterator) { #ifdef WIN32 _findclose(iterator->dirHandle); #else closedir(iterator->dirHandle); #endif stdio_EntriesIterator_delete(iterator); } #ifdef WIN32 stdio_EntriesIterator * stdio_EntriesIterator_new(long dirHandle) { stdio_EntriesIterator *result; result = stdio_EntriesIterator_alloc(); result->dirHandle = dirHandle; return result; } #else stdio_EntriesIterator * stdio_EntriesIterator_new(DIR *dirHandle) { stdio_EntriesIterator *result; size_t bufferSize; result = stdio_EntriesIterator_alloc(); result->dirHandle = dirHandle; // Linux's and FreeBSD's struct dirent are defined with a // maximum d_name field (NAME_MAX). // However, POSIX doesn't require this, and in fact // at least QNX defines struct dirent with an empty d_name field. // Solaris defineds it with a d_name field of length 1. // This should take care of it: bufferSize = sizeof (struct dirent) - sizeof (((struct dirent *) 0)->d_name) + (NAME_MAX + 1); // Take the length of the dirent structure as it is defined, // subtract the length of the d_name field, and add the length // of the maximum length d_name field (NAME_MAX plus 1 for // the '\0'). // XXX: Could this give problems with weird alignments? result->direntBuffer = uio_malloc(bufferSize); return result; } #endif void stdio_EntriesIterator_delete(stdio_EntriesIterator *iterator) { #ifndef WIN32 uio_free(iterator->direntBuffer); #endif stdio_EntriesIterator_free(iterator); } static inline stdio_EntriesIterator * stdio_EntriesIterator_alloc(void) { return uio_malloc(sizeof (stdio_EntriesIterator)); } static inline void stdio_EntriesIterator_free(stdio_EntriesIterator *iterator) { uio_free(iterator); } static inline uio_GPFile * stdio_addFile(uio_GPDir *gPDir, const char *fileName) { uio_GPFile *file; file = uio_GPFile_new(gPDir->pRoot, NULL, uio_gPFileFlagsFromPRootFlags(gPDir->pRoot->flags)); uio_GPDir_addFile(gPDir, fileName, file); return file; } // called by fillGPDir when a subdir is found static inline uio_GPDir * stdio_addDir(uio_GPDir *gPDir, const char *dirName) { uio_GPDir *subDir; subDir = uio_GPDir_prepareSubDir(gPDir, dirName); if (subDir->extra == NULL) { // It's a new dir, we'll need to add our own data. uio_GPDir_ref(gPDir); subDir->extra = stdio_GPDirData_new(uio_strdup(dirName), NULL, gPDir); uio_GPDir_setComplete(subDir, true); // fillPDir should not be called. } uio_GPDir_commitSubDir(gPDir, dirName, subDir); return subDir; } // returns a pointer to gPDir->extra->cachedPath // pointer should not be stored, the memory it points to can be freed // lateron. TODO: not threadsafe. static char * stdio_getPath(uio_GPDir *gPDir) { if (gPDir->extra->cachedPath == NULL) { char *upPath; size_t upPathLen, nameLen; if (gPDir->extra->upDir == NULL) { #ifdef WIN32 // Drive letter still needs to follow. gPDir->extra->cachedPath = uio_malloc(1); gPDir->extra->cachedPath[0] = '\0'; #else gPDir->extra->cachedPath = uio_malloc(2); gPDir->extra->cachedPath[0] = '/'; gPDir->extra->cachedPath[1] = '\0'; #endif return gPDir->extra->cachedPath; } upPath = stdio_getPath(gPDir->extra->upDir); if (upPath == NULL) { // errno is set return NULL; } #ifdef WIN32 if (upPath[0] == '\0') { // The up dir is the root dir. Directly below the root dir are // only dirs for drive letters. No '/' needs to be attached. gPDir->extra->cachedPath = uio_strdup(gPDir->extra->name); return gPDir->extra->cachedPath; } #endif upPathLen = strlen(upPath); #ifndef WIN32 if (upPath[upPathLen - 1] == '/') { // should only happen for "/" upPathLen--; } #endif nameLen = strlen(gPDir->extra->name); if (upPathLen + nameLen + 1 >= PATH_MAX) { errno = ENAMETOOLONG; return NULL; } gPDir->extra->cachedPath = uio_malloc(upPathLen + nameLen + 2); memcpy(gPDir->extra->cachedPath, upPath, upPathLen); gPDir->extra->cachedPath[upPathLen] = '/'; memcpy(gPDir->extra->cachedPath + upPathLen + 1, gPDir->extra->name, nameLen); gPDir->extra->cachedPath[upPathLen + nameLen + 1] = '\0'; } return gPDir->extra->cachedPath; } static stdio_GPDirData * stdio_GPDirData_new(char *name, char *cachedPath, uio_GPDir *upDir) { stdio_GPDirData *result; result = stdio_GPDirData_alloc(); result->name = name; result->cachedPath = cachedPath; result->upDir = upDir; return result; } static void stdio_GPDirData_delete(stdio_GPDirData *gPDirData) { if (gPDirData->upDir != NULL) uio_GPDir_unref(gPDirData->upDir); stdio_GPDirData_free(gPDirData); } static inline stdio_GPDirData * stdio_GPDirData_alloc(void) { stdio_GPDirData *result; result = uio_malloc(sizeof (stdio_GPDirData)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(stdio_GPDirData, (void *) result); #endif return result; } static inline void stdio_GPDirData_free(stdio_GPDirData *gPDirData) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(stdio_GPDirData, (void *) gPDirData); #endif uio_free(gPDirData->name); if (gPDirData->cachedPath != NULL) uio_free(gPDirData->cachedPath); uio_free(gPDirData); } uqm-0.6.2/sc2/src/sc2code/libs/uio/stdio/Makeinfo0000600000175000017500000000002710543202050020120 0ustar joeyjoeyuqm_CFILES="stdio.c" uqm-0.6.2/sc2/src/sc2code/libs/uio/charhashtable.h0000600000175000017500000000230510543202051020266 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _CHARHASHTABLE_H #define _CHARHASHTABLE_H #define HASHTABLE_(identifier) CharHashTable ## _ ## identifier typedef char HASHTABLE_(Key); typedef void HASHTABLE_(Value); #define CharHashTable_HASH CharHashTable_hash #define CharHashTable_EQUAL CharHashTable_equal #define CharHashTable_COPY CharHashTable_copy #define CharHashTable_FREE CharHashTable_free #include "hashtable.h" #endif /* _HASHTABLE_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/io.h0000644000175000017500000001035410546776502016143 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _IO_H #define _IO_H #include #include typedef struct uio_Handle uio_Handle; typedef struct uio_DirHandle uio_DirHandle; typedef struct uio_DirList uio_DirList; typedef struct uio_MountHandle uio_MountHandle; typedef enum { uio_MOUNT_BOTTOM = (0 << 2), uio_MOUNT_TOP = (1 << 2), uio_MOUNT_BELOW = (2 << 2), uio_MOUNT_ABOVE = (3 << 2) } uio_MountLocation; #include "match.h" #include "fstypes.h" #include "mount.h" #include "mounttree.h" #include "uiostream.h" #include "debug.h" struct uio_AutoMount { const char *pattern; match_MatchType matchType; uio_FileSystemID fileSystemID; int mountFlags; // uio_AutoMount **autoMount; // automount rules to apply to file systems automounted // because of this automount rule. }; #ifndef uio_INTERNAL struct uio_DirList { const char **names; int numNames; // The rest of the fields are not visible from the outside }; #endif // Initialise the resource system void uio_init(void); // Uninitialise the resource system void uio_unInit(void); // Open a repository. uio_Repository *uio_openRepository(int flags); // Close a repository opened by uio_openRepository(). void uio_closeRepository(uio_Repository *repository); // Mount a directory into a repository uio_MountHandle *uio_mountDir(uio_Repository *destRep, const char *mountPoint, uio_FileSystemID fsType, uio_DirHandle *sourceDir, const char *sourcePath, const char *inPath, uio_AutoMount **autoMount, int flags, uio_MountHandle *relative); // Unmount a previously mounted dir. int uio_unmountDir(uio_MountHandle *mountHandle); // Unmount all previously mounted dirs. int uio_unmountAllDirs(uio_Repository *repository); // Get the filesystem identifier for a mounted directory. uio_FileSystemID uio_getMountFileSystemType(uio_MountHandle *mountHandle); // Open a file uio_Handle *uio_open(uio_DirHandle *dir, const char *file, int flags, mode_t mode); // Close a file descriptor for a file opened by uio_open int uio_close(uio_Handle *handle); // Rename or move a file or directory. int uio_rename(uio_DirHandle *oldDir, const char *oldPath, uio_DirHandle *newDir, const char *newPath); // Fstat a file descriptor int uio_fstat(uio_Handle *handle, struct stat *statBuf); int uio_stat(uio_DirHandle *dir, const char *path, struct stat *statBuf); int uio_mkdir(uio_DirHandle *dir, const char *name, mode_t mode); ssize_t uio_read(uio_Handle *handle, void *buf, size_t count); int uio_rmdir(uio_DirHandle *dirHandle, const char *path); int uio_lseek(uio_Handle *handle, off_t offset, int whence); ssize_t uio_write(uio_Handle *handle, const void *buf, size_t count); int uio_unlink(uio_DirHandle *dirHandle, const char *path); int uio_getFileLocation(uio_DirHandle *dir, const char *inPath, int flags, uio_MountHandle **mountHandle, char **outPath); // Get a directory handle. uio_DirHandle *uio_openDir(uio_Repository *repository, const char *path, int flags); #define uio_OD_ROOT 1 // Get a directory handle using a path relative to another handle. uio_DirHandle *uio_openDirRelative(uio_DirHandle *base, const char *path, int flags); // Release a directory handle int uio_closeDir(uio_DirHandle *dirHandle); uio_DirList *uio_getDirList(uio_DirHandle *dirHandle, const char *path, const char *pattern, match_MatchType matchType); void uio_DirList_free(uio_DirList *dirList); // For debugging purposes void uio_DirHandle_print(const uio_DirHandle *dirHandle, FILE *out); #ifdef DEBUG # define uio_DEBUG #endif #endif /* _IO_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/ioaux.h0000600000175000017500000000375010543202051016627 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _IOAUX_H #define _IOAUX_H #include "iointrn.h" #include "physical.h" #include "uioport.h" int uio_walkPhysicalPath(uio_PDirHandle *startPDirHandle, const char *path, size_t pathLen, uio_PDirHandle **endPDirHandle, const char **pathRest); uio_PDirHandle *uio_makePath(uio_PDirHandle *pDirHandle, const char *path, size_t pathLen, mode_t mode); int uio_copyFilePhysical(uio_PDirHandle *fromDir, const char *fromName, uio_PDirHandle *toDir, const char *toName); int uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path, int flags, int extraFlags, uio_MountInfo **mountInfoReadPtr, uio_PDirHandle **readPDirHandlePtr, char **readPRootPathPtr, uio_MountInfo **mountInfoWritePtr, uio_PDirHandle **writePDirHandlePtr, char **writePRootPathPtr, char **restPtr); #define uio_GPA_NOWRITE 1 int uio_getPathPhysicalDirs(uio_DirHandle *dirHandle, const char *path, size_t pathLen, uio_PDirHandle ***resPDirHandles, int *resNumPDirHandles, uio_MountTreeItem ***resItems); int uio_verifyPath(uio_DirHandle *dirHandle, const char *path, char **resolvedPath); ssize_t uio_resolvePath(uio_DirHandle *dirHandle, const char *path, size_t pathLen, char **destPath); #endif /* _IOAUX_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/debug.h0000600000175000017500000000163310543202051016566 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _DEBUG_H #define DEBUG_H void uio_debugInteractive(FILE *in, FILE *out, FILE *err); #endif /* _DEBUG_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/uiostream.h0000600000175000017500000000527610543202051017517 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _STREAM_H #define _STREAM_H typedef struct uio_Stream uio_Stream; #include "io.h" uio_Stream *uio_fopen(uio_DirHandle *dir, const char *path, const char *mode); int uio_fclose(uio_Stream *stream); size_t uio_fread(void *buf, size_t size, size_t nmemb, uio_Stream *stream); char *uio_fgets(char *buf, int size, uio_Stream *stream); int uio_fgetc(uio_Stream *stream); #define uio_getc uio_fgetc int uio_ungetc(int c, uio_Stream *stream); int uio_fputc(int c, uio_Stream *stream); #define uio_putc uio_fputc int uio_fputs(const char *s, uio_Stream *stream); int uio_fseek(uio_Stream *stream, long offset, int whence); long uio_ftell(uio_Stream *stream); size_t uio_fwrite(const void *buf, size_t size, size_t nmemb, uio_Stream *stream); int uio_fflush(uio_Stream *stream); int uio_feof(uio_Stream *stream); int uio_ferror(uio_Stream *stream); void uio_clearerr(uio_Stream *stream); uio_Handle *uio_streamHandle(uio_Stream *stream); /* *** Internal definitions follow *** */ #ifdef uio_INTERNAL #include #include #include "iointrn.h" typedef enum { uio_StreamOperation_none, uio_StreamOperation_read, uio_StreamOperation_write } uio_StreamOperation; struct uio_Stream { char *buf; // Start of the buffer. char *dataStart; // Start of the part of the buffer that is in use. char *dataEnd; // Start of the unused part of the buffer. char *bufEnd; // End of the buffer. // INV: buf <= dataStart <= dataEnd <= bufEnd // INV: if 'operation == uio_StreamOperation_write' then buf == dataStart uio_Handle *handle; int status; #define uio_Stream_STATUS_OK 0 #define uio_Stream_STATUS_EOF 1 #define uio_Stream_STATUS_ERROR 2 uio_StreamOperation operation; // What was the last action (reading or writing). This // determines whether the buffer is a read or write buffer. int openFlags; // Flags used for opening the file. }; #endif /* uio_INTERNAL */ #endif /* _STREAM_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/doc/0000755000175000017500000000000010552600274016112 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/uio/doc/todo0000644000175000017500000001430010546776501017012 0ustar joeyjoeyNeeded for use in UQM: - documentation - configuring for GLOB - when doing uio_getStdioPhysical(), if write access is required, but not available on the original location, also copy the file to the temporary dir. Documentation: - use doxygen - Warning: getting (part of) the contents of a directory is fairly slow, as dirs need to be merged. - It would be (theoretically) possible to add HTTP and FTP support for remote file systems. - on adding extra file system types: open, mkdir, rmdir, and unlink should themselves make sure that the physical structure is kept up to date when an entry is removed or added. - stream stuff is not thread safe - uio_fflush() does not accept NULL as argument to flush all streams, like stdio fflush() does. - uio_close() does never fail - The physical open function should call uio_Handle_new and store its own data in it. The physical close function should delete its own data. It's called Will cleanup the general Handle. Analogous for mount/unmount with PRoot - No need to store MountHandles. They will be automatically freed when the repository is closed. - You can use mount stuff from other repositories. - ".." works by nullifying one path component, not by following the ".." link in the directory. "/a/../b" will always be functionally equivalent to "/b", even when "/a" is a symlink. Bugs: - 'openDir(repository, "dir/")' will have the trailing '/' in the dirHandle, which will cause problems. - 'openDirRelative(repository, "/")' causes segfaults later on - uio_rename() doesn't work on directories - uio_getPhysicalAccess() needs to be changed so that it works the same on dirs as on files. stat() can be cleaned up too then. - uio_getPhysicalAccess() will not return ENOENT when (only) the last component does not exist, even when O_RDONLY is used. For O_RDRW, O_CREAT should probably be checked too (function description needs to be updated too then). - A lot of inlining is not possible because of the order of function definitions. - sizeof(size_t) may be less than 4 on some platforms. Check what problems this may cause. At least the size of zip_INPUT_BUFFER_SIZE is an issue. SIZE_MAX can be used to check for sizeof(size_t) at runtime. - remove() is probably more compatible than unlink(). remove() is part of the C standard (as well as POSIX), unlink() is just POSIX. - seeking in files opened as "text" on Windows goes wrong. - Network paths on Windows are not accepted. - No CRLF translation (and ^Z recognition) is done for files read from zip files, even though that may be expected on Windows. Extra features (not necessary for UQM): - Make functions to use for uio_malloc, uio_free and uio_realloc configurable at init. - add uio_mmap() - add match_MATCH_ALL and match_MATCH_NONE - automounting - Unmount automounted filesystems when the originating filesystem is unmounted. - when doing stat() on a directory, merge the stat info of the underlying physical dirs. - read directory information from zip files. - implement ungetc() - make fileblocks public - setmode() for windows? - prevent aliasing of files/dirs, both between two physical file systems (where possible), as within the same filesystem (in particular stdio). On Windows, aliasing can occur easilly when a file or dir is accessed with the long vs the short ("PROGRA~1") name, or when capitalisation is involved. - accept non-dir, non-regular-file dir entries in stdio. - Add non-merging mounts. Make 'merging' an option for the mount. - make uio_rename() work cross-fs, or provide a wrapper which does that. (the system rename() doesn't work cross-fs either, so keeping uio_rename() as it is makes sense, as I'm trying to stay close to the system functions, even though hiding file systems from the user would be nicer) Optimisations (not necessary for UQM): - use mmap for fileBlocks - Use a pre-allocated pool of hash table entries for allocHashEntry. - optimise certain strings (specifically directory entries) by making a string type which has pointers to a shared char array. Invariant: if two strings are the same, they point to the same character array. Consequence: string comparison is pointer comparison. Making a new string would imply checking the existing strings. Existing strings should be in a hash table. - optimise paths Encode all paths internally as (double-linked) chains of path components This way, operations like going up one path component, are cheap. Each path component could either be represented by a pointer to a string, (possibly shared as above), or as a pair of begin and end pointers (or begin pointer and length). In the latter case, there's no need for copying strings when parsing a user-supplied string, but sharing of strings would not be possible. It's probably possible to use both methods next to eachother; shared strings for stored paths, and pointers into a path for user-supplied strings (which would be freed when the call returns). Instead of a linked list, perhaps an array can be used, as paths rarely change. It would be a problem if for some reason, recursively path components are added to a path. - (maybe) keep track of already issued handles, so that the ref counter could just be incremented, instead of issuing a new one. (uio_getPDirEntryHandle) - Make it possible for people to add their own file system, without giving away the internals. (no wanton including of .h files) - Don't cache stdio dir structure (and don't read the dir leading up to the dir that is actually needed) - mounting foo to /Foo and foo/bar to /Foo/Bar should result in only one physical structure. Preferably, it shouldn't even lead to two mountInfo structures for /Foo/Bar, so that merging the dirs is not unnecessarilly expensive. - add uio_access() (uqm fileExists can be redone then) - implement the physical function cleanup() to clean up the physical structure. Int argument that specifies how thoroughly. On it depends whether cache is cleaned, whether stuff is realloc'ed to defragment memory, etc. Cleanups (not necessary for UQM): - rename function names to be more like class names for as far as that's not already done. uio_PRoot_unref etc - Add uio_fatal(), uio_error(), uio_warning() - Clean up the include structure uqm-0.6.2/sc2/src/sc2code/libs/uio/doc/conventions0000644000175000017500000000225610545750177020421 0ustar joeyjoeyThis file describes the various conventions used in the source. -= Naming of constructors and destructors =- uio_Thing *uio_Thing_new(args) Allocates the structure, and initialises it from the arguments. Arguments are always used as-is; if they are reference-counted, and the caller still needs a reference, it is up to the caller to increment the reference counter. void uio_Thing_delete(uio_Thing *thing) Frees the structure and all sub-structures. Decrements reference counters to shared structures. uio_Thing *uio_Thing_alloc() Allocates memory for a new structure. Could be omited for standard allocators. Particularly relevant when a non-standard allocation scheme is used (for instance, allocation from a pool of pre-allocated strucures). void uio_Thing_free(Thing *thing) Frees the memory allocated for thing (reverse of uio_Thing_alloc). Could be omited for standard deallocators. void uio_Thing_ref(Thing *thing) Increments the reference counter to the structure. void uio_Thing_unref(Thing *thing) Decrements the reference counter to the structure. Calls uio_Thing_Delete() if the refcounter becomes 0. These functions are always declared and defined in this order. uqm-0.6.2/sc2/src/sc2code/libs/uio/doc/basics0000600000175000017500000001244310543202050017263 0ustar joeyjoey-= Introduction =- The file io system I present here provides the user with a virtual file systems on which normal POSIX-like file operations can be performed. A virtual file system consists of a number of underlying filesystems merged together in one directory structure. Underlying file systems can be POSIX filesystems, or zip archives, but others can be added easilly. Filesystems are grafted into the virtual filesystem either explicitely, by mounting, or implicitely, by having files of a specific type (for instance those ending on .zip) mounted automatically. When a filesystem is mounted to a directory which already exists in an earlier mounted file system, files in the later mounted file system hide files in an earlier mounted file system. Files present in a filesystem mounted earlier that don't exist in a filesystem mounted later will remain visible. Accessing compressed files inside compressed files is possible, though slow. -= Nomenclature =- 'repository' A collection of files from various sources as a virtual file system. 'physical directory structure' An underlying filesystem, such as a POSIX filesystem, or a .zip archive. 'logical directory structure' The merger of one or more Physical directory structures. 'mounting' Grafting a physical directory structure in a logical directory system. When mounting several dirs on top of eachother, I refer to later mounted dirs as 'higher' dirs, and earlier mounted dirs as 'lower' dirs. 'directory entry' A file or subdirectory within a directory. -= API =- Types: uio_Repository - A struct describing a repository uio_Handle - A handle for working on files uio_DirHandle - A handle for working on directories TODO: functions -= Behaviour relating directory structures =- The design of the virtual filesystem is guided by the following rules: - Combined directories contain the entries of each directory. If some of the source directories contain an entry with the same name, the combined directory will contain the entry of the topmost directory. (this means a directory can hide a file and the other way around) - Entries hidden in this way are never accessable. - Where possible, actions on directory entries within a combined directory are done as in a normal file system. Because of these, some design decisions have been made: - New entries are created in the topmost writable filesystem. If the path to the directory where the entry is to be created does not exist, it is created [1]. - When a file is to be opened for writing, and the file in the combined filesystem exists, but is not writable, and there exists a writable filesystem, mounted higher than the filesystem where the existing file resides, the file is first copied to the topmost writable filesystem. [1] I could have decided to use a pre-existing writable directory if one is available. With this choice, when no such pre-existing directory exists, it would make sense to complete the path in the writable filesystem in which the part of the path that does exist is the longest. As you can't create a directory inside a specific filesystem, this would complicate and confuse things for the user. In specific, for various actions: opening a file: - if O_RDONLY: - open the file in the highest dir. - if O_WRONLY or O_RDWR: - if file already exists: - if O_CREAT and O_EXCL: return EEXIST - if file is writable, use that one - if file is not writable, copy it to the highest writable location higher than the location of that file (don't bother if O_TRUNC) and use the new file. If necessary, create the path leading upto it. If no such location exists, return EACCESS. - if file does not exist: - if not O_CREAT: return ENOENT - if the path to the file does not exists, return ENOENT. - find the highest writable dir and open the file there, creating the path leading upto it if necessary. removing a file: - try removing the specified file from all physical directory structures for a repository. - once a file is encountered that can't be removed, return an error for that and don't try the rest. creating a directory: - as for opening a file with O_WRONLY | O_CREAT | O_EXCL removing a directory: - as for removing a file (but a physical directory not being empty is a reason for failure) -= Limitations =- There's no limit to the length of a path in the logical file system. Paths in the underlying physical filesystem can be limited though. At the moment, the system is not thread safe. Only one thread should access a repository at once. Seperate threads working on seperate repositories is no problem, as long as the repositories don't overlap. -= Internals =- Types: uio_MountTree - A node in a data structure describing the mounted directories. uio_PRoot - A struct describing the a physical file system. uio_PRootExtra - Filesystem-dependant extra data for a PRoot. uio_GPRoot - Generic filesystem-dependant data for a PRoot, used as uio_PRootExtra. uio_GPRootExtra - Extra filesystem-dependant data for a PRoot, when using uio_GPRoot for generic filesystem-dependant data. uio_GPDir - Generic structure representing a node in a physical directory structure describing one directory. uio_GPFile - Generic structure describing a file in a physical file system. TODO: functions uqm-0.6.2/sc2/src/sc2code/libs/uio/gphys.h0000600000175000017500000002350110543202051016630 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _GPHYS_H #define _GPHYS_H #include "uioport.h" #ifndef uio_INTERNAL_PHYSICAL typedef void *uio_GPRootExtra; typedef void *uio_GPDirExtra; typedef void *uio_GPFileExtra; #endif typedef struct CharHashTable_HashTable uio_GPDirEntries; #define uio_GPDirEntries_new() \ ((uio_GPDirEntries *) CharHashTable_newHashTable(NULL, NULL, NULL, \ NULL, 0, 0.85, 0.9)) #define uio_GPDirEntries_add(hashTable, name, item) \ CharHashTable_add((CharHashTable_HashTable *) hashTable, name, \ (void *) item) #define uio_GPDirEntries_remove(hashTable, name) \ CharHashTable_remove((CharHashTable_HashTable *) hashTable, name) #define uio_GPDirEntries_count(hashTable) \ CharHashTable_count((CharHashTable_HashTable *) hashTable) #define uio_GPDirEntries_find(hashTable, name) \ ((uio_GPDirEntry *) CharHashTable_find( \ (CharHashTable_HashTable *) hashTable, name)) #define uio_GPDirEntries_deleteHashTable(hashTable) \ CharHashTable_deleteHashTable((CharHashTable_HashTable *) hashTable) //#define uio_GPDirEntries_clear(hashTable) // CharHashTable_clear((CharHashTable_HashTable *) hashTable) #define uio_GPDirEntries_getIterator(hashTable) \ ((uio_GPDirEntries_Iterator *) CharHashTable_getIterator( \ (const CharHashTable_HashTable *) hashTable)) #define uio_GPDirEntries_iteratorDone(iterator) \ CharHashTable_iteratorDone((const CharHashTable_Iterator *) iterator) #define uio_GPDirEntries_iteratorName(iterator) \ CharHashTable_iteratorKey((CharHashTable_Iterator *) iterator) #define uio_GPDirEntries_iteratorItem(iterator) \ ((uio_GPDirEntry *) CharHashTable_iteratorValue( \ (CharHashTable_Iterator *) iterator)) #define uio_GPDirEntries_iteratorNext(iterator) \ ((uio_GPDirEntries_Iterator *) CharHashTable_iteratorNext( \ (CharHashTable_Iterator *) iterator)) #define uio_GPDirEntries_freeIterator(iterator) \ CharHashTable_freeIterator(iterator) // 'forward' declarations typedef struct uio_GPDirEntry uio_GPDirEntry; typedef struct uio_GPDir uio_GPDir; typedef struct uio_GPFile uio_GPFile; typedef struct uio_GPRoot_Operations uio_GPRoot_Operations; typedef struct uio_GPRoot uio_GPRoot; #include "charhashtable.h" typedef CharHashTable_Iterator uio_GPDirEntries_Iterator; #ifdef uio_INTERNAL_GPHYS typedef uio_GPDirEntries_Iterator *uio_NativeEntriesContext; #endif typedef struct uio_GPRoot *uio_PRootExtra; typedef struct uio_GPDir uio_GPDirHandle; typedef uio_GPDirHandle *uio_PDirHandleExtra; typedef struct uio_GPFile uio_GPFileHandle; typedef uio_GPFileHandle *uio_PFileHandleExtra; #ifdef DEBUG # include #endif #include "iointrn.h" #ifdef uio_MEM_DEBUG # include "memdebug.h" #endif struct uio_GPRoot_Operations { void (*fillGPDir)(uio_GPDir *); void (*deleteGPRootExtra)(uio_GPRootExtra); void (*deleteGPDirExtra)(uio_GPDirExtra); void (*deleteGPFileExtra)(uio_GPFileExtra); }; struct uio_GPRoot { int flags; #define uio_GPRoot_PERSISTENT 0x4000 /* Set if directories in this file system should not be deleted * as long as the file system is mounted. If this flag is not * set, the GPDir structure is only a cache. */ uio_GPRoot_Operations *ops; uio_GPRootExtra extra; }; #define uio_GPDirEntry_COMMON \ int flags; \ int ref; \ /* Number of times this structure is referenced from the \ * outside (so not counting the references from subdirs \ * or files when the entry is a directory) \ */ #define uio_GPDirEntry_NOCACHE uio_PRoot_NOCACHE /* * uio_GPDirEntry * super-'class' of uio_GPDir and uio_GPFile */ struct uio_GPDirEntry { uio_GPDirEntry_COMMON void *extra; }; #define uio_GPDirEntry_TYPE_REG 0x0000 #define uio_GPDirEntry_TYPE_DIR 0x0001 #define uio_GPDirEntry_TYPEMASK 0x0001 /* * uio_GPDir * Represents a directory in a physical directory structure. * sub-'class' of uio_GPDirEntry */ struct uio_GPDir { uio_GPDirEntry_COMMON # define uio_GPDir_NOCACHE uio_GPDirEntry_NOCACHE /* This directory info will not be cached. * PDIR_COMPLETE is irrelevant in this case */ # define uio_GPDir_COMPLETE 0x1000 /* Set if fillDir should not be called if an entry does not * exist in a directory. Usually set if the entire dir has been * completely read in. */ # define uio_GPDir_DETACHED 0x2000 /* Set if this dir is not linked to from elsewhere in the physical * structure */ # define uio_GPDir_PERSISTENT 0x4000 /* Set if this dir should not be deleted as long as the file * system is mounted. If this flag is not set, the GPDir * structure is only a cache. */ uio_GPDirExtra extra; /* extra internal data for some filesystem types */ uio_PRoot *pRoot; uio_GPDirEntries *entries; }; /* * uio_GPFile * Represents a file in a physical directory structure. * sub-'class' of uio_GPDirEntry */ struct uio_GPFile { uio_GPDirEntry_COMMON # define uio_GPFile_NOCACHE uio_GPDirEntry_NOCACHE /* Info on this file will not be cached. */ uio_GPFileExtra extra; /* extra internal data for some filesystem types */ uio_PRoot *pRoot; }; static inline uio_bool uio_GPDirEntry_isReg(uio_GPDirEntry *gPDirEntry) { return (gPDirEntry->flags & uio_GPDirEntry_TYPEMASK) == uio_GPDirEntry_TYPE_REG; } static inline uio_bool uio_GPDirEntry_isDir(uio_GPDirEntry *gPDirEntry) { return (gPDirEntry->flags & uio_GPDirEntry_TYPEMASK) == uio_GPDirEntry_TYPE_DIR; } #ifdef DEBUG void uio_GPDirEntry_print(FILE *outStream, uio_GPDirEntry *gPDirEntry); void uio_GPDir_print(FILE *outStream, uio_GPDir *gPDir); void uio_GPFile_print(FILE *outStream, uio_GPFile *pFile); #endif uio_NativeEntriesContext uio_GPDir_openEntries(uio_PDirHandle *pDirHandle); int uio_GPDir_readEntries(uio_NativeEntriesContext *iterator, char *buf, size_t len); void uio_GPDir_closeEntries(uio_NativeEntriesContext iterator); int uio_GPDir_entryCount(const uio_GPDir *gPDir); int uio_gPDirFlagsFromPRootFlags(int flags); int uio_gPFileFlagsFromPRootFlags(int flags); uio_PRoot *uio_GPRoot_makePRoot(uio_FileSystemHandler *handler, int pRootFlags, uio_GPRoot_Operations *ops, uio_GPRootExtra gPRootExtra, int gPRootFlags, uio_Handle *handle, uio_GPDirExtra gPDirExtra, int gPDirFlags); int uio_GPRoot_umount(uio_PRoot *pRoot); uio_GPDir *uio_GPDir_prepareSubDir(uio_GPDir *gPDir, const char *dirName); void uio_GPDir_commitSubDir(uio_GPDir *gPDir, const char *dirName, uio_GPDir *subDir); void uio_GPDir_addFile(uio_GPDir *gPDir, const char *fileName, uio_GPFile *file); void uio_GPDir_removeFile(uio_GPDir *gPDir, const char *fileName); void uio_GPDir_removeSubDir(uio_GPDir *gPDir, const char *dirName); void uio_GPDir_setComplete(uio_GPDir *gPDir, uio_bool flag); uio_GPDirEntry *uio_GPDir_getGPDirEntry(uio_GPDir *gPDir, const char *name); uio_PDirEntryHandle *uio_GPDir_getPDirEntryHandle( const uio_PDirHandle *pDirHandle, const char *name); int uio_walkGPPath(uio_GPDir *startGPDir, const char *path, size_t pathLen, uio_GPDir **endGPDir, const char **pathRest); uio_PDirHandle *uio_GPDir_makePDirHandle(uio_GPDir *gPDir); void uio_GPDir_fill(uio_GPDir *gPDir); void uio_GPRoot_deleteGPRootExtra(uio_GPRoot *gPRoot); void uio_GPDir_deleteGPDirExtra(uio_GPDir *gPDir); void uio_GPFile_deleteGPFileExtra(uio_GPFile *gPFile); void uio_GPDirHandle_delete(uio_GPDirHandle *gPDirHandle); void uio_GPFileHandle_delete(uio_GPFileHandle *gPFileHandle); void uio_GPDirEntry_delete(uio_GPDirEntry *gPDirEntry); uio_GPRoot *uio_GPRoot_new(uio_GPRoot_Operations *ops, uio_GPRootExtra extra, int flags); void uio_GPRoot_delete(uio_GPRoot *gPRoot); uio_GPDir *uio_GPDir_new(uio_PRoot *pRoot, uio_GPDirExtra extra, int flags); void uio_GPDir_delete(uio_GPDir *gPDir); uio_GPFile *uio_GPFile_new(uio_PRoot *pRoot, uio_GPFileExtra extra, int flags); void uio_GPFile_delete(uio_GPFile *gPFile); static inline void uio_GPDirEntry_ref(uio_GPDirEntry *gPDirEntry) { #ifdef uio_MEM_DEBUG if (uio_GPDirEntry_isDir(gPDirEntry)) { uio_MemDebug_debugRef(uio_GPDir, (void *) gPDirEntry); } else { uio_MemDebug_debugRef(uio_GPFile, (void *) gPDirEntry); } #endif gPDirEntry->ref++; } static inline void uio_GPDirEntry_unref(uio_GPDirEntry *gPDirEntry) { assert(gPDirEntry->ref > 0); #ifdef uio_MEM_DEBUG if (uio_GPDirEntry_isDir(gPDirEntry)) { uio_MemDebug_debugUnref(uio_GPDir, (void *) gPDirEntry); } else { uio_MemDebug_debugUnref(uio_GPFile, (void *) gPDirEntry); } #endif gPDirEntry->ref--; if (gPDirEntry->ref == 0) uio_GPDirEntry_delete(gPDirEntry); } static inline void uio_GPDir_ref(uio_GPDir *gPDir) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugRef(uio_GPDir, (void *) gPDir); #endif gPDir->ref++; } static inline void uio_GPDir_unref(uio_GPDir *gPDir) { assert(gPDir->ref > 0); #ifdef uio_MEM_DEBUG uio_MemDebug_debugUnref(uio_GPDir, (void *) gPDir); #endif gPDir->ref--; if (gPDir->ref == 0) uio_GPDir_delete(gPDir); } static inline void uio_GPFile_ref(uio_GPFile *gPFile) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugRef(uio_GPFile, (void *) gPFile); #endif gPFile->ref++; } static inline void uio_GPFile_unref(uio_GPFile *gPFile) { assert(gPFile->ref > 0); #ifdef uio_MEM_DEBUG uio_MemDebug_debugUnref(uio_GPFile, (void *) gPFile); #endif gPFile->ref--; if (gPFile->ref == 0) uio_GPFile_delete(gPFile); } #endif /* _GPHYS_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/mounttree.c0000644000175000017500000005617610546776502017565 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #ifdef DEBUG # include #endif #include #include "iointrn.h" #include "uioport.h" #include "mounttree.h" #include "paths.h" #include "types.h" #include "mem.h" #include "uioutils.h" #ifdef uio_MEM_DEBUG # include "memdebug.h" #endif static uio_MountTree *uio_mountTreeAddMountInfoRecTree( uio_Repository *repository, uio_MountTree *tree, uio_MountInfo *mountInfo, const char *start, const char *end, uio_PathComp *upComp, uio_MountLocation location, const uio_MountInfo *relative); static inline uio_MountTree *uio_mountTreeAddMountInfoRecTreeSub( uio_Repository *repository, uio_MountTree **tree, uio_MountInfo *mountInfo, const char *start, const char *end, uio_MountLocation location, const uio_MountInfo *relative); static void uio_mountTreeAddMountInfoLocAll(uio_Repository *repository, uio_MountTree *tree, uio_MountInfo *mountInfo, int depth, uio_MountLocation location, const uio_MountInfo *relative); static uio_MountTreeItem *uio_copyMountTreeItems(uio_MountTreeItem *item, int extraDepth); static void uio_addMountTreeItem(uio_Repository *repository, uio_MountTreeItem **pLocs, uio_MountTreeItem *item, uio_MountLocation location, const uio_MountInfo *relative); static uio_MountTree *uio_mountTreeAddNewSubTree(uio_Repository *repository, uio_MountTree *tree, const char *path, uio_MountInfo *mountInfo, uio_PathComp *upComp, uio_MountLocation location, const uio_MountInfo *relative); static void uio_mountTreeAddSub(uio_MountTree *tree, uio_MountTree *sub); static uio_MountTree * uio_splitMountTree(uio_MountTree **tree, uio_PathComp *lastComp, int depth); static void uio_mountTreeRemoveMountInfoRec(uio_MountTree *mountTree, uio_MountInfo *mountInfo); static void uio_printMount(FILE *outStream, const uio_MountInfo *mountInfo); static inline uio_MountTree * uio_MountTree_new(uio_MountTree *subTrees, uio_MountTreeItem *pLocs, uio_MountTree *upTree, uio_PathComp *comps, uio_PathComp *lastComp, uio_MountTree *next); static inline uio_MountTreeItem *uio_MountTree_newItem( uio_MountInfo *mountInfo, int depth, uio_MountTreeItem *next); static inline void uio_MountTreeItem_delete(uio_MountTreeItem *item); static inline uio_MountTree *uio_MountTree_alloc(void); static inline uio_MountTreeItem *uio_MountTreeItem_alloc(void); static inline uio_MountInfo *uio_MountInfo_alloc(void); static inline void uio_MountTree_free(uio_MountTree *mountTree); static inline void uio_MountTreeItem_free(uio_MountTreeItem *mountTreeItem); static inline void uio_MountInfo_free(uio_MountInfo *mountInfo); // make the root mount Tree uio_MountTree * uio_makeRootMountTree(void) { return uio_MountTree_new(NULL, NULL, NULL, NULL, NULL, NULL); } // Add a MountInfo structure to a MountTree in the place pointed // to by 'path'. // returns the MountTree for the location at the end of the path uio_MountTree * uio_mountTreeAddMountInfo(uio_Repository *repository, uio_MountTree *mountTree, uio_MountInfo *mountInfo, const char *path, uio_MountLocation location, const uio_MountInfo *relative) { const char *start, *end; getFirstPath0Component(path, &start, &end); return uio_mountTreeAddMountInfoRecTree(repository, mountTree, mountInfo, start, end, NULL, location, relative); } // recursive helper for uio_mountTreeAddMountInfo // returns the MountTree for the location at the end of the path static uio_MountTree * uio_mountTreeAddMountInfoRecTree(uio_Repository *repository, uio_MountTree *tree, uio_MountInfo *mountInfo, const char *start, const char *end, uio_PathComp *upComp, uio_MountLocation location, const uio_MountInfo *relative) { uio_MountTree **sub; if (*start == '\0') { // End of the path. Put the MountInfo here and on all subtrees below // this level. uio_mountTreeAddMountInfoLocAll(repository, tree, mountInfo, 0, location, relative); return tree; } // Check if sub trees match the path. for (sub = &tree->subTrees; *sub != NULL; sub = &(*sub)->next) { uio_MountTree *resTree; resTree = uio_mountTreeAddMountInfoRecTreeSub(repository, sub, mountInfo, start, end, location, relative); if (resTree != NULL) { // handled return resTree; } } // No subtree found matching (part of) 'path'. // Need to add a new tree sub return uio_mountTreeAddNewSubTree(repository, tree, start, mountInfo, upComp, location, relative); } // recursive helper for uio_mountTreeAddMountInfo // Pre: *start != '\0' // returns the MountTree for the location at the end of the path, if // that falls within this tree. If not, returns NULL. static inline uio_MountTree * uio_mountTreeAddMountInfoRecTreeSub(uio_Repository *repository, uio_MountTree **tree, uio_MountInfo *mountInfo, const char *start, const char *end, uio_MountLocation location, const uio_MountInfo *relative) { uio_PathComp *comp, *lastComp; int depth; comp = (*tree)->comps; if (strncmp(comp->name, start, end - start) != 0 || comp->name[end - start] != '\0') { // first component does not match; this is not the correct subTree return NULL; } depth = 1; // try to match all components of the directory path to this subTree. while (1) { getNextPath0Component(&start, &end); lastComp = comp; comp = comp->next; if (comp == NULL) break; if (*start == '\0') { // end of the path reached // We need to split up the components and insert a new // MountTree here. uio_MountTree *newTree; newTree = uio_splitMountTree(tree, lastComp, depth); // Add mountInfo to each of the MountTrees below newTree. uio_mountTreeAddMountInfoLocAll(repository, newTree, mountInfo, 0, location, relative); return newTree; } if (strncmp(comp->name, start, end - start) != 0 || comp->name[end - start] != '\0') { // Some, but not all components matched; we need to split // up the components and add a new subTree here for the // (non-matching) rest of the path. uio_MountTree *newTree; newTree = uio_splitMountTree(tree, lastComp, depth); // A new Tree is added at the split-point. return uio_mountTreeAddNewSubTree(repository, newTree, start, mountInfo, lastComp, location, relative); } getNextPath0Component(&start, &end); depth++; } // All components matched. We can recurse to the next subdir. return uio_mountTreeAddMountInfoRecTree(repository, *tree, mountInfo, start, end, lastComp, location, relative); } // Add a MountInfo struct 'mountInfo' to the pLocs fields of all subTrees // starting with 'tree'. // 'depth' is the distance to the MountTree where the MountInfo is located. static void uio_mountTreeAddMountInfoLocAll(uio_Repository *repository, uio_MountTree *tree, uio_MountInfo *mountInfo, int depth, uio_MountLocation location, const uio_MountInfo *relative) { uio_MountTreeItem *newPLoc; uio_MountTree *subTree; int compCount; // Add a new PLoc to this mountTree newPLoc = uio_MountTree_newItem(mountInfo, depth, NULL); uio_addMountTreeItem(repository, &tree->pLocs, newPLoc, location, relative); // Recurse for subtrees for (subTree = tree->subTrees; subTree != NULL; subTree = subTree->next) { compCount = uio_countPathComps(subTree->comps); uio_mountTreeAddMountInfoLocAll( repository, subTree, mountInfo, depth + compCount, location, relative); } } // pre: repository->mounts is already updated // pre: if location is uio_MOUNT_BELOW or uio_MOUNT_ABOVE, 'relative' // exists in repository->mounts static void uio_addMountTreeItem(uio_Repository *repository, uio_MountTreeItem **pLocs, uio_MountTreeItem *item, uio_MountLocation location, const uio_MountInfo *relative) { switch (location) { case uio_MOUNT_TOP: item->next = *pLocs; *pLocs = item; break; case uio_MOUNT_BOTTOM: while (*pLocs != NULL) pLocs = &(*pLocs)->next; item->next = NULL; *pLocs = item; break; case uio_MOUNT_ABOVE: { uio_MountInfo **mountInfo; mountInfo = repository->mounts; while (*mountInfo != relative) { assert(*mountInfo != NULL); if ((*pLocs)->mountInfo == *mountInfo) pLocs = &(*pLocs)->next; mountInfo++; } item->next = *pLocs; *pLocs = item; break; } case uio_MOUNT_BELOW: { uio_MountInfo **mountInfo; mountInfo = repository->mounts; while (*mountInfo != relative) { assert(*mountInfo != NULL); if ((*pLocs)->mountInfo == *mountInfo) pLocs = &(*pLocs)->next; mountInfo++; } item->next = (*pLocs)->next; (*pLocs)->next = item; break; } default: assert(false); } } // Copy a chain of MountTreeItems, but increase the depth by 'extraDepth'. static uio_MountTreeItem * uio_copyMountTreeItems(uio_MountTreeItem *item, int extraDepth) { uio_MountTreeItem *result, **resPtr; uio_MountTreeItem *newItem; resPtr = &result; while (item != NULL) { newItem = uio_MountTree_newItem( item->mountInfo, item->depth + extraDepth, NULL); *resPtr = newItem; resPtr = &newItem->next; item = item->next; } *resPtr = NULL; return result; } // add a new sub tree under a tree 'tree'. // 'path' is the part leading up to the new tree and // 'mountInfo' is the MountInfo structure to at there. // 'upComp' points to the last path component that lead to 'tree'. static uio_MountTree * uio_mountTreeAddNewSubTree(uio_Repository *repository, uio_MountTree *tree, const char *path, uio_MountInfo *mountInfo, uio_PathComp *upComp, uio_MountLocation location, const uio_MountInfo *relative) { uio_MountTreeItem *item, *items; uio_MountTree *newTree; uio_PathComp *compList, *lastComp; int compCount; compList = uio_makePathComps(path, upComp); compCount = uio_countPathComps(compList); lastComp = uio_lastPathComp(compList); item = uio_MountTree_newItem(mountInfo, 0, NULL); item->next = NULL; items = uio_copyMountTreeItems(tree->pLocs, compCount); uio_addMountTreeItem(repository, &items, item, location, relative); newTree = uio_MountTree_new( NULL /* subTrees */, items /* pLocs */, tree /* upTree */, compList /* comps */, lastComp /* lastComp */, NULL /* next */); uio_mountTreeAddSub(tree, newTree); return newTree; } // add a sub structure to the end of the 'subTrees' list of a tree. static void uio_mountTreeAddSub(uio_MountTree *tree, uio_MountTree *sub) { uio_MountTree **subPtr; for (subPtr = &tree->subTrees; *subPtr != NULL; subPtr = &(*subPtr)->next) { // Nothing to do here. } *subPtr = sub; } // Add a new MountTree structure in between two MountTrees. // Tree points to the pointer for the tree in front of which the new // tree needs to be placed (at depth 'depth'). // 'lastComp' is the last pathComp of the part before the splitting point // It returns the new MountTree. static uio_MountTree * uio_splitMountTree(uio_MountTree **tree, uio_PathComp *lastComp, int depth) { uio_MountTree *newTree; uio_MountTreeItem *items; items = uio_copyMountTreeItems((*tree)->upTree->pLocs, depth); newTree = uio_MountTree_new( *tree /* subTrees */, items /* pLocs */, (*tree)->upTree /* upTree */, (*tree)->comps /* comps */, lastComp /* lastComp */, NULL /* next */); (*tree)->upTree = newTree; (*tree)->comps = lastComp->next; lastComp->next = NULL; *tree = newTree; return newTree; } void uio_mountTreeRemoveMountInfo(uio_Repository *repository, uio_MountTree *mountTree, uio_MountInfo *mountInfo) { uio_MountTree **subTreePtr; uio_MountTree *upTree; // If the tree has no sub-trees and it has the same items as the // upTree, with 'mountInfo' added, then the tree is a dead end // and can be removed entirely. // First we handle the other case. // Note that if the upTree has exactly one item less than the tree // itself, these items must be the same, plus mountInfo for the // tree itself, as each tree has at least the items of its upTree. if (mountTree->upTree == NULL || mountTree->subTrees != NULL || uio_mountTreeCountPLocs(mountTree) != uio_mountTreeCountPLocs(mountTree->upTree) + 1) { // We can't remove the tree itself. // We need to remove the mountInfo from the tree, and all subTrees. // Then we're done. uio_mountTreeRemoveMountInfoRec(mountTree, mountInfo); return; } // mountTree itself can be removed. // First remove the tree from the list of subtrees of the upTree. subTreePtr = &mountTree->upTree->subTrees; while (1) { assert(*subTreePtr != NULL); if (*subTreePtr == mountTree) break; subTreePtr = &(*subTreePtr)->next; } *subTreePtr = mountTree->next; // Save the upTree for later. upTree = mountTree->upTree; // Remove the tree itself. uio_MountTree_delete(mountTree); // The upTree itself could have become unnecessary now. // This is the case when upTree now only has one subTree, and upTree // and the subTree have the same items. // Again, same item count implies same items. if (upTree->subTrees == NULL || upTree->subTrees->next != NULL || uio_mountTreeCountPLocs(upTree) != uio_mountTreeCountPLocs(upTree->subTrees)) { // upTree is still necessary. We're done. return; } // Merge upTree and upTree->subTrees. // It would be easiest to keep upTree, and throw upTree->subTrees away, // but that's not possible as external links point to upTree->subTrees. // First merge the path components: assert(upTree->subTrees->lastComp != NULL); upTree->subTrees->lastComp->next = upTree->subTrees->comps; upTree->subTrees->lastComp = upTree->lastComp; upTree->subTrees->comps = upTree->comps; // Now let the pointer that pointed to upTree, point to upTree->subTrees. // Change upTree->next accordingly. if (upTree->upTree == NULL) { assert(repository->mountTree == upTree); repository->mountTree = upTree->subTrees; // upTree->subTrees->next is already NULL } else { uio_MountTree *next; subTreePtr = &upTree->upTree->subTrees; while (1) { assert(*subTreePtr != NULL); if (*subTreePtr == upTree) break; subTreePtr = &(*subTreePtr)->next; } next = (*subTreePtr)->next; *subTreePtr = upTree->subTrees; upTree->subTrees->next = next; } // Now delete the tree itself upTree->subTrees = NULL; upTree->comps = NULL; uio_MountTree_delete(upTree); } // pre: mountInfo exists in mountTree->pLocs (and hence in pLocs for // every sub-tree) static void uio_mountTreeRemoveMountInfoRec(uio_MountTree *mountTree, uio_MountInfo *mountInfo) { uio_MountTree *subTree; uio_MountTreeItem **itemPtr, *item; // recurse for all subTrees for (subTree = mountTree->subTrees; subTree != NULL; subTree = subTree->next) uio_mountTreeRemoveMountInfoRec(subTree, mountInfo); // Find the mount info in this tree. itemPtr = &mountTree->pLocs; while (1) { assert(*itemPtr != NULL); // We know an item with the specified mountInfo // must be here somewhere. if ((*itemPtr)->mountInfo == mountInfo) { // Found it. break; } itemPtr = &(*itemPtr)->next; } item = *itemPtr; *itemPtr = item->next; uio_MountTreeItem_delete(item); } // Count the number of pLocs in a tree that leads to. int uio_mountTreeCountPLocs(const uio_MountTree *tree) { int count; uio_MountTreeItem *item; count = 0; for (item = tree->pLocs; item != NULL; item = item->next) count++; return count; } // resTree may point to top // pPath may point to path void uio_findMountTree(uio_MountTree *top, const char *path, uio_MountTree **resTree, const char **pPath) { const char *start, *end, *pathFromTree; uio_MountTree *tree, *sub; uio_PathComp *comp; getFirstPath0Component(path, &start, &end); tree = top; while(1) { if (*start == '\0') { *resTree = tree; *pPath = start; return; } pathFromTree = start; sub = tree->subTrees; while(1) { if (sub == NULL) { // No matching sub Dirs found. So we report back the current // dir. *resTree = tree; *pPath = pathFromTree; return; } comp = sub->comps; if (strncmp(comp->name, start, end - start) == 0 && comp->name[end - start] == '\0') break; sub = sub->next; } // Found a Sub dir which matches at least partially. while (1) { getNextPath0Component(&start, &end); comp = comp->next; if (comp == NULL) break; if (*start == '\0' || strncmp(comp->name, start, end - start) != 0 || comp->name[end - start] != '\0') { // either the path ends here, or the path in the tree does. // either way, the last Tree is the one we want. *resTree = tree; *pPath = pathFromTree; return; } } // all components matched until the next MountTree tree = sub; } } // finds the path to the MountInfo associated with a mountTreeItem // given a path to the 'item' itself. // 'item' is the mountTreeItem // 'endComp' is the last PathComp leading to 'item' // 'start' is the start of the path to the item char * uio_mountTreeItemRestPath(const uio_MountTreeItem *item, uio_PathComp *endComp, const char *path) { int i; const char *pathPtr; i = item->depth; while (i--) endComp = endComp->up; pathPtr = path; if (endComp != NULL) { while (1) { pathPtr += endComp->nameLen; endComp = endComp->up; if (endComp == NULL) break; pathPtr++; // for a '/' } } if (*path == '/') { // / at the beginning of the path pathPtr++; } if (*pathPtr == '/') { // / at the end of the path pathPtr++; } // return (char *) pathPtr; // gives warning // return *((char **)((void *) &pathPtr)); // not portable return (char *) unconst((const void *) pathPtr); } void uio_printMountTree(FILE *outStream, const uio_MountTree *tree, int indent) { uio_MountTree *sub; uio_PathComp *comp; fprintf(outStream, "("); uio_printMountTreeItems(outStream, tree->pLocs); fprintf(outStream, ")\n"); for (sub = tree->subTrees; sub != NULL; sub = sub->next) { int newIndent; newIndent = indent; fprintf(outStream, "%*s", indent, ""); for (comp = sub->comps; comp != NULL; comp = comp->next) { fprintf(outStream, "/%s", comp->name); newIndent += 1 + comp->nameLen; } fprintf(outStream, " "); newIndent += 1; uio_printMountTree(outStream, sub, newIndent); } } void uio_printMountTreeItem(FILE *outStream, const uio_MountTreeItem *item) { uio_printMountInfo(outStream, item->mountInfo); fprintf(outStream, ":%d", item->depth); } void uio_printMountTreeItems(FILE *outStream, const uio_MountTreeItem *item) { if (!item) return; while(1) { uio_printMountTreeItem(outStream, item); item = item->next; if (item == NULL) break; fprintf(outStream, ", "); } } void uio_printPathToMountTree(FILE *outStream, const uio_MountTree *tree) { if (tree->upTree == NULL) { fprintf(outStream, "/"); } else uio_printPathToComp(outStream, tree->lastComp); } void uio_printMountInfo(FILE *outStream, const uio_MountInfo *mountInfo) { uio_FileSystemInfo *fsInfo; fsInfo = uio_getFileSystemInfo(mountInfo->fsID); fprintf(outStream, "%s:/%s", fsInfo->name, mountInfo->dirName); } static void uio_printMount(FILE *outStream, const uio_MountInfo *mountInfo) { uio_FileSystemInfo *fsInfo; fsInfo = uio_getFileSystemInfo(mountInfo->fsID); fprintf(outStream, "???:%s on ", mountInfo->dirName); uio_printPathToMountTree(outStream, mountInfo->mountTree); fprintf(outStream, " type %s (", fsInfo->name); if (mountInfo->flags & uio_MOUNT_RDONLY) { fprintf(outStream, "ro"); } else fprintf(outStream, "rw"); fprintf(outStream, ")\n"); } void uio_printMounts(FILE *outStream, const uio_Repository *repository) { int i; for (i = 0; i < repository->numMounts; i++) { uio_printMount(outStream, repository->mounts[i]); } } // *** uio_MountTree*** // static inline uio_MountTree * uio_MountTree_new(uio_MountTree *subTrees, uio_MountTreeItem *pLocs, uio_MountTree *upTree, uio_PathComp *comps, uio_PathComp *lastComp, uio_MountTree *next) { uio_MountTree *result; result = uio_MountTree_alloc(); result->subTrees = subTrees; result->pLocs = pLocs; result->upTree = upTree; result->comps = comps; result->lastComp = lastComp; result->next = next; return result; } void uio_MountTree_delete(uio_MountTree *tree) { uio_MountTree *subTree, *nextTree; uio_MountTreeItem *item, *nextItem; subTree = tree->subTrees; while (subTree != NULL) { nextTree = subTree->next; uio_MountTree_delete(subTree); subTree = nextTree; } item = tree->pLocs; while (item != NULL) { nextItem = item->next; uio_MountTreeItem_delete(item); item = nextItem; } if (tree->comps != NULL) uio_PathComp_delete(tree->comps); uio_MountTree_free(tree); } static inline uio_MountTree * uio_MountTree_alloc(void) { uio_MountTree *result = uio_malloc(sizeof (uio_MountTree)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_MountTree, (void *) result); #endif return result; } static inline void uio_MountTree_free(uio_MountTree *mountTree) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_MountTree, (void *) mountTree); #endif uio_free(mountTree); } // *** uio_MountTreeItem *** // static inline uio_MountTreeItem * uio_MountTree_newItem(uio_MountInfo *mountInfo, int depth, uio_MountTreeItem *next) { uio_MountTreeItem *result; result = uio_MountTreeItem_alloc(); result->mountInfo = mountInfo; result->depth = depth; result->next = next; return result; } static inline void uio_MountTreeItem_delete(uio_MountTreeItem *item) { uio_MountTreeItem_free(item); } static inline uio_MountTreeItem * uio_MountTreeItem_alloc(void) { uio_MountTreeItem *result = uio_malloc(sizeof (uio_MountTreeItem)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_MountTreeItem, (void *) result); #endif return result; } static inline void uio_MountTreeItem_free(uio_MountTreeItem *mountTreeItem) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_MountTreeItem, (void *) mountTreeItem); #endif uio_free(mountTreeItem); } // *** uio_MountInfo *** // uio_MountInfo * uio_MountInfo_new(uio_FileSystemID fsID, uio_MountTree *mountTree, uio_PDirHandle *pDirHandle, char *dirName, uio_AutoMount **autoMount, uio_MountHandle *mountHandle, int flags) { uio_MountInfo *result; result = uio_MountInfo_alloc(); result->fsID = fsID; result->mountTree = mountTree; result->pDirHandle = pDirHandle; result->dirName = dirName; result->autoMount = autoMount; result->mountHandle = mountHandle; result->flags = flags; return result; } void uio_MountInfo_delete(uio_MountInfo *mountInfo) { uio_free(mountInfo->dirName); uio_PDirHandle_unref(mountInfo->pDirHandle); uio_MountInfo_free(mountInfo); } static inline uio_MountInfo * uio_MountInfo_alloc(void) { uio_MountInfo *result = uio_malloc(sizeof (uio_MountInfo)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_MountInfo, (void *) result); #endif return result; } static inline void uio_MountInfo_free(uio_MountInfo *mountInfo) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_MountInfo, (void *) mountInfo); #endif uio_free(mountInfo); } uqm-0.6.2/sc2/src/sc2code/libs/uio/fileblock.h0000600000175000017500000000307110543202051017430 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _FILEBLOCK_H #define _FILEBLOCK_H #include "io.h" #include "uioport.h" #include typedef struct uio_FileBlock { uio_Handle *handle; int flags; #define uio_FB_USE_MMAP 1 off_t offset; // Offset to the start of the block in the file. size_t blockSize; char *buffer; // either allocated buffer, or buffer to mmap'ed area. size_t bufSize; } uio_FileBlock; uio_FileBlock *uio_openFileBlock(uio_Handle *handle); uio_FileBlock *uio_openFileBlock2(uio_Handle *handle, off_t offset, size_t size); ssize_t uio_accessFileBlock(uio_FileBlock *block, off_t offset, size_t length, char **buffer); int uio_copyFileBlock(uio_FileBlock *block, off_t offset, char *buffer, size_t length); int uio_closeFileBlock(uio_FileBlock *block); #endif /* _FILEBLOCK_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/hashtable.h0000600000175000017500000001173510543202051017437 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ // The 'already included' check must be done slightly more complicated // than usually. This file may be included directly only once, // but it may be included my derivative HashTable definitions that use // this file as a template more than once. #if !defined(_HASHTABLE_H) || defined(HASHTABLE_GENERIC) #if defined(HASHTABLE_) # define HASHTABLE_GENERIC #endif #include "types.h" #include "uioport.h" // Define to enable profiling. #define HashTable_PROFILE // You can use inline hash functions for extra speed, by using this file as // a template. // To do this, make a new .h and .c file. In the .h file, define the macros // (and typedefs) from the HASHTABLE_ block below. // In the .c file, #define HASHTABLE_INTERNAL, #include the .h file // and hashtable.c (in this order), and add the necessary functions. #ifndef HASHTABLE_ # define HASHTABLE_(identifier) HashTable ## _ ## identifier typedef void HashTable_Key; typedef void HashTable_Value; # define HashTable_HASH(hashTable, hashValue) \ (hashTable)->hashFunction(hashValue) # define HashTable_EQUAL(hashTable, hashKey1, hashKey2) \ (hashTable)->equalFunction(hashKey1, hashKey2) # define HashTable_COPY(hashTable, hashKey) \ (hashTable)->copyFunction(hashKey) # define HashTable_FREE(hashTable, hashKey) \ (hashTable)->freeFunction(hashKey) #endif typedef uio_uint32 (*HASHTABLE_(HashFunction))(const HASHTABLE_(Key) *); typedef uio_bool (*HASHTABLE_(EqualFunction))(const HASHTABLE_(Key) *, const HASHTABLE_(Key) *); typedef HASHTABLE_(Value) *(*HASHTABLE_(CopyFunction))( const HASHTABLE_(Value) *); typedef void (*HASHTABLE_(FreeFunction))(HASHTABLE_(Value) *); typedef struct HASHTABLE_(HashTable) HASHTABLE_(HashTable); typedef struct HASHTABLE_(HashEntry) HASHTABLE_(HashEntry); typedef struct HASHTABLE_(Iterator) HASHTABLE_(Iterator); struct HASHTABLE_(HashTable) { HASHTABLE_(HashFunction) hashFunction; HASHTABLE_(EqualFunction) equalFunction; HASHTABLE_(CopyFunction) copyFunction; HASHTABLE_(FreeFunction) freeFunction; double minFillQuotient; // How much of half of the hashtable needs to be filled // before resizing to size/2. double maxFillQuotient; // How much of the hashTable needs to be filled before // resizing to size*2. uio_uint32 minSize; // Resize to size/2 when below this size. uio_uint32 maxSize; // Resize to size*2 when above this size. uio_uint32 size; // The number of buckets in the hash table. uio_uint32 hashMask; // Mask to take on a the calculated hash value, to make it // fit into the table. HASHTABLE_(HashEntry) **entries; // The actual entries uio_uint32 numEntries; #ifdef HashTable_PROFILE uio_uint32 numCollisions; #endif }; struct HASHTABLE_(HashEntry) { uio_uint32 hash; HASHTABLE_(Key) *key; HASHTABLE_(Value) *value; HASHTABLE_(HashEntry) *next; }; struct HASHTABLE_(Iterator) { const HASHTABLE_(HashTable) *hashTable; uio_uint32 bucketNr; HASHTABLE_(HashEntry) *entry; }; HASHTABLE_(HashTable) *HASHTABLE_(newHashTable)( HASHTABLE_(HashFunction) hashFunction, HASHTABLE_(EqualFunction) equalFunction, HASHTABLE_(CopyFunction) copyFunction, HASHTABLE_(FreeFunction) freeFunction, uio_uint32 initialSize, double minFillQuotient, double maxFillQuotient); uio_bool HASHTABLE_(add)(HASHTABLE_(HashTable) *hashTable, const HASHTABLE_(Key) *key, HASHTABLE_(Value) *value); uio_bool HASHTABLE_(remove)(HASHTABLE_(HashTable) *hashTable, const HASHTABLE_(Key) *key); HASHTABLE_(Value) *HASHTABLE_(find)( HASHTABLE_(HashTable) *hashTable, const HASHTABLE_(Key) *key); uio_uint32 HASHTABLE_(count)(const HASHTABLE_(HashTable) *hashTable); void HASHTABLE_(deleteHashTable)(HASHTABLE_(HashTable) *hashTable); HASHTABLE_(Iterator) *HASHTABLE_(getIterator)( const HASHTABLE_(HashTable) *hashTable); int HASHTABLE_(iteratorDone)(const HASHTABLE_(Iterator) *iterator); HASHTABLE_(Key) *HASHTABLE_(iteratorKey)(HASHTABLE_(Iterator) *iterator); HASHTABLE_(Value) *HASHTABLE_(iteratorValue)(HASHTABLE_(Iterator) *iterator); HASHTABLE_(Iterator) *HASHTABLE_(iteratorNext)(HASHTABLE_(Iterator) *iterator); void HASHTABLE_(freeIterator)(HASHTABLE_(Iterator) *iterator); #ifndef HASHTABLE_INTERNAL # undef HASHTABLE_ #endif #endif /* !defined(_HASHTABLE_H) || defined(HASHTABLE_GENERIC) */ uqm-0.6.2/sc2/src/sc2code/libs/uio/fileblock.c0000644000175000017500000001124710546776502017463 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "iointrn.h" #include "fileblock.h" #include "uioport.h" #include static uio_FileBlock *uio_FileBlock_new(uio_Handle *handle, int flags, off_t offset, size_t blockSize, char *buffer, size_t bufSize); static inline uio_FileBlock *uio_FileBlock_alloc(void); static void uio_FileBlock_free(uio_FileBlock *block); uio_FileBlock * uio_openFileBlock(uio_Handle *handle) { // TODO: if mmap support is available, and it is available natively // for the filesystem (make some sort of sysctl for filesystems // to check this?), use mmap. // mmap the entire file if it's small enough. // N.B. Keep in mind streams of which the size is not known in // advance. struct stat statBuf; if (uio_fstat(handle, &statBuf) == -1) { // errno is set return NULL; } uio_Handle_ref(handle); return uio_FileBlock_new(handle, 0, 0, statBuf.st_size, NULL, 0); } uio_FileBlock * uio_openFileBlock2(uio_Handle *handle, off_t offset, size_t size) { // TODO: mmap (see uio_openFileBlock) // TODO: check if offset and size are acceptable. // Need to handle streams of which the size is unknown. #if 0 if (uio_stat(handle, &statBuf) == -1) { // errno is set return NULL; } if (statBuf.st_size > #endif uio_Handle_ref(handle); return uio_FileBlock_new(handle, 0, offset, size, NULL, 0); } // block remains usable until the next call to uio_accessFileBlock // with the same block as argument, or until uio_closeFileBlock with // that block as argument. ssize_t uio_accessFileBlock(uio_FileBlock *block, off_t offset, size_t length, char **buffer) { if (block->flags & uio_FB_USE_MMAP) { // TODO errno = ENOSYS; return -1; } else { // TODO: add read-ahead buffering ssize_t numRead; if (length > block->blockSize - offset) length = block->blockSize - offset; if (block->buffer != NULL && length != block->bufSize) { uio_free(block->buffer); block->buffer = NULL; } if (block->buffer == NULL) block->buffer = uio_malloc(length); // TODO: lock handle if (uio_lseek(block->handle, block->offset + offset, SEEK_SET) == (off_t) -1) { // errno is set return -1; } numRead = uio_read(block->handle, block->buffer, length); if (numRead == -1) { // errno is set // TODO: unlock handle return -1; } // TODO: unlock handle *buffer = block->buffer; return numRead; } } int uio_copyFileBlock(uio_FileBlock *block, off_t offset, char *buffer, size_t length) { if (block->flags & uio_FB_USE_MMAP) { // TODO errno = ENOSYS; return -1; } else { ssize_t numRead; if (length > block->blockSize - offset) length = block->blockSize - offset; // TODO: lock handle if (uio_lseek(block->handle, block->offset + offset, SEEK_SET) == (off_t) -1) { // errno is set return -1; } numRead = uio_read(block->handle, buffer, length); if (numRead == -1) { // errno is set // TODO: unlock handle return -1; } // TODO: unlock handle return numRead; } } int uio_closeFileBlock(uio_FileBlock *block) { if (block->flags & uio_FB_USE_MMAP) { #if 0 if (block->buffer != NULL) uio_mmunmap(block->buffer); #endif } else { if (block->buffer != NULL) uio_free(block->buffer); } uio_Handle_unref(block->handle); uio_FileBlock_free(block); return 0; } // caller should uio_Handle_ref(handle) (unless it doesn't need it's own // reference anymore). static uio_FileBlock * uio_FileBlock_new(uio_Handle *handle, int flags, off_t offset, size_t blockSize, char *buffer, size_t bufSize) { uio_FileBlock *result; result = uio_FileBlock_alloc(); result->handle = handle; result->flags = flags; result->offset = offset; result->blockSize = blockSize; result->buffer = buffer; result->bufSize = bufSize; return result; } static inline uio_FileBlock * uio_FileBlock_alloc(void) { return uio_malloc(sizeof (uio_FileBlock)); } static void uio_FileBlock_free(uio_FileBlock *block) { uio_free(block); } uqm-0.6.2/sc2/src/sc2code/libs/uio/mount.c0000644000175000017500000001063310546776502016671 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include "iointrn.h" #include "uioport.h" #include "mount.h" #include "mounttree.h" #include "mem.h" #include "uioutils.h" #ifdef uio_MEM_DEBUG # include "memdebug.h" #endif static void uio_Repository_delete(uio_Repository *repository); static uio_Repository *uio_Repository_alloc(void); static void uio_Repository_free(uio_Repository *repository); void uio_repositoryAddMount(uio_Repository *repository, uio_MountInfo *mountInfo, uio_MountLocation location, uio_MountInfo *relative) { lockRepository(repository, uio_LOCK_WRITE); switch (location) { case uio_MOUNT_TOP: { uio_MountInfo **newMounts; newMounts = uio_malloc( (repository->numMounts + 2) * sizeof (uio_MountInfo *)); newMounts[0] = mountInfo; memcpy(&newMounts[1], repository->mounts, (repository->numMounts + 1) * sizeof (uio_MountInfo *)); uio_free(repository->mounts); repository->mounts = newMounts; repository->numMounts++; break; } case uio_MOUNT_BOTTOM: repository->mounts = uio_realloc(repository->mounts, (repository->numMounts + 2) * sizeof (uio_MountInfo *)); repository->mounts[repository->numMounts] = mountInfo; repository->numMounts++; break; case uio_MOUNT_BELOW: { int i; uio_MountInfo **newMounts; i = 0; while (repository->mounts[i] != relative) i++; newMounts = (uio_MountInfo **) insertArrayPointer( (const void **) repository->mounts, repository->numMounts + 1, i, (void *) mountInfo); uio_free(repository->mounts); repository->mounts = newMounts; repository->numMounts++; break; } case uio_MOUNT_ABOVE: { int i; uio_MountInfo **newMounts; i = 0; while (repository->mounts[i] != relative) i++; i++; newMounts = (uio_MountInfo **) insertArrayPointer( (const void **) repository->mounts, repository->numMounts + 1, i, (void *) mountInfo); uio_free(repository->mounts); repository->mounts = newMounts; repository->numMounts++; break; } default: assert(false); } unlockRepository(repository); } void uio_repositoryRemoveMount(uio_Repository *repository, uio_MountInfo *mountInfo) { int i; uio_MountInfo **newMounts; lockRepository(repository, uio_LOCK_WRITE); i = 0; while (repository->mounts[i] != mountInfo) i++; newMounts = (uio_MountInfo **) excludeArrayPointer( (const void **) repository->mounts, repository->numMounts + 1, i, 1); uio_free(repository->mounts); repository->mounts = newMounts; repository->numMounts--; unlockRepository(repository); } // sets ref to 1 uio_Repository * uio_Repository_new(int flags) { uio_Repository *result; result = uio_Repository_alloc(); result->ref = 1; result->flags = flags; result->numMounts = 0; result->mounts = uio_malloc(1 * sizeof (uio_MountInfo *)); result->mounts[0] = NULL; result->mountTree = uio_makeRootMountTree(); return result; } void uio_Repository_unref(uio_Repository *repository) { assert(repository->ref > 0); repository->ref--; if (repository->ref == 0) uio_Repository_delete(repository); } static uio_Repository * uio_Repository_alloc(void) { uio_Repository *result = uio_malloc(sizeof (uio_Repository)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_Repository, (void *) result); #endif return result; } static void uio_Repository_delete(uio_Repository *repository) { assert(repository->numMounts == 0); uio_free(repository->mounts); uio_MountTree_delete(repository->mountTree); uio_Repository_free(repository); } static void uio_Repository_free(uio_Repository *repository) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_Repository, (void *) repository); #endif uio_free(repository); } uqm-0.6.2/sc2/src/sc2code/libs/uio/match.h0000600000175000017500000001110010543202051016562 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _MATCH_H #define _MATCH_H typedef struct match_MatchContext match_MatchContext; #include // TODO: make this into a configurable option //#define HAVE_GLOB #define HAVE_REGEX typedef enum { match_MATCH_LITTERAL = 0, match_MATCH_PREFIX, match_MATCH_SUFFIX, match_MATCH_SUBSTRING, #ifdef HAVE_GLOB match_MATCH_GLOB, #endif #ifdef HAVE_REGEX match_MATCH_REGEX, #endif } match_MatchType; typedef int match_Result; #define match_NOMATCH 0 #define match_MATCH 1 #define match_OK 0 #define match_EUNKNOWN -1 #define match_ENOSYS -2 #define match_ECUSTOM -3 #define match_ENOTINIT -4 typedef struct match_LitteralContext match_LitteralContext; typedef struct match_PrefixContext match_PrefixContext; typedef struct match_SuffixContext match_SuffixContext; typedef struct match_SubStringContext match_SubStringContext; #ifdef HAVE_GLOB typedef struct match_GlobContext match_GlobContext; #endif #ifdef HAVE_REGEX typedef struct match_RegexContext match_RegexContext; #endif match_Result match_prepareContext(const char *pattern, match_MatchContext **contextPtr, match_MatchType type); match_Result match_matchPattern(match_MatchContext *context, const char *string); const char *match_errorString(match_MatchContext *context, match_Result result); void match_freeContext(match_MatchContext *context); /* *** Internal definitions follow *** */ #ifdef match_INTERNAL #include #ifdef HAVE_REGEX # include #endif #include "uioport.h" struct match_MatchContext { match_MatchType type; union { match_LitteralContext *litteral; match_PrefixContext *prefix; match_SuffixContext *suffix; match_SubStringContext *subString; #ifdef HAVE_GLOB match_GlobContext *glob; #endif #ifdef HAVE_REGEX match_RegexContext *regex; #endif } u; }; struct match_LitteralContext { char *pattern; }; struct match_PrefixContext { char *pattern; }; struct match_SuffixContext { char *pattern; size_t len; // for speed }; struct match_SubStringContext { char *pattern; }; #ifdef HAVE_GLOB struct match_GlobContext { char *pattern; }; #endif #ifdef HAVE_REGEX struct match_RegexContext { regex_t native; char *errorString; int errorCode; int flags; #define match_REGEX_INITIALISED 1 }; #endif match_Result match_prepareLitteral(const char *pattern, match_LitteralContext **contextPtr); match_Result match_matchLitteral(match_LitteralContext *context, const char *string); void match_freeLitteral(match_LitteralContext *context); match_Result match_preparePrefix(const char *pattern, match_PrefixContext **contextPtr); match_Result match_matchPrefix(match_PrefixContext *context, const char *string); void match_freePrefix(match_PrefixContext *context); match_Result match_prepareSuffix(const char *pattern, match_SuffixContext **contextPtr); match_Result match_matchSuffix(match_SuffixContext *context, const char *string); void match_freeSuffix(match_SuffixContext *context); match_Result match_prepareSubString(const char *pattern, match_SubStringContext **contextPtr); match_Result match_matchSubString(match_SubStringContext *context, const char *string); void match_freeSubString(match_SubStringContext *context); #ifdef HAVE_GLOB match_Result match_prepareGlob(const char *pattern, match_GlobContext **contextPtr); match_Result match_matchGlob(match_GlobContext *context, const char *string); void match_freeGlob(match_GlobContext *context); #endif /* HAVE_GLOB */ #ifdef HAVE_REGEX match_Result match_prepareRegex(const char *pattern, match_RegexContext **contextPtr); match_Result match_matchRegex(match_RegexContext *context, const char *string); const char *match_errorStringRegex(match_RegexContext *context, int errorCode); void match_freeRegex(match_RegexContext *context); #endif #endif /* match_INTERNAL */ #endif /* _MATCH_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/COPYING0000600000175000017500000004362710543202051016373 0ustar joeyjoeyBelow the text of the GNU General Public License is quoted verbatim. It applies to all files in and below this directory that say so. Note that most of these files will say only version 2 of the GNU General Public License applies, not any later version. --------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. uqm-0.6.2/sc2/src/sc2code/libs/uio/mounttree.h0000644000175000017500000001456010546776502017561 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _MOUNTTREE_H #define _MOUNTTREE_H #include #include "mount.h" void uio_printMounts(FILE *outStream, const uio_Repository *repository); /* *** Internal definitions follow *** */ #ifdef uio_INTERNAL #include typedef struct uio_MountTreeItem uio_MountTreeItem; typedef struct uio_MountTree uio_MountTree; typedef struct uio_MountInfo uio_MountInfo; #include "physical.h" #include "types.h" #include "uioport.h" #include "paths.h" /* * A MountTree describes the relation between dirs (PRoot structures) * mounted in a directory structure. * A MountTree structure represents a node (a dir) in this directory * structure. * It describes what MountInfo structures apply in that dir and below (if * not overrided in subnodes) (the 'pLocs' field). * These path components are also linked together 'up'-wards (towards the * root of the tree) by the 'up' field. */ struct uio_MountTreeItem { struct uio_MountInfo *mountInfo; int depth; // 'mountInfo->pDirHandle' and 'depth' together point to a // location in a physical tree. An uio_pDirHandle alone can't be // used as the directory might not exist. // So pDirHandle points to the top dir that was mounted, and // 'depth' indicates how many directory names of the path to // this point in the Mount Tree need to be followed. // Example: // This MountTreeItem is somewhere in a tree /foo/bar/bla // and depth = 1. Then this MountTreeItem points to // /bla in the specified root. struct uio_MountTreeItem *next; // The next MountTreeItem in a MountTree }; struct uio_MountTree { struct uio_MountTree *subTrees; // Trees for subdirs in this MountTree struct uio_MountTreeItem *pLocs; // The physical locations that have effect in this MountTree. struct uio_MountTree *upTree; // the MountTree that pointed to this MountTree struct uio_PathComp *comps; // the names of the path components that lead to the tree. // Not necessary every PathComp is connected to a MountTree. // If you have /foo and /foo/bar/zut mounted, then // there are MountTrees for /, /foo and /foo/bar/zut, // but there are PathComps for 'foo', 'bar' and 'zut'. struct uio_PathComp *lastComp; // The last PathComp of comps that pointed to this MountTree. // This can be used to trace the path back to the top. struct uio_MountTree *next; // If this tree is a subTree of a tree, 'next' points to the // next subTree of that tree. }; /* * A MountInfo structure describes how a physical structure was mounted. * A physical structure can be used by several MountInfo structures. */ struct uio_MountInfo { int flags; /* Mount flags */ # define uio_MOUNTINFO_RDONLY uio_MOUNT_RDONLY uio_FileSystemID fsID; char *dirName; /* The path inside the mounted fs leading to pDirHandle */ uio_PDirHandle *pDirHandle; /* The pDirHandle belonging to this mount type */ uio_MountTree *mountTree; /* The MountTree node for the mountpoint */ uio_AutoMount **autoMount; uio_MountHandle *mountHandle; }; /* * Say we've got mounted (in order): * Bla -> / * Bar -> /foo/bar * Foo -> /foo * Zut -> /zut/123 * Fop -> /zut/123 * * This will build a tree that looks like this: * (the strings between brackets are the mounted filesystems that have effect * in a dir, in order) * * / (Bar) * foo (Foo, Bla) * bar (Foo, Bar, Bla) * zut/123 (Fop, Zut, Bla) * * The MountTree will look like: * / = { * sub = { * /foo, * /zut/123 * }, * pLocs = { * BlaDir:/ (0) * } * } * /foo = { * sub = { * /foo/bar * }, * pLocs = { * BlaDir:/foo (1), * FooDir:/ (0) * } * } * /foo/bar = { * sub = { }, * pLocs = { * BlaDir:/foo/bar (2), * BarDir:/ (0), * FooDir:/bar (1) * } * } * /zut/123 = { * sub = { }, * pLocs = { * FooDir:/ (0) * ZutDir:/ (0) * BlaDir:/zut/123 (2) * } * } * * 'BlaDir:/zut/123 (2)' means the pDirHandle is 'Bla', and the dir into * that directory is '/zut/123', but as this is always a postfix of the * path where we are, the number of dirs (the '(2)') is enough to store * (apart from the pDirHandle). */ uio_MountTree *uio_makeRootMountTree(void); void uio_MountTree_delete(uio_MountTree *tree); uio_MountTree *uio_mountTreeAddMountInfo(uio_Repository *repository, uio_MountTree *mountTree, uio_MountInfo *mountInfo, const char *path, uio_MountLocation location, const uio_MountInfo *relative); void uio_mountTreeRemoveMountInfo(uio_Repository *repository, uio_MountTree *mountTree, uio_MountInfo *mountInfo); void uio_findMountTree(uio_MountTree *top, const char *path, uio_MountTree **resTree, const char **pPath); char *uio_mountTreeItemRestPath(const uio_MountTreeItem *item, uio_PathComp *endComp, const char *path); int uio_mountTreeCountPLocs(const uio_MountTree *tree); uio_MountInfo *uio_MountInfo_new(uio_FileSystemID fsID, uio_MountTree *mountTree, uio_PDirHandle *pDirHandle, char *dirName, uio_AutoMount **autoMount, uio_MountHandle *mountHandle, int flags); void uio_MountInfo_delete(uio_MountInfo *mountInfo); void uio_printMountTree(FILE *outStream, const uio_MountTree *tree, int indent); void uio_printMountTreeItem(FILE *outStream, const uio_MountTreeItem *item); void uio_printMountTreeItems(FILE *outStream, const uio_MountTreeItem *item); void uio_printPathToMountTree(FILE *outStream, const uio_MountTree *tree); void uio_printMountInfo(FILE *outStream, const uio_MountInfo *mountInfo); static inline uio_bool uio_mountInfoIsReadOnly(uio_MountInfo *mountInfo) { return (mountInfo->flags & uio_MOUNTINFO_RDONLY) != 0; } #endif /* uio_INTERNAL */ #endif /* _MOUNTTREE_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/defaultfs.h0000600000175000017500000000232110543202051017450 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef uio_DEFAULTFS_H #define uio_DEFAULTFS_H typedef struct uio_DefaultFileSystemSetup uio_DefaultFileSystemSetup; #include "iointrn.h" #include "uioport.h" #include "fstypes.h" struct uio_DefaultFileSystemSetup { uio_FileSystemID id; const char *name; uio_FileSystemHandler *handler; }; extern const uio_DefaultFileSystemSetup defaultFileSystems[]; int uio_numDefaultFileSystems(void); #endif /* uio_DEFAULTFS_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/Makeinfo0000600000175000017500000000065410543202051017005 0ustar joeyjoeyuqm_SUBDIRS="stdio" uqm_CFILES="charhashtable.c defaultfs.c fileblock.c fstypes.c gphys.c io.c ioaux.c match.c mount.c mounttree.c paths.c physical.c uiostream.c uioutils.c utils.c" if [ -n "$uqm_USE_ZIP_IO" ]; then uqm_SUBDIRS="$uqm_SUBDIRS zip" fi #if [ -n "$DEBUG" -o -n "$uqm_UIO_DEBUG" ]; then uqm_CFILES="$uqm_CFILES debug.c" #fi if [ -n "$MEMDEBUG" ]; then uqm_CFILES="$uqm_CFILES hashtable.c memdebug.c" fi uqm-0.6.2/sc2/src/sc2code/libs/uio/mem.h0000644000175000017500000000313610546776502016312 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _MEM_H #define _MEM_H #include #include #include "uioport.h" #define uio_malloc malloc #define uio_realloc realloc #define uio_free free #define uio_calloc calloc #define uio_alloca alloca #ifdef uio_MEM_DEBUG // When uio_strdup is defined to the libc strdup, there's no opportunity // to intercept the alloc. Hence this function here. static inline char * uio_strdup(const char *s) { char *result; size_t size; size = strlen(s) + 1; result = uio_malloc(size); memcpy(result, s, size); return result; } #else # define uio_strdup strdup #endif // Allocates new memory, copies 'len' characters from 'src', and adds a '\0'. static inline char * uio_memdup0(const char *src, size_t len) { char *dst = uio_malloc(len + 1); memcpy(dst, src, len); dst[len] = '\0'; return dst; } #endif uqm-0.6.2/sc2/src/sc2code/libs/uio/mount.h0000644000175000017500000000347310545750177016701 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _MOUNT_H #define _MOUNT_H typedef struct uio_Repository uio_Repository; typedef struct uio_AutoMount uio_AutoMount; #define uio_MOUNT_RDONLY (1 << 1) /* *** Internal definitions follow */ #ifdef uio_INTERNAL #define uio_MOUNT_LOCATION_MASK (3 << 2) #include "uioport.h" #include "fstypes.h" #include "mounttree.h" #include "match.h" struct uio_Repository { int ref; /* reference counter */ int flags; int numMounts; struct uio_MountInfo **mounts; // first in the list is considered the top // last entry is NULL struct uio_MountTree *mountTree; }; #define lockRepository(repository, prot) #define unlockRepository(repository) uio_Repository *uio_Repository_new(int flags); void uio_Repository_unref(uio_Repository *repository); void uio_repositoryAddMount(uio_Repository *repository, uio_MountInfo *mountInfo, uio_MountLocation location, uio_MountInfo *relative); void uio_repositoryRemoveMount(uio_Repository *repository, uio_MountInfo *mountInfo); #endif /* uio_INTERNAL */ #endif /* _MOUNT_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/io.c0000644000175000017500000012445010546776502016141 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include "iointrn.h" #include "ioaux.h" #include "mount.h" #include "fstypes.h" #include "mounttree.h" #include "physical.h" #include "paths.h" #include "mem.h" #include "uioutils.h" #include "uioport.h" #ifdef uio_MEM_DEBUG # include "memdebug.h" #endif static int uio_statDir(uio_DirHandle *dirHandle, const char *path, struct stat *statBuf); static int uio_statOneDir(uio_PDirHandle *pDirHandle, struct stat *statBuf); static void uio_PDirHandles_delete(uio_PDirHandle *pDirHandles[], int numPDirHandles); static inline uio_PDirHandle *uio_PDirHandle_alloc(void); static inline void uio_PDirHandle_free(uio_PDirHandle *pDirHandle); static inline uio_PFileHandle *uio_PFileHandle_alloc(void); static inline void uio_PFileHandle_free(uio_PFileHandle *pFileHandle); static uio_DirHandle *uio_DirHandle_new(uio_Repository *repository, char *path, char *rootEnd); static inline uio_DirHandle *uio_DirHandle_alloc(void); static inline void uio_DirHandle_free(uio_DirHandle *dirHandle); static inline uio_Handle *uio_Handle_alloc(void); static inline void uio_Handle_free(uio_Handle *handle); static uio_MountHandle *uio_MountHandle_new(uio_Repository *repository, uio_MountInfo *mountInfo); static inline void uio_MountHandle_delete(uio_MountHandle *mountHandle); static inline uio_MountHandle *uio_MountHandle_alloc(void); static inline void uio_MountHandle_free(uio_MountHandle *mountHandle); void uio_init(void) { #ifdef uio_MEM_DEBUG uio_MemDebug_init(); #endif uio_registerDefaultFileSystems(); } void uio_unInit(void) { uio_unRegisterDefaultFileSystems(); #ifdef uio_MEM_DEBUG # ifdef DEBUG uio_MemDebug_printPointers(stderr); fflush(stderr); # endif uio_MemDebug_unInit(); #endif } uio_Repository * uio_openRepository(int flags) { return uio_Repository_new(flags); } void uio_closeRepository(uio_Repository *repository) { uio_unmountAllDirs(repository); uio_Repository_unref(repository); } /* * Function name: uio_mountDir * Description: Grafts a directory from inside a physical fileSystem * into the locical filesystem, at a specified directory. * Arguments: destRep - the repository where the newly mounted dir * is to be grafted. * mountPoint - the path to the directory where the dir * is to be grafted. * fsType - the file system type of physical fileSystem * pointed to by sourcePath. * sourceDir - the directory to which 'sourcePath' is to * be taken relative. * sourcePath - a path relative to sourceDir, which contains * the file/directory to be mounted. * If sourceDir and sourcePath are NULL, the file * system of the operating system will be used. * inPath - the location relative to the root of the newly * mounted fileSystem, pointing to the directory * that is to be grafted. * Note: If fsType is uio_FSTYPE_STDIO, inPath is * relative to the root of the filesystem, NOT to * the current working dir. * autoMount - array of automount options in function * in this mountPoint. * flags - one of uio_MOUNT_TOP, uio_MOUNT_BOTTOM, * uio_MOUNT_BELOW, uio_MOUNT_ABOVE, specifying * the precedence of this mount, OR'ed with * one or more of the following flags: * uio_MOUNT_RDONLY (no writing is allowed) * relative - If 'flags' includes uio_MOUNT_BELOW or * uio_MOUNT_ABOVE, this is the mount handle * where the new mount is relative to. * Otherwise, it should be NULL. * Returns: a handle suitable for uio_unmountDir() * NULL if an error occured. In this case 'errno' is set. */ uio_MountHandle * uio_mountDir(uio_Repository *destRep, const char *mountPoint, uio_FileSystemID fsType, uio_DirHandle *sourceDir, const char *sourcePath, const char *inPath, uio_AutoMount **autoMount, int flags, uio_MountHandle *relative) { uio_PRoot *pRoot; uio_Handle *handle; uio_FileSystemHandler *handler; uio_MountInfo *relativeInfo; switch (flags & uio_MOUNT_LOCATION_MASK) { case uio_MOUNT_TOP: case uio_MOUNT_BOTTOM: if (relative != NULL) { errno = EINVAL; return NULL; } relativeInfo = NULL; break; case uio_MOUNT_BELOW: case uio_MOUNT_ABOVE: if (relative == NULL) { errno = EINVAL; return NULL; } relativeInfo = relative->mountInfo; break; default: abort(); } if (mountPoint[0] == '/') mountPoint++; if (!validPathName(mountPoint, strlen(mountPoint))) { errno = EINVAL; return NULL; } // TODO: check if the filesystem is already mounted, and if so, reuse it. // A RO filedescriptor will need to be replaced though if the // filesystem needs to be remounted RW now. if (sourceDir == NULL) { if (sourcePath != NULL) { // bad: sourceDir is NULL, but sourcePath isn't errno = EINVAL; return NULL; } handle = NULL; } else { if (sourcePath == NULL) { // bad: sourcePath is NULL, but sourceDir isn't errno = EINVAL; return NULL; } handle = uio_open(sourceDir, sourcePath, ((flags & uio_MOUNT_RDONLY) == uio_MOUNT_RDONLY ? O_RDONLY : O_RDWR) #ifdef WIN32 | O_BINARY #endif , 0); if (handle == NULL) { // errno is set return NULL; } } handler = uio_getFileSystemHandler(fsType); if (handler == NULL) { if (handle) uio_close(handle); errno = ENODEV; return NULL; } assert(handler->mount != NULL); pRoot = (handler->mount)(handle, flags); if (pRoot == NULL) { int savedErrno; savedErrno = errno; if (handle) uio_close(handle); errno = savedErrno; return NULL; } if (handle) { // Close this reference to handle. // The physical layer may store the link in pRoot, in which it // will be cleaned up from uio_unmount(). uio_close(handle); } // The new file system is ready, now we need to find the specified // dir inside it and put it in its place in the mountTree. { uio_PDirHandle *endDirHandle; const char *endInPath; char *dirName; uio_MountInfo *mountInfo; uio_MountTree *mountTree; uio_PDirHandle *pRootHandle; #ifdef WIN32 char *unixPath; unixPath = dosToUnixPath(inPath); inPath = unixPath; #endif if (inPath[0] == '/') inPath++; pRootHandle = uio_PRoot_getRootDirHandle(pRoot); uio_walkPhysicalPath(pRootHandle, inPath, strlen(inPath), &endDirHandle, &endInPath); if (*endInPath != '\0') { // Path inside the filesystem to mount does not exist. #ifdef WIN32 uio_free(unixPath); #endif uio_PDirHandle_unref(endDirHandle); uio_PRoot_unrefMount(pRoot); if (handle) uio_close(handle); errno = ENOENT; return NULL; } dirName = uio_malloc(endInPath - inPath + 1); memcpy(dirName, inPath, endInPath - inPath); dirName[endInPath - inPath] = '\0'; #ifdef WIN32 // InPath is a copy with the paths fixed. uio_free(unixPath); #endif mountInfo = uio_MountInfo_new(fsType, NULL, endDirHandle, dirName, autoMount, NULL, flags); uio_repositoryAddMount(destRep, mountInfo, flags & uio_MOUNT_LOCATION_MASK, relativeInfo); mountTree = uio_mountTreeAddMountInfo(destRep, destRep->mountTree, mountInfo, mountPoint, flags & uio_MOUNT_LOCATION_MASK, relativeInfo); // mountTree is the node in destRep->mountTree where mountInfo // leads to. mountInfo->mountTree = mountTree; mountInfo->mountHandle = uio_MountHandle_new(destRep, mountInfo); return mountInfo->mountHandle; } } int uio_unmountDir(uio_MountHandle *mountHandle) { uio_PRoot *pRoot; pRoot = mountHandle->mountInfo->pDirHandle->pRoot; // check if it's in use #ifdef DEBUG if (pRoot->mountRef == 1 && pRoot->handleRef > 0) { fprintf(stderr, "Warning: File system to be unmounted still " "has file descriptors open. The file system will not " "be deallocated until these are all closed.\n"); } #endif // TODO: lock (and furtheron unlock) repository // remove from mount tree uio_mountTreeRemoveMountInfo(mountHandle->repository, mountHandle->mountInfo->mountTree, mountHandle->mountInfo); // remove from mount list. uio_repositoryRemoveMount(mountHandle->repository, mountHandle->mountInfo); uio_MountInfo_delete(mountHandle->mountInfo); uio_MountHandle_delete(mountHandle); uio_PRoot_unrefMount(pRoot); return 0; } int uio_unmountAllDirs(uio_Repository *repository) { int i; i = repository->numMounts; while (i--) uio_unmountDir(repository->mounts[i]->mountHandle); return 0; } uio_FileSystemID uio_getMountFileSystemType(uio_MountHandle *mountHandle) { return mountHandle->mountInfo->fsID; } int uio_close(uio_Handle *handle) { uio_Handle_unref(handle); return 0; } int uio_rename(uio_DirHandle *oldDir, const char *oldPath, uio_DirHandle *newDir, const char *newPath) { uio_PDirHandle *oldPReadDir, *newPReadDir, *newPWriteDir; uio_MountInfo *oldReadMountInfo, *newReadMountInfo, *newWriteMountInfo; char *oldName, *newName; int retVal; if (uio_getPhysicalAccess(oldDir, oldPath, O_RDONLY, 0, &oldReadMountInfo, &oldPReadDir, NULL, NULL, NULL, NULL, &oldName) == -1) { // errno is set return -1; } if (uio_getPhysicalAccess(newDir, newPath, O_WRONLY | O_CREAT | O_EXCL, uio_GPA_NOWRITE, &newReadMountInfo, &newPReadDir, NULL, &newWriteMountInfo, &newPWriteDir, NULL, &newName) == -1) { int savedErrno = errno; uio_PDirHandle_unref(oldPReadDir); uio_free(oldName); errno = savedErrno; return -1; } if (oldReadMountInfo != newWriteMountInfo) { uio_PDirHandle_unref(oldPReadDir); uio_PDirHandle_unref(newPReadDir); uio_PDirHandle_unref(newPWriteDir); uio_free(oldName); uio_free(newName); errno = EXDEV; return -1; } if (uio_mountInfoIsReadOnly(oldReadMountInfo)) { // XXX: Doesn't uio_getPhysicalAccess already handle this? // It doesn't return EROFS though; perhaps it should. uio_PDirHandle_unref(oldPReadDir); uio_PDirHandle_unref(newPReadDir); uio_PDirHandle_unref(newPWriteDir); uio_free(oldName); uio_free(newName); errno = EROFS; return -1; } if (oldReadMountInfo->pDirHandle->pRoot->handler->rename == NULL) { uio_PDirHandle_unref(oldPReadDir); uio_PDirHandle_unref(newPReadDir); uio_PDirHandle_unref(newPWriteDir); uio_free(oldName); uio_free(newName); errno = ENOSYS; return -1; } retVal = (oldReadMountInfo->pDirHandle->pRoot->handler->rename)( oldPReadDir, oldName, newPWriteDir, newName); if (retVal == -1) { int savedErrno = errno; uio_PDirHandle_unref(oldPReadDir); uio_PDirHandle_unref(newPReadDir); uio_PDirHandle_unref(newPWriteDir); uio_free(oldName); uio_free(newName); errno = savedErrno; return -1; } uio_PDirHandle_unref(oldPReadDir); uio_PDirHandle_unref(newPReadDir); uio_PDirHandle_unref(newPWriteDir); uio_free(oldName); uio_free(newName); return 0; } int uio_fstat(uio_Handle *handle, struct stat *statBuf) { if (handle->root->handler->fstat == NULL) { errno = ENOSYS; return -1; } return (handle->root->handler->fstat)(handle, statBuf); } int uio_stat(uio_DirHandle *dir, const char *path, struct stat *statBuf) { uio_PDirHandle *pReadDir; uio_MountInfo *readMountInfo; char *name; int result; if (uio_getPhysicalAccess(dir, path, O_RDONLY, 0, &readMountInfo, &pReadDir, NULL, NULL, NULL, NULL, &name) == -1) { if (uio_statDir(dir, path, statBuf) == -1) { // errno is set return -1; } return 0; } if (pReadDir->pRoot->handler->stat == NULL) { uio_PDirHandle_unref(pReadDir); uio_free(name); errno = ENOSYS; return -1; } result = (pReadDir->pRoot->handler->stat)(pReadDir, name, statBuf); uio_PDirHandle_unref(pReadDir); uio_free(name); return result; } // auxiliary function to uio_stat static int uio_statDir(uio_DirHandle *dirHandle, const char *path, struct stat *statBuf) { int numPDirHandles; uio_PDirHandle **pDirHandles; if (uio_getPathPhysicalDirs(dirHandle, path, strlen(path), &pDirHandles, &numPDirHandles, NULL) == -1) { // errno is set return -1; } if (numPDirHandles == 0) { errno = ENOENT; return -1; } if (uio_statOneDir(pDirHandles[0], statBuf) == -1) { int savedErrno = errno; uio_PDirHandles_delete(pDirHandles, numPDirHandles); errno = savedErrno; return -1; } // TODO: atm, fstat'ing a dir will show the info for the topmost // dir. Maybe it would make sense of merging the bits. (How?) #if 0 for (i = 1; i < numPDirHandles; i++) { struct stat statOne; uio_PDirHandle *pDirHandle; if (statOneDir(pDirHandles[i], &statOne) == -1) { // errno is set int savedErrno = errno; uio_PDirHandles_delete(pDirHandles, numPDirHandles); errno = savedErrno; return -1; } // Merge dirs: } #endif uio_PDirHandles_delete(pDirHandles, numPDirHandles); return 0; } static int uio_statOneDir(uio_PDirHandle *pDirHandle, struct stat *statBuf) { if (pDirHandle->pRoot->handler->stat == NULL) { errno = ENOSYS; return -1; } return (pDirHandle->pRoot->handler->stat)(pDirHandle, ".", statBuf); // sets errno on error } int uio_mkdir(uio_DirHandle *dir, const char *path, mode_t mode) { uio_PDirHandle *pReadDir, *pWriteDir; uio_MountInfo *readMountInfo, *writeMountInfo; char *name; uio_PDirHandle *newDirHandle; if (uio_getPhysicalAccess(dir, path, O_WRONLY | O_CREAT | O_EXCL, 0, &readMountInfo, &pReadDir, NULL, &writeMountInfo, &pWriteDir, NULL, &name) == -1) { // errno is set if (errno == EISDIR) errno = EEXIST; return -1; } uio_PDirHandle_unref(pReadDir); if (pWriteDir->pRoot->handler->mkdir == NULL) { uio_free(name); uio_PDirHandle_unref(pWriteDir); errno = ENOSYS; return -1; } newDirHandle = (pWriteDir->pRoot->handler->mkdir)(pWriteDir, name, mode); if (newDirHandle == NULL) { int savedErrno = errno; uio_free(name); uio_PDirHandle_unref(pWriteDir); errno = savedErrno; return -1; } uio_PDirHandle_unref(pWriteDir); uio_PDirHandle_unref(newDirHandle); uio_free(name); return 0; } uio_Handle * uio_open(uio_DirHandle *dir, const char *path, int flags, mode_t mode) { uio_PDirHandle *readPDirHandle, *writePDirHandle, *pDirHandle; uio_MountInfo *readMountInfo, *writeMountInfo; char *name; uio_Handle *handle; if (uio_getPhysicalAccess(dir, path, flags, 0, &readMountInfo, &readPDirHandle, NULL, &writeMountInfo, &writePDirHandle, NULL, &name) == -1) { // errno is set return NULL; } if ((flags & O_ACCMODE) == O_RDONLY) { // WritePDirHandle is not filled in. pDirHandle = readPDirHandle; } else if (readPDirHandle == writePDirHandle) { // In general, the dirs can be the same even when the handles are // not the same. But here it works, because uio_getPhysicalAccess // guarantees it. uio_PDirHandle_unref(writePDirHandle); pDirHandle = readPDirHandle; } else { // need to write uio_PDirEntryHandle *entry; entry = uio_getPDirEntryHandle(readPDirHandle, name); if (entry != NULL) { // file already exists uio_PDirEntryHandle_unref(entry); if ((flags & O_CREAT) == O_CREAT && (flags & O_EXCL) == O_EXCL) { uio_free(name); uio_PDirHandle_unref(readPDirHandle); uio_PDirHandle_unref(writePDirHandle); errno = EEXIST; return NULL; } if ((flags & O_TRUNC) == O_TRUNC) { // No use copying the file to the writable dir. // As it doesn't exists there, O_TRUNC needs to be turned off // though. flags &= ~O_TRUNC; } else { // file needs to be copied if (uio_copyFilePhysical(readPDirHandle, name, writePDirHandle, name) == -1) { int savedErrno = errno; uio_free(name); uio_PDirHandle_unref(readPDirHandle); uio_PDirHandle_unref(writePDirHandle); errno = savedErrno; return NULL; } } } else { // file does not exist if (((flags & O_ACCMODE) == O_RDONLY) || (flags & O_CREAT) != O_CREAT) { uio_free(name); uio_PDirHandle_unref(readPDirHandle); uio_PDirHandle_unref(writePDirHandle); errno = ENOENT; return NULL; } } uio_PDirHandle_unref(readPDirHandle); pDirHandle = writePDirHandle; } handle = (pDirHandle->pRoot->handler->open)(pDirHandle, name, flags, mode); // Also adds a new entry to the physical dir if appropriate. if (handle == NULL) { int savedErrno = errno; uio_free(name); uio_PDirHandle_unref(pDirHandle); errno = savedErrno; return NULL; } uio_free(name); uio_PDirHandle_unref(pDirHandle); return handle; } uio_DirHandle * uio_openDir(uio_Repository *repository, const char *path, int flags) { uio_DirHandle *dirHandle; const char * const rootStr = ""; dirHandle = uio_DirHandle_new(repository, unconst(rootStr), unconst(rootStr)); // dirHandle->path will be replaced before uio_openDir() // exits() if (uio_verifyPath(dirHandle, path, &dirHandle->path) == -1) { int savedErrno = errno; uio_DirHandle_free(dirHandle); errno = savedErrno; return NULL; } // dirHandle->path is no longer equal to 'path' at this point. // TODO: increase ref in repository? dirHandle->rootEnd = dirHandle->path; if (flags & uio_OD_ROOT) dirHandle->rootEnd += strlen(dirHandle->path); return dirHandle; } uio_DirHandle * uio_openDirRelative(uio_DirHandle *base, const char *path, int flags) { uio_DirHandle *dirHandle; char *newPath; if (uio_verifyPath(base, path, &newPath) == -1) { // errno is set return NULL; } if (flags & uio_OD_ROOT) { dirHandle = uio_DirHandle_new(base->repository, newPath, newPath + strlen(newPath)); // TODO: increase ref in base->repository? } else { // use the root of the base dir dirHandle = uio_DirHandle_new(base->repository, newPath, newPath + (base->rootEnd - base->path)); } return dirHandle; } int uio_closeDir(uio_DirHandle *dirHandle) { uio_DirHandle_unref(dirHandle); return 0; } ssize_t uio_read(uio_Handle *handle, void *buf, size_t count) { return (handle->root->handler->read)(handle, buf, count); } int uio_rmdir(uio_DirHandle *dirHandle, const char *path) { int numPDirHandles; uio_PDirHandle *pDirHandle, **pDirHandles; const char *pathEnd, *name; uio_PDirEntryHandle *entry; uio_MountTreeItem **items; int i; int numDeleted; pathEnd = strrchr(path, '/'); if (pathEnd == NULL) { pathEnd = path; name = path; } else name = pathEnd + 1; if (uio_getPathPhysicalDirs(dirHandle, path, pathEnd - path, &pDirHandles, &numPDirHandles, &items) == -1) { // errno is set return -1; } entry = NULL; // Should be set before a possible goto. if (name[0] == '\0') { // path was of the form "foo/bar/" or "/foo/bar/" // These are intentionally not accepted. // I see this as a path and not as a directory identifier. errno = ENOENT; goto err; } numDeleted = 0; for (i = 0; i < numPDirHandles; i++) { pDirHandle = pDirHandles[i]; entry = uio_getPDirEntryHandle(pDirHandle, name); if (entry == NULL) continue; if (!uio_PDirEntryHandle_isDir(entry)) { errno = ENOTDIR; goto err; } if (uio_mountInfoIsReadOnly(items[i]->mountInfo)) { errno = EROFS; goto err; } if (pDirHandle->pRoot->handler->rmdir == NULL) { errno = ENOSYS; goto err; } if ((pDirHandle->pRoot->handler->rmdir)(pDirHandle, name) == -1) { // errno is set goto err; } numDeleted++; uio_PDirEntryHandle_unref(entry); } entry = NULL; if (numDeleted == 0) { errno = ENOENT; goto err; } uio_PDirHandles_delete(pDirHandles, numPDirHandles); uio_free(items); return 0; err: { int savedErrno = errno; uio_PDirHandles_delete(pDirHandles, numPDirHandles); uio_free(items); if (entry != NULL) uio_PDirEntryHandle_unref(entry); errno = savedErrno; return -1; } } static void uio_PDirHandles_delete(uio_PDirHandle *pDirHandles[], int numPDirHandles) { while (numPDirHandles--) uio_PDirHandle_unref(pDirHandles[numPDirHandles]); uio_free(pDirHandles); } int uio_lseek(uio_Handle *handle, off_t offset, int whence) { if (handle->root->handler->seek == NULL) { errno = ENOSYS; return -1; } return (handle->root->handler->seek)(handle, offset, whence); } ssize_t uio_write(uio_Handle *handle, const void *buf, size_t count) { if (handle->root->handler->write == NULL) { errno = ENOSYS; return -1; } return (handle->root->handler->write)(handle, buf, count); } int uio_unlink(uio_DirHandle *dirHandle, const char *path) { int numPDirHandles; uio_PDirHandle *pDirHandle, **pDirHandles; const char *pathEnd, *name; uio_PDirEntryHandle *entry; uio_MountTreeItem **items; int i; int numDeleted; pathEnd = strrchr(path, '/'); if (pathEnd == NULL) { pathEnd = path; name = path; } else name = pathEnd + 1; if (uio_getPathPhysicalDirs(dirHandle, path, pathEnd - path, &pDirHandles, &numPDirHandles, &items) == -1) { // errno is set return -1; } entry = NULL; // Should be set before a possible goto. if (name[0] == '\0') { // path was of the form "foo/bar/" or "/foo/bar/" errno = ENOENT; goto err; } numDeleted = 0; for (i = 0; i < numPDirHandles; i++) { pDirHandle = pDirHandles[i]; entry = uio_getPDirEntryHandle(pDirHandle, name); if (entry == NULL) continue; if (uio_PDirEntryHandle_isDir(entry)) { errno = EISDIR; goto err; } if (uio_mountInfoIsReadOnly(items[i]->mountInfo)) { errno = EROFS; goto err; } if (pDirHandle->pRoot->handler->unlink == NULL) { errno = ENOSYS; goto err; } if ((pDirHandle->pRoot->handler->unlink)(pDirHandle, name) == -1) { // errno is set goto err; } numDeleted++; uio_PDirEntryHandle_unref(entry); } entry = NULL; if (numDeleted == 0) { errno = ENOENT; goto err; } uio_PDirHandles_delete(pDirHandles, numPDirHandles); uio_free(items); return 0; err: { int savedErrno = errno; uio_PDirHandles_delete(pDirHandles, numPDirHandles); uio_free(items); if (entry != NULL) uio_PDirEntryHandle_unref(entry); errno = savedErrno; return -1; } } // inPath and *outPath may point to the same location int uio_getFileLocation(uio_DirHandle *dir, const char *inPath, int flags, uio_MountHandle **mountHandle, char **outPath) { uio_PDirHandle *readPDirHandle, *writePDirHandle; uio_MountInfo *readMountInfo, *writeMountInfo, *mountInfo; char *name; char *readPRootPath, *writePRootPath, *pRootPath; if (uio_getPhysicalAccess(dir, inPath, flags, 0, &readMountInfo, &readPDirHandle, &readPRootPath, &writeMountInfo, &writePDirHandle, &writePRootPath, &name) == -1) { // errno is set return -1; } // TODO: This code is partly the same as the code in uio_open(). // probably some code could be put in a seperate function. if ((flags & O_ACCMODE) == O_RDONLY) { // WritePDirHandle is not filled in. uio_PDirHandle_unref(readPDirHandle); pRootPath = readPRootPath; mountInfo = readMountInfo; } else if (readPDirHandle == writePDirHandle) { // In general, the dirs can be the same even when the handles are // not the same. But here it works, because uio_getPhysicalAccess // guarantees it. uio_PDirHandle_unref(readPDirHandle); uio_PDirHandle_unref(writePDirHandle); pRootPath = readPRootPath; mountInfo = readMountInfo; uio_free(writePRootPath); } else { // need to write uio_PDirEntryHandle *entry; entry = uio_getPDirEntryHandle(readPDirHandle, name); if (entry != NULL) { // file already exists uio_PDirEntryHandle_unref(entry); if ((flags & O_CREAT) == O_CREAT && (flags & O_EXCL) == O_EXCL) { uio_free(name); uio_PDirHandle_unref(readPDirHandle); uio_free(readPRootPath); uio_PDirHandle_unref(writePDirHandle); uio_free(writePRootPath); errno = EEXIST; return -1; } if ((flags & O_TRUNC) == O_TRUNC) { // No use copying the file to the writable dir. // As it doesn't exists there, O_TRUNC needs to be turned off // though. flags &= ~O_TRUNC; } else { // file needs to be copied if (uio_copyFilePhysical(readPDirHandle, name, writePDirHandle, name) == -1) { int savedErrno = errno; uio_free(name); uio_PDirHandle_unref(readPDirHandle); uio_free(readPRootPath); uio_PDirHandle_unref(writePDirHandle); uio_free(writePRootPath); errno = savedErrno; return -1; } } } else { // file does not exist if (((flags & O_ACCMODE) == O_RDONLY) || (flags & O_CREAT) != O_CREAT) { uio_free(name); uio_PDirHandle_unref(readPDirHandle); uio_free(readPRootPath); uio_PDirHandle_unref(writePDirHandle); uio_free(writePRootPath); errno = ENOENT; return -1; } } uio_PDirHandle_unref(readPDirHandle); uio_PDirHandle_unref(writePDirHandle); pRootPath = writePRootPath; mountInfo = writeMountInfo; uio_free(readPRootPath); } uio_free(name); *mountHandle = mountInfo->mountHandle; *outPath = pRootPath; return 0; } // *** begin dirList stuff *** // #define uio_DIR_BUFFER_SIZE 2048 // Large values will give significantly better speed for large // directories. What is stored in the buffer is file names // plus one pointer per file name, so with an average size of 16 // characters per file (including \0), a buffer of size 2048 will // store approximately 100 files. // It should be at least big enough to store one entry (NAME_MAX is // 255 on POSIX systems). // TODO: add a compile-time check for this typedef struct uio_DirBufferLink { char *buffer; int numEntries; struct uio_DirBufferLink *next; } uio_DirBufferLink; static int strPtrCmp(const char * const *ptr1, const char * const *ptr2); static void uio_DirBufferLink_free(uio_DirBufferLink *sdbl); static void uio_DirBufferChain_free(uio_DirBufferLink *dirBufferLink); static uio_DirList *uio_getDirListMulti(uio_PDirHandle **pDirHandles, int numPDirHandles, const char *pattern, match_MatchType matchType); static uio_DirList *uio_makeDirList(const char **newNames, const char * const *names, int numNames); static uio_DirList *uio_DirList_new(const char **names, int numNames, char *buffer); static void uio_collectDirEntries(uio_PDirHandle *pDirHandle, uio_DirBufferLink **linkPtr, int *numEntries); static inline uio_DirList *uio_DirList_alloc(void); static void uio_filterNames(const char * const *names, int numNames, const char **newNames, int *numNewNames, match_MatchContext *matchContext); static uio_EntriesContext *uio_openEntriesPhysical(uio_PDirHandle *dirHandle); static int uio_readEntriesPhysical(uio_EntriesContext *iterator, char *buf, size_t len); static void uio_closeEntriesPhysical(uio_EntriesContext *iterator); static uio_EntriesContext *uio_EntriesContext_new(uio_PRoot *pRoot, uio_NativeEntriesContext *native); static inline uio_EntriesContext *uio_EntriesContext_alloc(void); static inline void uio_EntriesContext_delete(uio_EntriesContext *entriesContext); static inline void uio_EntriesContext_free(uio_EntriesContext *entriesContext); // The caller may modify the elements of dirHandle->names, but // dirHandle->names itself, and the rest of the elements of dirHandle // should be left alone, so that they will be freed by uio_DirList_free(). uio_DirList * uio_getDirList(uio_DirHandle *dirHandle, const char *path, const char *pattern, match_MatchType matchType) { int numPDirHandles; uio_PDirHandle **pDirHandles; uio_DirList *result; if (uio_getPathPhysicalDirs(dirHandle, path, strlen(path), &pDirHandles, &numPDirHandles, NULL) == -1) { // errno is set return NULL; } if (numPDirHandles == 0) { assert(pDirHandles == NULL); // nothing to free return uio_DirList_new(NULL, 0, NULL); } result = uio_getDirListMulti(pDirHandles, numPDirHandles, pattern, matchType); { int savedErrno; savedErrno = errno; uio_PDirHandles_delete(pDirHandles, numPDirHandles); errno = savedErrno; } return result; } // Names and newNames may point to the same location. // numNewNames may point to &numNames. static void uio_filterDoubleNames(const char * const *names, int numNames, const char **newNames, int *numNewNames) { const char * const *endNames; const char *prevName; int newNum; if (numNames == 0) { *numNewNames = 0; return; } endNames = names + numNames; prevName = *names; *newNames = *names; newNames++; names++; newNum = 1; while (names < endNames) { if (strcmp(prevName, *names) != 0) { *newNames = *names; newNum++; prevName = *names; newNames++; } names++; } *numNewNames = newNum; } static uio_DirList * uio_getDirListMulti(uio_PDirHandle **pDirHandles, int numPDirHandles, const char *pattern, match_MatchType matchType) { int pDirI; // physical dir iterator uio_DirBufferLink **links; // array of bufferLinks for each physical dir uio_DirBufferLink *linkPtr; int *numNames; // number of entries in each physical dir int totalNumNames; const char **bigNameBuffer; // buffer where all names will end up together const char **destPtr; uio_DirList *result; match_Result matchResult; match_MatchContext *matchContext; matchResult = match_prepareContext(pattern, &matchContext, matchType); if (matchResult != match_OK) { #ifdef DEBUG fprintf(stderr, "Error compiling match function: %s.\n", match_errorString(matchContext, matchResult)); #endif match_freeContext(matchContext); errno = EIO; // I actually want to signal an internal error. // EIO comes closes return NULL; } // first get the directory listings for all seperate relevant dirs. totalNumNames = 0; links = uio_malloc(numPDirHandles * sizeof (uio_DirBufferLink *)); numNames = uio_malloc(numPDirHandles * sizeof (int)); for (pDirI = 0; pDirI < numPDirHandles; pDirI++) { uio_collectDirEntries(pDirHandles[pDirI], &links[pDirI], &numNames[pDirI]); totalNumNames += numNames[pDirI]; } bigNameBuffer = uio_malloc(totalNumNames * sizeof (uio_DirBufferLink *)); // Fill the bigNameBuffer with all the names from all the DirBufferLinks // of all the physical dirs. destPtr = bigNameBuffer; totalNumNames = 0; for (pDirI = 0; pDirI < numPDirHandles; pDirI++) { for (linkPtr = links[pDirI]; linkPtr != NULL; linkPtr = linkPtr->next) { int numNewNames; uio_filterNames((const char * const *) linkPtr->buffer, linkPtr->numEntries, destPtr, &numNewNames, matchContext); totalNumNames += numNewNames; destPtr += numNewNames; } } match_freeContext(matchContext); // Sort the bigNameBuffer // Necessary for removing doubles. // Not really necessary if the big list was the result of only one // physical dir, but let's output a sorted list anyhow. qsort((void *) bigNameBuffer, totalNumNames, sizeof (char *), (int (*)(const void *, const void *)) strPtrCmp); // remove doubles // (unnecessary if the big list was the result of only one physical dir) if (numPDirHandles > 1) { uio_filterDoubleNames(bigNameBuffer, totalNumNames, bigNameBuffer, &totalNumNames); } // resize the bigNameBuffer bigNameBuffer = uio_realloc((void *) bigNameBuffer, totalNumNames * sizeof (char *)); // put the lot in a DirList, copying the strings themselves result = uio_makeDirList(bigNameBuffer, bigNameBuffer, totalNumNames); // free the old junk for (pDirI = 0; pDirI < numPDirHandles; pDirI++) uio_DirBufferChain_free(links[pDirI]); uio_free(links); uio_free(numNames); return result; } // 'buffer' and 'names' may be the same dir // 'names' contains an array of 'numNames' pointers. // 'newNames', if non-NULL, will be used as the array of new pointers // (to a copy of the strings) in the DirList. static uio_DirList * uio_makeDirList(const char **newNames, const char * const *names, int numNames) { int i; size_t len, totLen; char *bufPtr; uio_DirList *result; if (newNames == NULL) newNames = uio_malloc(numNames * sizeof (char *)); totLen = 0; for (i = 0; i < numNames; i++) totLen += strlen(names[i]); totLen += numNames; // for the \0's result = uio_DirList_new(newNames, numNames, uio_malloc(totLen)); bufPtr = result->buffer; for (i = 0; i < numNames; i++) { len = strlen(names[i]) + 1; memcpy(bufPtr, names[i], len); newNames[i] = bufPtr; bufPtr += len; } return result; } static void uio_collectDirEntries(uio_PDirHandle *pDirHandle, uio_DirBufferLink **linkPtr, int *numEntries) { uio_EntriesContext *entriesContext; uio_DirBufferLink **linkEndPtr; // where to attach the next link int numRead; int totalEntries; char *buffer; entriesContext = uio_openEntriesPhysical(pDirHandle); if (entriesContext == NULL) { #ifdef DEBUG fprintf(stderr, "Error: uio_openEntriesPhysical() failed: %s\n", strerror(errno)); #endif *linkPtr = NULL; *numEntries = 0; return; } linkEndPtr = linkPtr; totalEntries = 0; while (1) { *linkEndPtr = uio_malloc(sizeof (uio_DirBufferLink)); buffer = uio_malloc(uio_DIR_BUFFER_SIZE); (*linkEndPtr)->buffer = buffer; numRead = uio_readEntriesPhysical(entriesContext, buffer, uio_DIR_BUFFER_SIZE); if (numRead == 0) { fprintf(stderr, "Warning: uio_DIR_BUFFER_SIZE is too small to " "hold a certain large entry on its own!\n"); uio_DirBufferLink_free(*linkEndPtr); break; } totalEntries += numRead; (*linkEndPtr)->numEntries = numRead; if (((char **) buffer)[numRead - 1] == NULL) { // The entry being NULL means this is the last buffer // Decrement the amount of queries to get the real number. (*linkEndPtr)->numEntries--; totalEntries--; linkEndPtr = &(*linkEndPtr)->next; break; } linkEndPtr = &(*linkEndPtr)->next; } *linkEndPtr = NULL; uio_closeEntriesPhysical(entriesContext); *numEntries = totalEntries; } static void uio_filterNames(const char * const *names, int numNames, const char **newNames, int *numNewNames, match_MatchContext *matchContext) { int newNum; const char * const *namesEnd; match_Result matchResult; newNum = 0; namesEnd = names + numNames; while (names < namesEnd) { matchResult = match_matchPattern(matchContext, *names); if (matchResult == match_MATCH) { *newNames = *names; newNames++; newNum++; } else if (matchResult != match_NOMATCH) { fprintf(stderr, "Error trying to match pattern: %s.\n", match_errorString(matchContext, matchResult)); } names++; } *numNewNames = newNum; } static int strPtrCmp(const char * const *ptr1, const char * const *ptr2) { return strcmp(*ptr1, *ptr2); } static uio_EntriesContext * uio_openEntriesPhysical(uio_PDirHandle *dirHandle) { uio_NativeEntriesContext *native; uio_PRoot *pRoot; pRoot = dirHandle->pRoot; assert(pRoot->handler->openEntries != NULL); native = pRoot->handler->openEntries(dirHandle); if (native == NULL) return NULL; uio_PRoot_refHandle(pRoot); return uio_EntriesContext_new(pRoot, native); } static int uio_readEntriesPhysical(uio_EntriesContext *iterator, char *buf, size_t len) { assert(iterator->pRoot->handler->readEntries != NULL); return iterator->pRoot->handler->readEntries(&iterator->native, buf, len); } static void uio_closeEntriesPhysical(uio_EntriesContext *iterator) { assert(iterator->pRoot->handler->closeEntries != NULL); iterator->pRoot->handler->closeEntries(iterator->native); uio_PRoot_unrefHandle(iterator->pRoot); uio_EntriesContext_delete(iterator); } static uio_EntriesContext * uio_EntriesContext_new(uio_PRoot *pRoot, uio_NativeEntriesContext *native) { uio_EntriesContext *result; result = uio_EntriesContext_alloc(); result->pRoot = pRoot; result->native = native; return result; } static inline uio_EntriesContext * uio_EntriesContext_alloc(void) { return uio_malloc(sizeof (uio_EntriesContext)); } static inline void uio_EntriesContext_delete(uio_EntriesContext *entriesContext) { uio_EntriesContext_free(entriesContext); } static inline void uio_EntriesContext_free(uio_EntriesContext *entriesContext) { uio_free(entriesContext); } static void uio_DirBufferLink_free(uio_DirBufferLink *dirBufferLink) { uio_free(dirBufferLink->buffer); uio_free(dirBufferLink); } static void uio_DirBufferChain_free(uio_DirBufferLink *dirBufferLink) { uio_DirBufferLink *next; while (dirBufferLink != NULL) { next = dirBufferLink->next; uio_DirBufferLink_free(dirBufferLink); dirBufferLink = next; } } static uio_DirList * uio_DirList_new(const char **names, int numNames, char *buffer) { uio_DirList *result; result = uio_DirList_alloc(); result->names = names; result->numNames = numNames; result->buffer = buffer; return result; } static uio_DirList * uio_DirList_alloc(void) { return uio_malloc(sizeof (uio_DirList)); } void uio_DirList_free(uio_DirList *dirList) { if (dirList->buffer) uio_free(dirList->buffer); if (dirList->names) uio_free((void *) dirList->names); uio_free(dirList); } // *** end DirList stuff *** // // *** PDirEntryHandle stuff *** // uio_PDirEntryHandle * uio_getPDirEntryHandle(const uio_PDirHandle *dirHandle, const char *name) { assert(dirHandle->pRoot->handler != NULL); return dirHandle->pRoot->handler->getPDirEntryHandle(dirHandle, name); } void uio_PDirHandle_deletePDirHandleExtra(uio_PDirHandle *pDirHandle) { if (pDirHandle->extra == NULL) return; assert(pDirHandle->pRoot->handler->deletePDirHandleExtra != NULL); pDirHandle->pRoot->handler->deletePDirHandleExtra(pDirHandle->extra); } void uio_PFileHandle_deletePFileHandleExtra(uio_PFileHandle *pFileHandle) { if (pFileHandle->extra == NULL) return; assert(pFileHandle->pRoot->handler->deletePFileHandleExtra != NULL); pFileHandle->pRoot->handler->deletePFileHandleExtra(pFileHandle->extra); } uio_PDirHandle * uio_PDirHandle_new(uio_PRoot *pRoot, uio_PDirHandleExtra extra) { uio_PDirHandle *result; result = uio_PDirHandle_alloc(); result->flags = uio_PDirEntryHandle_TYPE_DIR; result->ref = 1; result->pRoot = pRoot; result->extra = extra; return result; } void uio_PDirEntryHandle_delete(uio_PDirEntryHandle *pDirEntryHandle) { if (uio_PDirEntryHandle_isDir(pDirEntryHandle)) { uio_PDirHandle_delete((uio_PDirHandle *) pDirEntryHandle); } else { uio_PFileHandle_delete((uio_PFileHandle *) pDirEntryHandle); } } void uio_PDirHandle_delete(uio_PDirHandle *pDirHandle) { uio_PDirHandle_deletePDirHandleExtra(pDirHandle); uio_PDirHandle_free(pDirHandle); } static inline uio_PDirHandle * uio_PDirHandle_alloc(void) { uio_PDirHandle *result = uio_malloc(sizeof (uio_PDirHandle)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_PDirHandle, (void *) result); #endif return result; } static inline void uio_PDirHandle_free(uio_PDirHandle *pDirHandle) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_PDirHandle, (void *) pDirHandle); #endif uio_free(pDirHandle); } uio_PFileHandle * uio_PFileHandle_new(uio_PRoot *pRoot, uio_PFileHandleExtra extra) { uio_PFileHandle *result; result = uio_PFileHandle_alloc(); result->flags = uio_PDirEntryHandle_TYPE_REG; result->ref = 1; result->pRoot = pRoot; result->extra = extra; return result; } void uio_PFileHandle_delete(uio_PFileHandle *pFileHandle) { uio_PFileHandle_deletePFileHandleExtra(pFileHandle); uio_PFileHandle_free(pFileHandle); } static inline uio_PFileHandle * uio_PFileHandle_alloc(void) { uio_PFileHandle *result = uio_malloc(sizeof (uio_PFileHandle)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_PFileHandle, (void *) result); #endif return result; } static inline void uio_PFileHandle_free(uio_PFileHandle *pFileHandle) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_PFileHandle, (void *) pFileHandle); #endif uio_free(pFileHandle); } // *** PDirEntryHandle stuff *** // // ref count set to 1 uio_Handle * uio_Handle_new(uio_PRoot *root, uio_NativeHandle native, int openFlags) { uio_Handle *handle; handle = uio_Handle_alloc(); handle->ref = 1; uio_PRoot_refHandle(root); handle->root = root; handle->native = native; handle->openFlags = openFlags; return handle; } void uio_Handle_delete(uio_Handle *handle) { (handle->root->handler->close)(handle); uio_PRoot_unrefHandle(handle->root); uio_Handle_free(handle); } static inline uio_Handle * uio_Handle_alloc(void) { uio_Handle *result = uio_malloc(sizeof (uio_Handle)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_Handle, (void *) result); #endif return result; } static inline void uio_Handle_free(uio_Handle *handle) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_Handle, (void *) handle); #endif uio_free(handle); } // ref count set to 1 static uio_DirHandle * uio_DirHandle_new(uio_Repository *repository, char *path, char *rootEnd) { uio_DirHandle *result; result = uio_DirHandle_alloc(); result->ref = 1; result->repository = repository; result->path = path; result->rootEnd = rootEnd; return result; } void uio_DirHandle_delete(uio_DirHandle *dirHandle) { uio_free(dirHandle->path); uio_DirHandle_free(dirHandle); } static inline uio_DirHandle * uio_DirHandle_alloc(void) { uio_DirHandle *result = uio_malloc(sizeof (uio_DirHandle)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_DirHandle, (void *) result); #endif return result; } static inline void uio_DirHandle_free(uio_DirHandle *dirHandle) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_DirHandle, (void *) dirHandle); #endif uio_free(dirHandle); } void uio_DirHandle_print(const uio_DirHandle *dirHandle, FILE *out) { fprintf(out, "["); fwrite(dirHandle->path, dirHandle->path - dirHandle->rootEnd, 1, out); fprintf(out, "]%s", dirHandle->rootEnd); } static uio_MountHandle * uio_MountHandle_new(uio_Repository *repository, uio_MountInfo *mountInfo) { uio_MountHandle *result; result = uio_MountHandle_alloc(); result->repository = repository; result->mountInfo = mountInfo; return result; } static inline void uio_MountHandle_delete(uio_MountHandle *mountHandle) { uio_MountHandle_free(mountHandle); } static inline uio_MountHandle * uio_MountHandle_alloc(void) { uio_MountHandle *result = uio_malloc(sizeof (uio_MountHandle)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_MountHandle, (void *) result); #endif return result; } static inline void uio_MountHandle_free(uio_MountHandle *mountHandle) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_MountHandle, (void *) mountHandle); #endif uio_free(mountHandle); } uqm-0.6.2/sc2/src/sc2code/libs/uio/uiostream.c0000644000175000017500000003426010551540576017535 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "uioport.h" #include "iointrn.h" #include "uiostream.h" #include #include #include "uioutils.h" #ifdef uio_MEM_DEBUG # include "memdebug.h" #endif #define uio_Stream_BLOCK_SIZE 1024 static inline uio_Stream *uio_Stream_new(uio_Handle *handle, int openFlags); static inline void uio_Stream_delete(uio_Stream *stream); static inline uio_Stream *uio_Stream_alloc(void); static inline void uio_Stream_free(uio_Stream *stream); #ifdef NDEBUG # define uio_assertReadSanity(stream) # define uio_assertWriteSanity(stream) #else static void uio_assertReadSanity(uio_Stream *stream); static void uio_assertWriteSanity(uio_Stream *stream); #endif static int uio_Stream_fillReadBuffer(uio_Stream *stream); static int uio_Stream_flushWriteBuffer(uio_Stream *stream); static void uio_Stream_discardReadBuffer(uio_Stream *stream); uio_Stream * uio_fopen(uio_DirHandle *dir, const char *path, const char *mode) { int openFlags; uio_Handle *handle; uio_Stream *stream; int i; switch (*mode) { case 'r': openFlags = O_RDONLY; break; case 'w': openFlags = O_WRONLY | O_CREAT | O_TRUNC; break; case 'a': openFlags = O_WRONLY| O_CREAT | O_APPEND; default: errno = EINVAL; fprintf(stderr, "Invalid mode string in call to uio_fopen().\n"); return NULL; } mode++; // C'89 says 'b' may either be the second or the third character. // If someone specifies both 'b' and 't', he/she is out of luck. i = 2; while (i-- && (*mode != '\0')) { switch (*mode) { case 'b': #ifdef WIN32 openFlags |= O_BINARY; #endif break; case 't': #ifdef WIN32 openFlags |= O_TEXT; #endif break; case '+': openFlags = (openFlags & ~O_ACCMODE) | O_RDWR; break; default: i = 0; // leave the while loop break; } mode++; } // Any characters in the mode string that might follow are ignored. handle = uio_open(dir, path, openFlags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (handle == NULL) { // errno is set return NULL; } stream = uio_Stream_new(handle, openFlags); return stream; } int uio_fclose(uio_Stream *stream) { if (stream->operation == uio_StreamOperation_write) uio_Stream_flushWriteBuffer(stream); uio_close(stream->handle); uio_Stream_delete(stream); return 0; } // "The file position indicator for the stream (if defined) is advanced by // the number of characters successfully read. If an error occurs, the // resulting value of the file position indicator for the stream is // indeterminate. If a partial element is read, its value is // indeterminate." (from POSIX for fread()). size_t uio_fread(void *buf, size_t size, size_t nmemb, uio_Stream *stream) { size_t bytesToRead; size_t bytesRead; bytesToRead = size * nmemb; bytesRead = 0; uio_assertReadSanity(stream); stream->operation = uio_StreamOperation_read; if (stream->dataEnd > stream->dataStart) { // First use what's in the buffer. size_t numRead; numRead = minu(stream->dataEnd - stream->dataStart, bytesToRead); memcpy(buf, stream->dataStart, numRead); buf = (void *) ((char *) buf + numRead); stream->dataStart += numRead; bytesToRead -= numRead; bytesRead += numRead; } if (bytesToRead == 0) { // Done already return nmemb; } { // Read the rest directly into the caller's buffer. ssize_t numRead; numRead = uio_read(stream->handle, buf, bytesToRead); if (numRead == -1) { stream->status = uio_Stream_STATUS_ERROR; goto out; } bytesRead += numRead; if ((size_t) numRead < bytesToRead) { // End of file stream->status = uio_Stream_STATUS_EOF; stream->operation = uio_StreamOperation_none; goto out; } } out: if (bytesToRead == 0) return nmemb; return bytesRead / size; } char * uio_fgets(char *s, int size, uio_Stream *stream) { int orgSize; char *buf; uio_assertReadSanity(stream); stream->operation = uio_StreamOperation_read; size--; orgSize = size; buf = s; while (size > 0) { size_t maxRead; const char *newLinePos; // Fill buffer if empty. if (stream->dataStart == stream->dataEnd) { if (uio_Stream_fillReadBuffer(stream) == -1) { // errno is set stream->status = uio_Stream_STATUS_ERROR; return NULL; } if (stream->dataStart == stream->dataEnd) { // End-of-file stream->status = uio_Stream_STATUS_EOF; stream->operation = uio_StreamOperation_none; if (size == orgSize) { // Nothing was read. return NULL; } break; } } // Search in buffer maxRead = minu(stream->dataEnd - stream->dataStart, size); newLinePos = memchr(stream->dataStart, '\n', maxRead); if (newLinePos != NULL) { // Newline found. maxRead = newLinePos + 1 - stream->dataStart; memcpy(buf, stream->dataStart, maxRead); stream->dataStart += maxRead; buf[maxRead] = '\0'; return buf; } // No newline present. memcpy(buf, stream->dataStart, maxRead); stream->dataStart += maxRead; buf += maxRead; size -= maxRead; } *buf = '\0'; return s; } int uio_fgetc(uio_Stream *stream) { int result; uio_assertReadSanity(stream); stream->operation = uio_StreamOperation_read; if (stream->dataStart == stream->dataEnd) { // Buffer is empty if (uio_Stream_fillReadBuffer(stream) == -1) { stream->status = uio_Stream_STATUS_ERROR; return (int) EOF; } if (stream->dataStart == stream->dataEnd) { // End-of-file stream->status = uio_Stream_STATUS_EOF; stream->operation = uio_StreamOperation_none; return (int) EOF; } } result = (int) *((unsigned char *) stream->dataStart); stream->dataStart++; return result; } // Only one character pushback is guaranteed, just like with stdio ungetc(). int uio_ungetc(int c, uio_Stream *stream) { assert((stream->openFlags & O_ACCMODE) != O_WRONLY); assert(c >= 0 && c <= 255); return (int) EOF; // not implemented // return c; } int uio_fputc(int c, uio_Stream *stream) { assert((stream->openFlags & O_ACCMODE) != O_RDONLY); assert(c >= 0 && c <= 255); uio_assertWriteSanity(stream); stream->operation = uio_StreamOperation_write; if (stream->dataEnd == stream->bufEnd) { // The buffer is full. Flush it out. if (uio_Stream_flushWriteBuffer(stream) == -1) { // errno is set // Error status (for ferror()) is set. return EOF; } } *(unsigned char *) stream->dataEnd = (unsigned char) c; stream->dataEnd++; return c; } int uio_fputs(const char *s, uio_Stream *stream) { int result; result = uio_fwrite(s, strlen(s), 1, stream); if (result != 1) return EOF; return 0; } int uio_fseek(uio_Stream *stream, long offset, int whence) { int newPos; if (stream->operation == uio_StreamOperation_read) { uio_Stream_discardReadBuffer(stream); } else if (stream->operation == uio_StreamOperation_write) { if (uio_Stream_flushWriteBuffer(stream) == -1) { // errno is set return -1; } } assert(stream->dataStart == stream->buf); assert(stream->dataEnd == stream->buf); stream->operation = uio_StreamOperation_none; newPos = uio_lseek(stream->handle, offset, whence); if (newPos == -1) { // errno is set return -1; } stream->status = uio_Stream_STATUS_OK; // Clear error or end-of-file flag. return 0; } long uio_ftell(uio_Stream *stream) { off_t newPos; newPos = uio_lseek(stream->handle, 0, SEEK_CUR); if (newPos == (off_t) -1) { // errno is set return (long) -1; } if (stream->operation == uio_StreamOperation_write) { newPos += stream->dataEnd - stream->dataStart; } else if (stream->operation == uio_StreamOperation_read) { newPos -= stream->dataEnd - stream->dataStart; } return (long) newPos; } // If less that nmemb elements could be written, or an error occurs, the // file pointer is undefined. clearerr() followed by fseek() need to be // called before attempting to read or write again. // I don't have the C standard myself, but I suspect this is the official // behaviour for fread() and fwrite(). size_t uio_fwrite(const void *buf, size_t size, size_t nmemb, uio_Stream *stream) { ssize_t bytesToWrite; ssize_t bytesWritten; uio_assertWriteSanity(stream); stream->operation = uio_StreamOperation_write; // NB. If a file is opened in append mode, the file position indicator // is moved to the end of the file before writing. // We leave that up to the physical layer. bytesToWrite = size * nmemb; if (bytesToWrite < stream->bufEnd - stream->dataEnd) { // There's enough space in the write buffer to store everything. memcpy(stream->dataEnd, buf, bytesToWrite); stream->dataEnd += bytesToWrite; return nmemb; } // Not enough space in the write buffer to write everything. // Flush what's left in the write buffer first. if (uio_Stream_flushWriteBuffer(stream) == -1) { // errno is set // Error status (for ferror()) is set. return 0; } if (bytesToWrite < stream->bufEnd - stream->dataEnd) { // The now empty write buffer is large enough to store everything. memcpy(stream->dataEnd, buf, bytesToWrite); stream->dataEnd += bytesToWrite; return nmemb; } // There is more data to write than fits in the (empty) write buffer. // The data is written directly, in its entirety, without going // through the write buffer. bytesWritten = uio_write(stream->handle, buf, bytesToWrite); if (bytesWritten != bytesToWrite) { stream->status = uio_Stream_STATUS_ERROR; if (bytesWritten == -1) return 0; } if (bytesWritten == bytesToWrite) return nmemb; return (size_t) bytesWritten / size; } // NB: stdio fflush() accepts NULL to flush all streams. uio_flush() does // not. int uio_fflush(uio_Stream *stream) { assert(stream != NULL); if (stream->operation == uio_StreamOperation_write) { if (uio_Stream_flushWriteBuffer(stream) == -1) { // errno is set return (int) EOF; } stream->operation = uio_StreamOperation_none; } return 0; } int uio_feof(uio_Stream *stream) { return stream->status == uio_Stream_STATUS_EOF; } int uio_ferror(uio_Stream *stream) { return stream->status == uio_Stream_STATUS_ERROR; } void uio_clearerr(uio_Stream *stream) { stream->status = uio_Stream_STATUS_OK; } // Counterpart of fileno() uio_Handle * uio_streamHandle(uio_Stream *stream) { return stream->handle; } #ifndef NDEBUG static void uio_assertReadSanity(uio_Stream *stream) { assert((stream->openFlags & O_ACCMODE) != O_WRONLY); if (stream->operation == uio_StreamOperation_write) { // "[...] output shall not be directly followed by input without an // intervening call to the fflush function or to a file positioning // function (fseek, fsetpos, or rewind), and input shall not be // directly followed by output without an intervening call to a file // positioning function, unless the input operation encounters // end-of-file." (POSIX, C) fprintf(stderr, "Error: Reading on a file directly after writing, " "without an intervening call to fflush() or a file " "positioning function.\n"); abort(); } } #endif #ifndef NDEBUG static void uio_assertWriteSanity(uio_Stream *stream) { assert((stream->openFlags & O_ACCMODE) != O_RDONLY); if (stream->operation == uio_StreamOperation_read) { // "[...] output shall not be directly followed by input without an // intervening call to the fflush function or to a file positioning // function (fseek, fsetpos, or rewind), and input shall not be // directly followed by output without an intervening call to a file // positioning function, unless the input operation encounters // end-of-file." (POSIX, C) fprintf(stderr, "Error: Writing on a file directly after reading, " "without an intervening call to a file positioning " "function.\n"); abort(); } assert(stream->dataStart == stream->buf); } #endif static int uio_Stream_flushWriteBuffer(uio_Stream *stream) { ssize_t bytesWritten; assert(stream->operation == uio_StreamOperation_write); bytesWritten = uio_write(stream->handle, stream->dataStart, stream->dataEnd - stream->dataStart); if (bytesWritten != stream->dataEnd - stream->dataStart) { stream->status = uio_Stream_STATUS_ERROR; return -1; } assert(stream->dataStart == stream->buf); stream->dataEnd = stream->buf; return 0; } static void uio_Stream_discardReadBuffer(uio_Stream *stream) { assert(stream->operation == uio_StreamOperation_read); stream->dataStart = stream->buf; stream->dataEnd = stream->buf; // TODO: when implementing pushback: throw away pushback buffer. } static int uio_Stream_fillReadBuffer(uio_Stream *stream) { ssize_t numRead; assert(stream->operation == uio_StreamOperation_read); numRead = uio_read(stream->handle, stream->buf, uio_Stream_BLOCK_SIZE); if (numRead == -1) return -1; stream->dataStart = stream->buf; stream->dataEnd = stream->buf + numRead; return 0; } static inline uio_Stream * uio_Stream_new(uio_Handle *handle, int openFlags) { uio_Stream *result; result = uio_Stream_alloc(); result->handle = handle; result->openFlags = openFlags; result->status = uio_Stream_STATUS_OK; result->operation = uio_StreamOperation_none; result->buf = uio_malloc(uio_Stream_BLOCK_SIZE); result->dataStart = result->buf; result->dataEnd = result->buf; result->bufEnd = result->buf + uio_Stream_BLOCK_SIZE; return result; } static inline uio_Stream * uio_Stream_alloc(void) { uio_Stream *result = uio_malloc(sizeof (uio_Stream)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_Stream, (void *) result); #endif return result; } static inline void uio_Stream_delete(uio_Stream *stream) { uio_free(stream->buf); uio_Stream_free(stream); } static inline void uio_Stream_free(uio_Stream *stream) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_Stream, (void *) stream); #endif uio_free(stream); } uqm-0.6.2/sc2/src/sc2code/libs/uio/memdebug.h0000600000175000017500000000676710543202051017302 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _MEMDEBUG_H #define _MEMDEBUG_H #include #include "uioport.h" // Important: if you add an item here, add it to uio_MemDebug_LogTypeInfo // too. The order should be the same. typedef enum { uio_MemDebug_LogType_uio_DirHandle, uio_MemDebug_LogType_uio_FileSystemInfo, uio_MemDebug_LogType_uio_GPDir, uio_MemDebug_LogType_uio_GPFile, uio_MemDebug_LogType_uio_GPRoot, uio_MemDebug_LogType_uio_Handle, uio_MemDebug_LogType_uio_MountHandle, uio_MemDebug_LogType_uio_MountInfo, uio_MemDebug_LogType_uio_MountTree, uio_MemDebug_LogType_uio_MountTreeItem, uio_MemDebug_LogType_uio_PathComp, uio_MemDebug_LogType_uio_PFileHandle, uio_MemDebug_LogType_uio_PDirHandle, uio_MemDebug_LogType_uio_PRoot, uio_MemDebug_LogType_uio_Repository, uio_MemDebug_LogType_uio_Stream, uio_MemDebug_LogType_stdio_GPDirData, uio_MemDebug_LogType_zip_GPFileData, uio_MemDebug_LogType_zip_GPDirData, uio_MemDebug_numLogTypes, /* This needs to be the last entry */ } uio_MemDebug_LogType; typedef void (uio_MemDebug_PrintFunction)(FILE *out, const void *arg); typedef struct uio_MemDebug_LogTypeInfo { const char *name; uio_MemDebug_PrintFunction *printFunction; int flags; #define uio_MemDebug_PRINT_ALLOC 0x1 #define uio_MemDebug_PRINT_FREE 0x2 #define uio_MemDebug_PRINT_REF 0x4 #define uio_MemDebug_PRINT_UNREF 0x8 #define uio_MemDebug_PRINT_ALL \ (uio_MemDebug_PRINT_ALLOC | uio_MemDebug_PRINT_FREE | \ uio_MemDebug_PRINT_REF | uio_MemDebug_PRINT_UNREF) } uio_MemDebug_LogTypeInfo; extern const uio_MemDebug_LogTypeInfo uio_MemDebug_logTypeInfo[]; typedef struct uio_MemDebug_PointerInfo { int pointerRef; // Ref counter for the associated pointer, not the pointerInfo // itself. } uio_MemDebug_PointerInfo; void uio_MemDebug_init(void); void uio_MemDebug_unInit(void); void uio_MemDebug_logAllocation(uio_MemDebug_LogType type, void *ptr); void uio_MemDebug_logDeallocation(uio_MemDebug_LogType type, void *ptr); void uio_MemDebug_logRef(uio_MemDebug_LogType type, void *ptr); void uio_MemDebug_logUnref(uio_MemDebug_LogType type, void *ptr); void uio_MemDebug_printPointer(FILE *out, uio_MemDebug_LogType type, void *ptr); void uio_MemDebug_printPointersType(FILE *out, uio_MemDebug_LogType type); void uio_MemDebug_printPointers(FILE *out); #define uio_MemDebug_debugAlloc(type, pointer) \ uio_MemDebug_logAllocation(uio_MemDebug_LogType_ ## type, pointer) #define uio_MemDebug_debugFree(type, pointer) \ uio_MemDebug_logDeallocation(uio_MemDebug_LogType_ ## type, pointer) #define uio_MemDebug_debugRef(type, pointer) \ uio_MemDebug_logRef(uio_MemDebug_LogType_ ## type, pointer) #define uio_MemDebug_debugUnref(type, pointer) \ uio_MemDebug_logUnref(uio_MemDebug_LogType_ ## type, pointer) #endif /* _MEMDEBUG_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/match.c0000600000175000017500000003252610543202051016574 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #ifdef DEBUG # include #endif #define match_INTERNAL #include "match.h" #include "mem.h" #include "uioport.h" #ifdef HAVE_GLOB # include #endif static inline match_MatchContext *match_allocMatchContext(void); static inline void match_freeMatchContext(match_MatchContext *context); static inline match_LitteralContext *match_newLitteralContext(char *pattern); static inline match_LitteralContext *match_allocLitteralContext(void); static inline void match_freeLitteralContext(match_LitteralContext *context); static inline match_PrefixContext *match_newPrefixContext(char *pattern); static inline match_PrefixContext *match_allocPrefixContext(void); static inline void match_freePrefixContext(match_PrefixContext *context); static inline match_SuffixContext *match_newSuffixContext( char *pattern, size_t len); static inline match_SuffixContext *match_allocSuffixContext(void); static inline void match_freeSuffixContext(match_SuffixContext *context); static inline match_SubStringContext *match_newSubStringContext( char *pattern); static inline match_SubStringContext *match_allocSubStringContext(void); static inline void match_freeSubStringContext(match_SubStringContext *context); #ifdef HAVE_GLOB static inline match_GlobContext *match_newGlobContext(char *pattern); static inline match_GlobContext *match_allocGlobContext(void); static inline void match_freeGlobContext(match_GlobContext *context); #endif /* HAVE_GLOB */ #ifdef HAVE_REGEX static inline match_RegexContext *match_newRegexContext(void); static inline match_RegexContext *match_allocRegexContext(void); static inline void match_freeRegexContext(match_RegexContext *context); #endif /* HAVE_REGEX */ // *** General part *** // NB: Even if this function fails, *contextPtr contains a context // which needs to be freed. match_Result match_prepareContext(const char *pattern, match_MatchContext **contextPtr, match_MatchType type) { match_Result result; *contextPtr = match_allocMatchContext(); (*contextPtr)->type = type; switch (type) { case match_MATCH_LITTERAL: result = match_prepareLitteral(pattern, &(*contextPtr)->u.litteral); break; case match_MATCH_PREFIX: result = match_preparePrefix(pattern, &(*contextPtr)->u.prefix); break; case match_MATCH_SUFFIX: result = match_prepareSuffix(pattern, &(*contextPtr)->u.suffix); break; case match_MATCH_SUBSTRING: result = match_prepareSubString(pattern, &(*contextPtr)->u.subString); break; #ifdef HAVE_GLOB case match_MATCH_GLOB: result = match_prepareGlob(pattern, &(*contextPtr)->u.glob); break; #endif #ifdef HAVE_REGEX case match_MATCH_REGEX: result = match_prepareRegex(pattern, &(*contextPtr)->u.regex); break; #endif default: #ifdef DEBUG fprintf(stderr, "match_prepareContext called with unsupported " "type %d matching.\n", type); #endif return match_ENOSYS; } return result; } match_Result match_matchPattern(match_MatchContext *context, const char *string) { switch (context->type) { case match_MATCH_LITTERAL: return match_matchLitteral(context->u.litteral, string); case match_MATCH_PREFIX: return match_matchPrefix(context->u.prefix, string); case match_MATCH_SUFFIX: return match_matchSuffix(context->u.suffix, string); case match_MATCH_SUBSTRING: return match_matchSubString(context->u.subString, string); #ifdef HAVE_GLOB case match_MATCH_GLOB: return match_matchGlob(context->u.glob, string); #endif #ifdef HAVE_REGEX case match_MATCH_REGEX: return match_matchRegex(context->u.regex, string); #endif default: abort(); } } const char * match_errorString(match_MatchContext *context, match_Result result) { switch (result) { case match_OK: case match_MATCH: // case match_NOMATCH: // same value as match_OK return "Success"; case match_ENOSYS: return "Not implemented"; case match_ENOTINIT: return "Uninitialised use"; case match_ECUSTOM: // Depends on match type. break; default: return "Unknown error"; } switch (context->type) { #if 0 case match_MATCH_LITTERAL: return match_errorStringLitteral(context->u.litteral, result); case match_MATCH_PREFIX: return match_errorStringPrefix(context->u.prefix, result); case match_MATCH_SUFFIX: return match_errorStringSuffix(context->u.suffix, result); case match_MATCH_SUBSTRING: return match_errorStringSubString(context->u.subString, result); #ifdef HAVE_GLOB case match_MATCH_GLOB: return match_errorStringGlob(context->u.glob, result); #endif #endif #ifdef HAVE_REGEX case match_MATCH_REGEX: return match_errorStringRegex(context->u.regex, result); #endif default: abort(); } } void match_freeContext(match_MatchContext *context) { switch (context->type) { case match_MATCH_LITTERAL: match_freeLitteral(context->u.litteral); break; case match_MATCH_PREFIX: match_freePrefix(context->u.prefix); break; case match_MATCH_SUFFIX: match_freeSuffix(context->u.suffix); break; case match_MATCH_SUBSTRING: match_freeSubString(context->u.subString); break; #ifdef HAVE_GLOB case match_MATCH_GLOB: match_freeGlob(context->u.glob); break; #endif #ifdef HAVE_REGEX case match_MATCH_REGEX: match_freeRegex(context->u.regex); break; #endif default: abort(); } match_freeMatchContext(context); } static inline match_MatchContext * match_allocMatchContext(void) { return uio_malloc(sizeof (match_MatchContext)); } static inline void match_freeMatchContext(match_MatchContext *context) { uio_free(context); } // *** Litteral part *** match_Result match_prepareLitteral(const char *pattern, match_LitteralContext **contextPtr) { *contextPtr = match_newLitteralContext(uio_strdup(pattern)); return match_OK; } match_Result match_matchLitteral(match_LitteralContext *context, const char *string) { return (strcmp(context->pattern, string) == 0) ? match_MATCH : match_NOMATCH; } void match_freeLitteral(match_LitteralContext *context) { uio_free(context->pattern); match_freeLitteralContext(context); } static inline match_LitteralContext * match_newLitteralContext(char *pattern) { match_LitteralContext *result; result = match_allocLitteralContext(); result->pattern = pattern; return result; } static inline match_LitteralContext * match_allocLitteralContext(void) { return uio_malloc(sizeof (match_LitteralContext)); } static inline void match_freeLitteralContext(match_LitteralContext *context) { uio_free(context); } // *** Prefix part *** match_Result match_preparePrefix(const char *pattern, match_PrefixContext **contextPtr) { *contextPtr = match_newPrefixContext(uio_strdup(pattern)); return match_OK; } match_Result match_matchPrefix(match_PrefixContext *context, const char *string) { char *patPtr; patPtr = context->pattern; while (1) { if (*patPtr == '\0') { // prefix has completely matched return match_MATCH; } if (*string == '\0') { // no more string left, and still prefix to match return match_NOMATCH; } if (*patPtr != *string) return match_NOMATCH; patPtr++; string++; } } void match_freePrefix(match_PrefixContext *context) { uio_free(context->pattern); match_freePrefixContext(context); } static inline match_PrefixContext * match_newPrefixContext(char *pattern) { match_PrefixContext *result; result = match_allocPrefixContext(); result->pattern = pattern; return result; } static inline match_PrefixContext * match_allocPrefixContext(void) { return uio_malloc(sizeof (match_PrefixContext)); } static inline void match_freePrefixContext(match_PrefixContext *context) { uio_free(context); } // *** Suffix part *** match_Result match_prepareSuffix(const char *pattern, match_SuffixContext **contextPtr) { *contextPtr = match_newSuffixContext( uio_strdup(pattern), strlen(pattern)); return match_OK; } match_Result match_matchSuffix(match_SuffixContext *context, const char *string) { size_t stringLen; stringLen = strlen(string); if (stringLen < context->len) { // Supplied suffix is larger than string return match_NOMATCH; } return memcmp(string + stringLen - context->len, context->pattern, context->len) == 0 ? match_MATCH : match_NOMATCH; } void match_freeSuffix(match_SuffixContext *context) { uio_free(context->pattern); match_freeSuffixContext(context); } static inline match_SuffixContext * match_newSuffixContext(char *pattern, size_t len) { match_SuffixContext *result; result = match_allocSuffixContext(); result->pattern = pattern; result->len = len; return result; } static inline match_SuffixContext * match_allocSuffixContext(void) { return uio_malloc(sizeof (match_SuffixContext)); } static inline void match_freeSuffixContext(match_SuffixContext *context) { uio_free(context); } // *** SubString part *** match_Result match_prepareSubString(const char *pattern, match_SubStringContext **contextPtr) { *contextPtr = match_newSubStringContext(uio_strdup(pattern)); return match_OK; } match_Result match_matchSubString(match_SubStringContext *context, const char *string) { return strstr(string, context->pattern) != NULL; } void match_freeSubString(match_SubStringContext *context) { uio_free(context->pattern); match_freeSubStringContext(context); } static inline match_SubStringContext * match_newSubStringContext(char *pattern) { match_SubStringContext *result; result = match_allocSubStringContext(); result->pattern = pattern; return result; } static inline match_SubStringContext * match_allocSubStringContext(void) { return uio_malloc(sizeof (match_SubStringContext)); } static inline void match_freeSubStringContext(match_SubStringContext *context) { uio_free(context); } // *** Glob part *** #ifdef HAVE_GLOB match_Result match_prepareGlob(const char *pattern, match_GlobContext **contextPtr) { *contextPtr = match_newGlobContext(uio_strdup(pattern)); return match_OK; } match_Result match_matchGlob(match_GlobContext *context, const char *string) { int retval; retval = fnmatch(context->pattern, string, 0); switch (retval) { case 0: return match_MATCH; case FNM_NOMATCH: return match_NOMATCH; #if 0 case FNM_NOSYS: return match_ENOSYS; #endif default: return match_EUNKNOWN; } } void match_freeGlob(match_GlobContext *context) { uio_free(context->pattern); match_freeGlobContext(context); } static inline match_GlobContext * match_newGlobContext(char *pattern) { match_GlobContext *result; result = match_allocGlobContext(); result->pattern = pattern; return result; } static inline match_GlobContext * match_allocGlobContext(void) { return uio_malloc(sizeof (match_GlobContext)); } static inline void match_freeGlobContext(match_GlobContext *context) { uio_free(context); } #endif /* HAVE_GLOB */ // *** Regex part *** #ifdef HAVE_REGEX match_Result match_prepareRegex(const char *pattern, match_RegexContext **contextPtr) { *contextPtr = match_newRegexContext(); (*contextPtr)->errorCode = regcomp(&(*contextPtr)->native, pattern, REG_EXTENDED | REG_NOSUB); if ((*contextPtr)->errorCode == 0) { (*contextPtr)->flags = match_REGEX_INITIALISED; return match_OK; } return match_ECUSTOM; } match_Result match_matchRegex(match_RegexContext *context, const char *string) { int retval; if ((context->flags & match_REGEX_INITIALISED) != match_REGEX_INITIALISED) { return match_ENOTINIT; } if (context->errorString) { uio_free(context->errorString); context->errorString = NULL; } retval = regexec(&context->native, string, 0, NULL, 0); switch (retval) { case 0: return match_MATCH; case REG_NOMATCH: return match_NOMATCH; default: context->errorCode = retval; return match_ECUSTOM; } } const char * match_errorStringRegex(match_RegexContext *context, int errorCode) { size_t errorStringLength; if (context->errorString != NULL) uio_free(context->errorString); errorStringLength = regerror(context->errorCode, &context->native, NULL, 0); context->errorString = uio_malloc(errorStringLength); regerror(context->errorCode, &context->native, context->errorString, errorStringLength); (void) errorCode; return context->errorString; } void match_freeRegex(match_RegexContext *context) { regfree(&context->native); if (context->errorString) uio_free(context->errorString); match_freeRegexContext(context); } static inline match_RegexContext * match_newRegexContext(void) { match_RegexContext *result; result = match_allocRegexContext(); result->errorString = NULL; result->errorCode = 0; result->flags = 0; return result; } static inline match_RegexContext * match_allocRegexContext(void) { return uio_malloc(sizeof (match_RegexContext)); } static inline void match_freeRegexContext(match_RegexContext *context) { uio_free(context); } #endif /* HAVE_REGEX */ uqm-0.6.2/sc2/src/sc2code/libs/uio/physical.h0000600000175000017500000000533410543202051017316 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _PHYSICAL_H #define _PHYSICAL_H #ifndef uio_INTERNAL_PHYSICAL typedef void *uio_PRootExtra; typedef void *uio_NativeEntriesContext; #endif // 'forward' declarations typedef struct uio_PRoot uio_PRoot; typedef struct uio_PRoot_CloseHandler uio_PRoot_CloseHandler; #include "iointrn.h" #include "uioport.h" #include "fstypes.h" /* * Represents the root of a physical directory structure. */ struct uio_PRoot { int mountRef; /* Number of times this structure is referenced from * mount trees. */ int handleRef; /* Number of file or directory handles that point inside the * physical directory strucure of this pRoot. */ struct uio_PDirHandle *rootDir; struct uio_FileSystemHandler *handler; /* How to handle files in this PRoot tree */ int flags; # define uio_PRoot_NOCACHE 0x0002 struct uio_Handle *handle; /* The handle through which this PRoot is opened, * this is NULL for the top PRoot */ // TODO: move this to extra? #ifdef uio_PROOT_HAVE_CLOSE_HANDLERS int numCloseHandlers; uio_PRoot_CloseHandler *closeHandlers; #endif uio_PRootExtra extra; /* extra internal data for some filesystem types */ }; #ifdef uio_PROOT_HAVE_CLOSE_HANDLERS struct uio_PRoot_CloseHandler { void (*fun)(void *); void *arg; }; #endif void uio_PRoot_deletePRootExtra(uio_PRoot *pRoot); uio_PRoot *uio_PRoot_new(uio_PDirHandle *topDirHandle, uio_FileSystemHandler *handler, uio_Handle *handle, uio_PRootExtra extra, int flags); #ifdef uio_PROOT_HAVE_CLOSE_HANDLERS void uio_PRoot_addCloseHandler(uio_PRoot *pRoot, void (*fun)(void *), void *arg); void uio_PRoot_callCloseHandlers(uio_PRoot *pRoot); void uio_PRoot_removeCloseHandlers(uio_PRoot *pRoot); #endif uio_PDirHandle *uio_PRoot_getRootDirHandle(uio_PRoot *pRoot); void uio_PRoot_refHandle(uio_PRoot *pRoot); void uio_PRoot_unrefHandle(uio_PRoot *pRoot); void uio_PRoot_refMount(uio_PRoot *pRoot); void uio_PRoot_unrefMount(uio_PRoot *pRoot); #endif /* _PHYSICAL_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/uioutils.h0000600000175000017500000000511010543202051017347 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _UIOUTILS_H #define _UIOUTILS_H #include #include "types.h" #include "uioport.h" char *strcata(const char *first, const char *second); void *insertArray(const void *array, size_t oldNumElements, int insertPos, const void *element, size_t elementSize); void **insertArrayPointer(const void **array, size_t oldNumElements, int insertPos, const void *element); void *excludeArray(const void *array, size_t oldNumElements, int startPos, int numExclude, size_t elementSize); void **excludeArrayPointer(const void **array, size_t oldNumElements, int startPos, int numExclude); time_t dosToUnixTime(uio_uint16 date, uio_uint16 tm); char *dosToUnixPath(const char *path); /* Sometimes you just have to remove a 'const'. * (for instance, when implementing a function like strchr) */ static inline void * unconst(const void *arg) { union { char *c; const char *cc; } u; u.cc = arg; return u.c; } // byte1 is the lowest byte, byte4 the highest static inline uio_uint32 makeUInt32(uio_uint8 byte1, uio_uint8 byte2, uio_uint8 byte3, uio_uint8 byte4) { return byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24); } static inline uio_uint16 makeUInt16(uio_uint8 byte1, uio_uint8 byte2) { return byte1 | (byte2 << 8); } static inline uio_sint32 makeSInt32(uio_uint8 byte1, uio_uint8 byte2, uio_uint8 byte3, uio_uint8 byte4) { return byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24); } static inline uio_sint16 makeSInt16(uio_uint8 byte1, uio_uint8 byte2) { return byte1 | (byte2 << 8); } static inline uio_bool isBitSet(uio_uint32 bitField, int bit) { return ((bitField >> bit) & 1) == 1; } static inline int mins(int i1, int i2) { return i1 <= i2 ? i1 : i2; } static inline unsigned int minu(unsigned int i1, unsigned int i2) { return i1 <= i2 ? i1 : i2; } #endif /* _UIOUTILS_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/hashtable.c0000600000175000017500000002235710543202051017434 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef HASHTABLE_INTERNAL // If HASHTABLE_INTERNAL is already defined, this file is included // as a template. In this case hashtable.h has already been included. # define HASHTABLE_INTERNAL # include "hashtable.h" #endif #include #include #include #include #include "mem.h" #include "uioport.h" static void HASHTABLE_(setup)(HASHTABLE_(HashTable) *HashTable, uio_uint32 size); static void HASHTABLE_(resize)(HASHTABLE_(HashTable) *hashTable); static inline uio_uint32 nextPower2(uio_uint32 x); static inline HASHTABLE_(HashTable) *HASHTABLE_(allocHashTable)(void); static inline HASHTABLE_(HashEntry) *HASHTABLE_(newHashEntry)(uio_uint32 hash, HASHTABLE_(Key) *key, HASHTABLE_(Value) *value, HASHTABLE_(HashEntry) *next); static inline HASHTABLE_(HashEntry) *HASHTABLE_(allocHashEntry)(void); static inline void HASHTABLE_(freeHashEntry)( HASHTABLE_(HashEntry) *entry); HASHTABLE_(HashTable) * HASHTABLE_(newHashTable)( HASHTABLE_(HashFunction) hashFunction, HASHTABLE_(EqualFunction) equalFunction, HASHTABLE_(CopyFunction) copyFunction, HASHTABLE_(FreeFunction) freeFunction, uio_uint32 initialSize, double minFillQuotient, double maxFillQuotient) { HASHTABLE_(HashTable) *hashTable; assert(maxFillQuotient >= minFillQuotient); hashTable = HASHTABLE_(allocHashTable)(); hashTable->hashFunction = hashFunction; hashTable->equalFunction = equalFunction; hashTable->copyFunction = copyFunction; hashTable->freeFunction = freeFunction; hashTable->minFillQuotient = minFillQuotient; hashTable->maxFillQuotient = maxFillQuotient; HASHTABLE_(setup)(hashTable, initialSize); return hashTable; } uio_bool HASHTABLE_(add)(HASHTABLE_(HashTable) *hashTable, const HASHTABLE_(Key) *key, HASHTABLE_(Value) *value) { uio_uint32 hash; struct HASHTABLE_(HashEntry) *entry; hash = HASHTABLE_(HASH)(hashTable, key); entry = hashTable->entries[hash & hashTable->hashMask]; while (entry != NULL) { if (HASHTABLE_(EQUAL)(hashTable, key, entry->key)) { // key is already present return false; } entry = entry->next; } #ifdef HashTable_PROFILE if (hashTable->entries[hash & hashTable->hashMask] != NULL) hashTable->numCollisions++; #endif hashTable->entries[hash & hashTable->hashMask] = HASHTABLE_(newHashEntry)(hash, HASHTABLE_(COPY)(hashTable, key), value, hashTable->entries[hash & hashTable->hashMask]); hashTable->numEntries++; if (hashTable->numEntries > hashTable->maxSize) HASHTABLE_(resize)(hashTable); return true; } uio_bool HASHTABLE_(remove)(HASHTABLE_(HashTable) *hashTable, const HASHTABLE_(Key) *key) { uio_uint32 hash; struct HASHTABLE_(HashEntry) **entry, *next; hash = HASHTABLE_(HASH)(hashTable, key); entry = &hashTable->entries[hash & hashTable->hashMask]; while (1) { if (*entry == NULL) return false; if (HASHTABLE_(EQUAL)(hashTable, key, (*entry)->key)) { // found the key break; } entry = &(*entry)->next; } next = (*entry)->next; HASHTABLE_(FREE)(hashTable, (*entry)->key); HASHTABLE_(freeHashEntry)(*entry); *entry = next; hashTable->numEntries--; if (hashTable->numEntries < hashTable->minSize) HASHTABLE_(resize)(hashTable); return true; } HASHTABLE_(Value) * HASHTABLE_(find)(HASHTABLE_(HashTable) *hashTable, const HASHTABLE_(Key) *key) { uio_uint32 hash; struct HASHTABLE_(HashEntry) *entry; hash = HASHTABLE_(HASH)(hashTable, key); entry = hashTable->entries[hash & hashTable->hashMask]; while (entry != NULL) { if (HASHTABLE_(EQUAL)(hashTable, key, entry->key)) { // found the key return entry->value; } entry = entry->next; } return NULL; } uio_uint32 HASHTABLE_(count)(const HASHTABLE_(HashTable) *hashTable) { return hashTable->numEntries; } static void HASHTABLE_(setup)(HASHTABLE_(HashTable) *hashTable, uio_uint32 initialSize) { if (initialSize < 4) initialSize = 4; hashTable->size = nextPower2((uio_uint32) ceil( ((double) initialSize) / hashTable->maxFillQuotient)); hashTable->hashMask = hashTable->size - 1; hashTable->minSize = (uio_uint32) ceil(((double) (hashTable->size >> 1)) * hashTable->minFillQuotient); hashTable->maxSize = (uio_uint32) floor(((double) hashTable->size) * hashTable->maxFillQuotient); hashTable->entries = uio_calloc(hashTable->size, sizeof (HASHTABLE_(HashEntry) *)); hashTable->numEntries = 0; #ifdef HashTable_PROFILE hashTable->numCollisions = 0; #endif } static void HASHTABLE_(resize)(HASHTABLE_(HashTable) *hashTable) { HASHTABLE_(HashEntry) **oldEntries; HASHTABLE_(HashEntry) *entry, *next; HASHTABLE_(HashEntry) **newLocation; uio_uint32 oldNumEntries; uio_uint32 i; oldNumEntries = hashTable->numEntries; oldEntries = hashTable->entries; HASHTABLE_(setup)(hashTable, hashTable->numEntries); hashTable->numEntries = oldNumEntries; i = 0; while (oldNumEntries > 0) { entry = oldEntries[i]; while (entry != NULL) { next = entry->next; newLocation = &hashTable->entries[entry->hash & hashTable->hashMask]; #ifdef HashTable_PROFILE if (*newLocation != NULL) hashTable->numCollisions++; #endif entry->next = *newLocation; *newLocation = entry; oldNumEntries--; entry = next; } i++; } uio_free(oldEntries); } // Adapted from "Hackers Delight" // Returns the smallest power of two greater or equal to x. static inline uio_uint32 nextPower2(uio_uint32 x) { x--; x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; return x + 1; } // NB: Iterator should be considered invalid if the HashTable is changed. // TODO: change this (make it thread-safe) // this can be done by only marking items as deleted when // there are outstanding iterators. HASHTABLE_(Iterator) * HASHTABLE_(getIterator)(const HASHTABLE_(HashTable) *hashTable) { HASHTABLE_(Iterator) *iterator; uio_uint32 i; iterator = uio_malloc(sizeof (HASHTABLE_(Iterator))); iterator->hashTable = hashTable; // Look for the first used bucket. for (i = 0; i < iterator->hashTable->size; i++) { if (iterator->hashTable->entries[i] != NULL) { // Found a used bucket. iterator->bucketNr = i; iterator->entry = iterator->hashTable->entries[i]; return iterator; } } // No entries were found. iterator->bucketNr = i; iterator->entry = NULL; return iterator; } int HASHTABLE_(iteratorDone)(const HASHTABLE_(Iterator) *iterator) { return iterator->bucketNr >= iterator->hashTable->size; } HASHTABLE_(Key) * HASHTABLE_(iteratorKey)(HASHTABLE_(Iterator) *iterator) { return iterator->entry->key; } HASHTABLE_(Value) * HASHTABLE_(iteratorValue)(HASHTABLE_(Iterator) *iterator) { return iterator->entry->value; } // Should not be called if the iterator is already past the last entry. HASHTABLE_(Iterator) * HASHTABLE_(iteratorNext)(HASHTABLE_(Iterator) *iterator) { uio_uint32 i; // If there's another entry in this bucket, use that. iterator->entry = iterator->entry->next; if (iterator->entry != NULL) return iterator; // Look for the next used bucket. for (i = iterator->bucketNr + 1; i < iterator->hashTable->size; i++) { if (iterator->hashTable->entries[i] != NULL) { // Found another used bucket. iterator->bucketNr = i; iterator->entry = iterator->hashTable->entries[i]; return iterator; } } // No more entries were found. iterator->bucketNr = i; iterator->entry = NULL; return iterator; } void HASHTABLE_(freeIterator)(HASHTABLE_(Iterator) *iterator) { uio_free(iterator); } static inline HASHTABLE_(HashTable) * HASHTABLE_(allocHashTable)(void) { return uio_malloc(sizeof (HASHTABLE_(HashTable))); } static inline HASHTABLE_(HashEntry) * HASHTABLE_(newHashEntry)(uio_uint32 hash, HASHTABLE_(Key) *key, HASHTABLE_(Value) *value, HASHTABLE_(HashEntry) *next) { HASHTABLE_(HashEntry) *result; result = HASHTABLE_(allocHashEntry)(); result->hash = hash; result->key = key; result->value = value; result->next = next; return result; } static inline HASHTABLE_(HashEntry) * HASHTABLE_(allocHashEntry)(void) { return uio_malloc(sizeof (HASHTABLE_(HashEntry))); } void HASHTABLE_(deleteHashTable)(HASHTABLE_(HashTable) *hashTable) { uio_uint32 i; HASHTABLE_(HashEntry) *entry, *next; HASHTABLE_(HashEntry) **bucketPtr; i = hashTable->numEntries; bucketPtr = hashTable->entries; while (i > 0) { entry = *bucketPtr; while (entry != NULL) { next = entry->next; HASHTABLE_(FREE)(hashTable, entry->key); HASHTABLE_(freeHashEntry)(entry); entry = next; i--; } bucketPtr++; } uio_free(hashTable->entries); uio_free(hashTable); } static inline void HASHTABLE_(freeHashEntry)(HASHTABLE_(HashEntry) *entry) { uio_free(entry); } uqm-0.6.2/sc2/src/sc2code/libs/uio/fstypes.c0000644000175000017500000001444210546776502017226 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include "iointrn.h" #include "uioport.h" #include "fstypes.h" #include "mem.h" #include "defaultfs.h" #ifdef uio_MEM_DEBUG # include "memdebug.h" #endif static uio_bool uio_validFileSystemHandler(uio_FileSystemHandler *handler); static uio_FileSystemInfo *uio_FileSystemInfo_new(uio_FileSystemID id, uio_FileSystemHandler *handler, char *name); static uio_FileSystemInfo **uio_getFileSystemInfoPtr(uio_FileSystemID id); static inline uio_FileSystemInfo *uio_FileSystemInfo_alloc(void); static inline void uio_FileSystemInfo_free( uio_FileSystemInfo *fileSystemInfo); uio_FileSystemInfo *uio_fileSystems = NULL; // list sorted by id void uio_registerDefaultFileSystems(void) { int i; int num; uio_FileSystemID registerResult; num = uio_numDefaultFileSystems(); for (i = 0; i < num; i++) { registerResult = uio_registerFileSystem( defaultFileSystems[i].id, defaultFileSystems[i].name, defaultFileSystems[i].handler); switch (registerResult) { case 0: fprintf(stderr, "Warning: Default file system '%s' is " "already registered.\n", defaultFileSystems[i].name); break; case -1: fprintf(stderr, "Error: Could not register '%s' file \n" "system: %s\n", defaultFileSystems[i].name, strerror(errno)); break; default: assert(registerResult == defaultFileSystems[i].id); break; } } } void uio_unRegisterDefaultFileSystems(void) { int i; int num; num = uio_numDefaultFileSystems(); for (i = 0; i < num; i++) { if (uio_unRegisterFileSystem(defaultFileSystems[i].id) == -1) { fprintf(stderr, "Could not unregister '%s' file system: %s\n", defaultFileSystems[i].name, strerror(errno)); } } } // if wantedID = 0, just pick one // if wantedID != 0, 0 will be returned if that id wasn't available // a copy of 'name' is made uio_FileSystemID uio_registerFileSystem(uio_FileSystemID wantedID, const char *name, uio_FileSystemHandler *handler) { uio_FileSystemInfo **ptr; if (!uio_validFileSystemHandler(handler)) { errno = EINVAL; return -1; } if (wantedID == 0) { // Search for the first free id >= uio_FIRST_CUSTOM_ID // it is put in wantedID for (ptr = &uio_fileSystems; *ptr != NULL; ptr = &(*ptr)->next) if ((*ptr)->id >= uio_FS_FIRST_CUSTOM_ID) break; wantedID = uio_FS_FIRST_CUSTOM_ID; while (*ptr != NULL) { if ((*ptr)->id != wantedID) { // wantedID is not in use break; } wantedID++; ptr = &(*ptr)->next; } // wantedID contains the new ID } else { // search for the place in the list where to insert the wanted // id, keeping the list sorted for (ptr = &uio_fileSystems; *ptr != NULL; ptr = &(*ptr)->next) { if ((*ptr)->id <= wantedID) { if ((*ptr)->id == wantedID) return 0; break; } } } // ptr points to the place where the new link can inserted if (handler->init != NULL && handler->init() == -1) { // errno is set return -1; } { uio_FileSystemInfo *newInfo; newInfo = uio_FileSystemInfo_new(wantedID, handler, uio_strdup(name)); newInfo->next = *ptr; *ptr = newInfo; return wantedID; } } int uio_unRegisterFileSystem(uio_FileSystemID id) { uio_FileSystemInfo **ptr; uio_FileSystemInfo *temp; ptr = uio_getFileSystemInfoPtr(id); if (ptr == NULL) { errno = EINVAL; return -1; } if ((*ptr)->ref > 1) { errno = EBUSY; return -1; } if ((*ptr)->handler->unInit != NULL && ((*ptr)->handler->unInit() == -1)) { // errno is set return -1; } temp = *ptr; *ptr = (*ptr)->next; // uio_FileSystemHandler_unref(temp->handler); uio_free(temp->name); uio_FileSystemInfo_free(temp); return 0; } static uio_bool uio_validFileSystemHandler(uio_FileSystemHandler *handler) { // Check for the essentials if (handler->mount == NULL || handler->umount == NULL || handler->open == NULL || handler->close == NULL || handler->read == NULL || handler->openEntries == NULL || handler->readEntries == NULL || handler->closeEntries == NULL) { #ifdef DEBUG fprintf(stderr, "Invalid file system handler.\n"); #endif return false; } return true; } uio_FileSystemHandler * uio_getFileSystemHandler(uio_FileSystemID id) { uio_FileSystemInfo *ptr; for (ptr = uio_fileSystems; ptr != NULL; ptr = ptr->next) { if (ptr->id == id) return ptr->handler; } return NULL; } uio_FileSystemInfo * uio_getFileSystemInfo(uio_FileSystemID id) { uio_FileSystemInfo *ptr; for (ptr = uio_fileSystems; ptr != NULL; ptr = ptr->next) { if (ptr->id == id) return ptr; } return NULL; } static uio_FileSystemInfo ** uio_getFileSystemInfoPtr(uio_FileSystemID id) { uio_FileSystemInfo **ptr; for (ptr = &uio_fileSystems; *ptr != NULL; ptr = &(*ptr)->next) { if ((*ptr)->id == id) return ptr; } return NULL; } // sets ref to 1 static uio_FileSystemInfo * uio_FileSystemInfo_new(uio_FileSystemID id, uio_FileSystemHandler *handler, char *name) { uio_FileSystemInfo *result; result = uio_FileSystemInfo_alloc(); result->id = id; result->handler = handler; result->name = name; result->ref = 1; return result; } // *** Allocators *** static inline uio_FileSystemInfo * uio_FileSystemInfo_alloc(void) { uio_FileSystemInfo *result = uio_malloc(sizeof (uio_FileSystemInfo)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_FileSystemInfo, (void *) result); #endif return result; } // *** Deallocators *** static inline void uio_FileSystemInfo_free(uio_FileSystemInfo *fileSystemInfo) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_FileSystemInfo, (void *) fileSystemInfo); #endif uio_free(fileSystemInfo); } uqm-0.6.2/sc2/src/sc2code/libs/uio/utils.h0000600000175000017500000000251210543202051016635 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _UTILS_H #define _UTILS_H #ifdef uio_INTERNAL typedef struct uio_StdioAccessHandle uio_StdioAccessHandle; #else typedef void uio_StdioAccessHandle; #endif int uio_copyFile(uio_DirHandle *srcDir, const char *srcName, uio_DirHandle *dstDir, const char *newName); uio_StdioAccessHandle *uio_getStdioAccess(uio_DirHandle *dir, const char *path, int flags, uio_DirHandle *tempDir); const char *uio_StdioAccessHandle_getPath(uio_StdioAccessHandle *handle); void uio_releaseStdioAccess(uio_StdioAccessHandle *handle); #endif /* _UTILS_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/types.h0000600000175000017500000000227410543202051016646 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _uio_TYPES_H #define _uio_TYPES_H typedef enum { false = 0, true } uio_bool; typedef unsigned char uio_uint8; typedef signed char uio_sint8; typedef unsigned short uio_uint16; typedef signed short uio_sint16; typedef unsigned int uio_uint32; typedef signed int uio_sint32; typedef unsigned long uio_uintptr; // Needs to be adapted for 64 bits systems #endif /* _uio_TYPES_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio/paths.c0000644000175000017500000003445110546776502016652 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include "paths.h" #include "uioport.h" #include "mem.h" static inline uio_PathComp *uio_PathComp_alloc(void); static inline void uio_PathComp_free(uio_PathComp *pathComp); // gets the first dir component of a path // sets '*start' to the start of the first component // sets '*end' to the end of the first component // if *start >= dirEnd, then the end has been reached. void getFirstPathComponent(const char *dir, const char *dirEnd, const char **startComp, const char **endComp) { assert(dir <= dirEnd); *startComp = dir; if (*startComp == dirEnd) { *endComp = *startComp; return; } *endComp = memchr(*startComp, '/', dirEnd - *startComp); if (*endComp == NULL) *endComp = dirEnd; } // gets the first dir component of a path // sets '*start' to the start of the first component // sets '*end' to the end of the first component // if **start == '\0', then the end has been reached. void getFirstPath0Component(const char *dir, const char **startComp, const char **endComp) { *startComp = dir; if (**startComp == '\0') { *endComp = *startComp; return; } *endComp = strchr(*startComp, '/'); if (*endComp == NULL) *endComp = *startComp + strlen(*startComp); } // gets the next component of a path // '*start' should be set to the start of the last component // '*end' should be set to the end of the last component // '*start' will be set to the start of the next component // '*end' will be set to the end of the next component // if *start >= dirEnd, then the end has been reached. void getNextPathComponent(const char *dirEnd, const char **startComp, const char **endComp) { assert(*endComp <= dirEnd); if (*endComp == dirEnd) { *startComp = *endComp; return; } assert(**endComp == '/'); *startComp = *endComp + 1; *endComp = memchr(*startComp, '/', dirEnd - *startComp); if (*endComp == NULL) *endComp = dirEnd; } // gets the next component of a path // '*start' should be set to the start of the last component // '*end' should be set to the end of the last component // '*start' will be set to the start of the next component // '*end' will be set to the end of the next component // if **start == '\0', then the end has been reached. void getNextPath0Component(const char **startComp, const char **endComp) { if (**endComp == '\0') { *startComp = *endComp; return; } assert(**endComp == '/'); *startComp = *endComp + 1; *endComp = strchr(*startComp, '/'); if (*endComp == NULL) *endComp = *startComp + strlen(*startComp); } // if *end == dir, the beginning has been reached void getLastPathComponent(const char *dir, const char *endDir, const char **startComp, const char **endComp) { *endComp = endDir; // if (*(*endComp - 1) == '/') // (*endComp)--; *startComp = *endComp; // TODO: use memrchr where available while ((*startComp) - 1 >= dir && *(*startComp - 1) != '/') (*startComp)--; } // if *end == dir, the beginning has been reached // pre: dir is \0-terminated void getLastPath0Component(const char *dir, const char **startComp, const char **endComp) { *endComp = dir + strlen(dir); // if (*(*endComp - 1) == '/') // (*endComp)--; *startComp = *endComp; // TODO: use memrchr where available while ((*startComp) - 1 >= dir && *(*startComp - 1) != '/') (*startComp)--; } // if *end == dir, the beginning has been reached void getPreviousPathComponent(const char *dir, const char **startComp, const char **endComp) { if (*startComp == dir) { *endComp = *startComp; return; } *endComp = *startComp - 1; *startComp = *endComp; while ((*startComp) - 1 >= dir && *(*startComp - 1) != '/') (*startComp)--; } // Combine two parts of a paths into a new path. // The new path starts with a '/' only when the first part does. // The first path may (but doesn't have to) end on a '/', or may be empty. // Pre: the second path doesn't start with a '/' char * joinPaths(const char *first, const char *second) { char *result, *resPtr; size_t firstLen, secondLen; if (first[0] == '\0') return uio_strdup(second); firstLen = strlen(first); if (first[firstLen - 1] == '/') firstLen--; secondLen = strlen(second); result = uio_malloc(firstLen + secondLen + 2); resPtr = result; memcpy(resPtr, first, firstLen); resPtr += firstLen; *resPtr = '/'; resPtr++; memcpy(resPtr, second, secondLen); resPtr += secondLen; *resPtr = '\0'; return result; } // Combine two parts of a paths into a new path. // The new path will always start with a '/'. // The first path may (but doesn't have to) end on a '/', or may be empty. // Pre: the second path doesn't start with a '/' char * joinPathsAbsolute(const char *first, const char *second) { char *result, *resPtr; size_t firstLen, secondLen; if (first[0] == '\0') { secondLen = strlen(second); result = uio_malloc(secondLen + 2); result[0] = '/'; memcpy(&result[1], second, secondLen); result[secondLen + 1] = '\0'; return result; } firstLen = strlen(first); if (first[firstLen - 1] == '/') firstLen--; secondLen = strlen(second); result = uio_malloc(firstLen + secondLen + 3); resPtr = result; *resPtr = '/'; resPtr++; memcpy(resPtr, first, firstLen); resPtr += firstLen; *resPtr = '/'; resPtr++; memcpy(resPtr, second, secondLen); resPtr += secondLen; *resPtr = '\0'; return result; } // Returns 'false' if // - one of the path components is empty, or // - one of the path components is ".", or // - one of the path components is ".." // and 'true' otherwise. uio_bool validPathName(const char *path, size_t len) { const char *pathEnd; const char *start, *end; pathEnd = path + len; getFirstPathComponent(path, pathEnd, &start, &end); while (start < pathEnd) { if (end == start || (end - start == 1 && start[0] == '.') || (end - start == 2 && start[0] == '.' && start[1] == '.')) return false; getNextPathComponent(pathEnd, &start, &end); } return true; } // returns 0 if the path is not a valid UNC path. // Does not skip trailing slashes. size_t uio_skipUNCServerShare(const char *inPath) { const char *path = inPath; // Skip the initial two backslashes. if (path[0] != '\\' || path[1] != '\\') return (size_t) 0; path += 2; // Skip the server part. while (*path != '\\' && *path != '/') { if (*path == '\0') return (size_t) 0; path++; } // Skip the seperator. path++; // Skip the share part. while (*path != '\0' && *path != '\\' && *path != '/') path++; return (size_t) (path - inPath); } /** * Find the server and share part of a Windows "Universal Naming Convention" * path (a path of the form '\\server\share\path\file'). * The path must contain at least a server and share path to be valid. * The initial two slashes must be backslashes, the other slashes may each * be either a forward slash or a backslash. * * @param[in] inPath The path to parse. * @param[out] outPath Will contain a newly allocated string (to be * freed using uio_free(), containing the server and share part * of inPath, separated by a backslash, or NULL if 'inPath' was * not a valid UNC path. * @param[out] outLen If not NULL on entry, it will contain the string * length of '*outPath', or 0 if 'inPath' was not a valid UNC path. * * @returns The number of characters to add to 'inPath' to get to the first * path component past the server and share part, or 0 if 'inPath' * was not a valid UNC path. */ size_t uio_getUNCServerShare(const char *inPath, char **outPath, size_t *outLen) { const char *ptr; const char *server; const char *serverEnd; const char *share; const char *shareEnd; char *name; char *nameEnd; size_t nameLen; ptr = inPath; if (ptr[0] != '\\' || ptr[1] != '\\') goto noMatch; // Parse the server part. server = ptr + 2; serverEnd = server; for (;;) { if (*serverEnd == '\0') goto noMatch; if (isPathDelimiter(*serverEnd)) break; serverEnd++; } if (serverEnd == server) goto noMatch; // Parse the share part. share = serverEnd + 1; shareEnd = share; while (*shareEnd != '\0') { if (isPathDelimiter(*shareEnd)) break; serverEnd++; } // Skip any trailing path delimiters. ptr = shareEnd; while (isPathDelimiter(*ptr)) ptr++; // Allocate a new string and fill it. nameLen = (serverEnd - server) + (shareEnd - share) + 3; name = uio_malloc(nameLen + 1); nameEnd = name; *(nameEnd++) = '\\'; *(nameEnd++) = '\\'; memcpy(nameEnd, server, serverEnd - server); *(nameEnd++) = '\\'; memcpy(nameEnd, share, shareEnd - share); *nameEnd = '\0'; *outPath = name; if (outLen != NULL) *outLen = nameLen; return (size_t) (ptr - inPath); noMatch: *outPath = NULL; if (outLen != NULL) *outLen = 0; return (size_t) 0; } // Decomposes a path into its components. // If isAbsolute is not NULL, *isAbsolute will be set to true // iff the path is absolute. // As POSIX considers multiple consecutive slashes to be equivalent to // a single slash, so will uio (but not in the "\\MACHINE\share" part // of a Windows UNC path). int decomposePath(const char *path, uio_PathComp **pathComp, uio_bool *isAbsolute) { uio_PathComp *result; uio_PathComp *last; uio_PathComp **endResult = &result; uio_bool absolute = false; char *name; #ifdef WIN32 size_t nameLen; #endif if (path[0] == '\0') { errno = ENOENT; return -1; } last = NULL; #ifdef WIN32 path += uio_getUNCServerShare(path, &name, &nameLen); if (name != NULL) { // UNC path *endResult = uio_PathComp_new(name, nameLen, last); last = *endResult; endResult = &last->next; absolute = true; } else if (isDriveLetter(path[0]) && path[1] == ':') { // DOS/Windows drive letter. if (path[2] != '\0' && !isPathDelimiter(path[2])) { errno = ENOENT; return -1; } name = uio_memdup0(path, 2); *endResult = uio_PathComp_new(name, 2, last); last = *endResult; endResult = &last->next; absolute = true; } else #endif { if (isPathDelimiter(*path)) { absolute = true; do { path++; } while (isPathDelimiter(*path)); } } while (*path != '\0') { const char *start = path; while (*path != '\0' && !isPathDelimiter(*path)) path++; name = uio_memdup0(path, path - start); *endResult = uio_PathComp_new(name, path - start, last); last = *endResult; endResult = &last->next; while (isPathDelimiter(*path)) path++; } *endResult = NULL; *pathComp = result; if (isAbsolute != NULL) *isAbsolute = absolute; return 0; } // Pre: pathComp forms a valid path for the platform. void composePath(const uio_PathComp *pathComp, uio_bool absolute, char **path, size_t *pathLen) { size_t len; const uio_PathComp *ptr; char *result; char *pathPtr; assert(pathComp != NULL); // First determine how much space is required. len = 0; if (absolute) len++; ptr = pathComp; while (ptr != NULL) { len += ptr->nameLen; ptr = ptr->next; } // Allocate the required space. result = (char *) uio_malloc(len + 1); // Fill the path. pathPtr = result; ptr = pathComp; if (absolute) { #ifdef WIN32 if (ptr->name[0] == '\\') { // UNC path assert(ptr->name[1] == '\\'); // Nothing to do. } else if (ptr->nameLen == 2 && ptr->name[1] == ':' && isDriveLetter(ptr->name[0])) { // Nothing to do. } else #endif { *(pathPtr++) = '/'; } } for (;;) { memcpy(pathPtr, ptr->name, ptr->nameLen); pathPtr += ptr->nameLen; ptr = ptr->next; if (ptr == NULL) break; *(pathPtr++) = '/'; } *path = result; *pathLen = len; } // *** uio_PathComp *** // static inline uio_PathComp * uio_PathComp_alloc(void) { uio_PathComp *result = uio_malloc(sizeof (uio_PathComp)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_PathComp, (void *) result); #endif return result; } static inline void uio_PathComp_free(uio_PathComp *pathComp) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_PathComp, (void *) pathComp); #endif uio_free(pathComp); } // 'name' should be a null terminated string. It is stored in the PathComp, // no copy is made. // 'namelen' should be the length of 'name' uio_PathComp * uio_PathComp_new(char *name, size_t nameLen, uio_PathComp *upComp) { uio_PathComp *result; result = uio_PathComp_alloc(); result->name = name; result->nameLen = nameLen; result->up = upComp; return result; } void uio_PathComp_delete(uio_PathComp *pathComp) { uio_PathComp *next; while (pathComp != NULL) { next = pathComp->next; uio_free(pathComp->name); uio_PathComp_free(pathComp); pathComp = next; } } // Count the number of path components that 'comp' leads to. int uio_countPathComps(const uio_PathComp *comp) { int count; count = 0; for (; comp != NULL; comp = comp->next) count++; return count; } uio_PathComp * uio_lastPathComp(uio_PathComp *comp) { if (comp == NULL) return NULL; while (comp->next != NULL) comp = comp->next; return comp; } // make a list of uio_PathComps from a path string uio_PathComp * uio_makePathComps(const char *path, uio_PathComp *upComp) { const char *start, *end; char *str; uio_PathComp *result; uio_PathComp **compPtr; // Where to put the next PathComp compPtr = &result; getFirstPath0Component(path, &start, &end); while (*start != '\0') { str = uio_malloc(end - start + 1); memcpy(str, start, end - start); str[end - start] = '\0'; *compPtr = uio_PathComp_new(str, end - start, upComp); upComp = *compPtr; compPtr = &(*compPtr)->next; getNextPath0Component(&start, &end); } *compPtr = NULL; return result; } void uio_printPathComp(FILE *outStream, const uio_PathComp *comp) { fprintf(outStream, "%s", comp->name); } void uio_printPathToComp(FILE *outStream, const uio_PathComp *comp) { if (comp == NULL) return; uio_printPathToComp(outStream, comp->up); fprintf(outStream, "/"); uio_printPathComp(outStream, comp); } uqm-0.6.2/sc2/src/sc2code/libs/uio/memdebug.c0000600000175000017500000002203610543202051017260 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include "memdebug.h" #include "hashtable.h" #include "mem.h" #include "uioutils.h" #include "types.h" #include "uioport.h" // I'm intentionally not including the .h files. It would only make things // messy, because the second arguments would be other pointers, which // would require typecasts of the functions in uio_MemDebug_logTypeInfo. extern void uio_DirHandle_print(FILE *out, const void *); extern void uio_printMountInfo(FILE *out, const void *); extern void uio_printMountTreeItem(FILE *out, const void *); extern void uio_printPathComp(FILE *out, const void *); // Must be in the same order as in uio_MemDebug_LogTypes // Change the third field to have debug info printed for specific actions. // See memdebug.h file the possible values. const uio_MemDebug_LogTypeInfo uio_MemDebug_logTypeInfo[] = { { "uio_DirHandle", uio_DirHandle_print, 0 }, { "uio_FileSystemInfo", NULL, 0 }, { "uio_GPDir", NULL, 0 }, { "uio_GPFile", NULL, 0 }, { "uio_GPRoot", NULL, 0 }, { "uio_Handle", NULL, 0 }, { "uio_MountHandle", NULL, 0 }, { "uio_MountInfo", uio_printMountInfo, 0 }, { "uio_MountTree", NULL, 0 }, { "uio_MountTreeItem", uio_printMountTreeItem, 0 }, { "uio_PathComp", uio_printPathComp, 0 }, { "uio_PFileHandle", NULL, 0 }, { "uio_PDirHandle", NULL, 0 }, { "uio_PRoot", NULL, 0 }, { "uio_Repository", NULL, 0 }, { "uio_Stream", NULL, 0 }, { "stdio_GPDirData", NULL, 0 }, #ifdef HAVE_ZIP { "zip_GPFileData", NULL, 0 }, { "zip_GPDirData", NULL, 0 }, #endif }; HashTable_HashTable **uio_MemDebug_logs; static uio_uint32 uio_MemDebug_pointerHash(const void *ptr); static uio_bool uio_MemDebug_pointerCompare(const void *ptr1, const void *ptr2); static void *uio_MemDebug_pointerCopy(const void *ptr); static void uio_MemDebug_pointerFree(void *ptr); static inline uio_MemDebug_PointerInfo *uio_MemDebug_PointerInfo_new(int ref); static inline void uio_MemDebug_PointerInfo_delete( uio_MemDebug_PointerInfo *pointerInfo); static inline uio_MemDebug_PointerInfo *uio_MemDebug_PointerInfo_alloc(void); static inline void uio_MemDebug_PointerInfo_free( uio_MemDebug_PointerInfo *pointerInfo); void uio_MemDebug_init(void) { int i; assert((int) uio_MemDebug_numLogTypes == (sizeof uio_MemDebug_logTypeInfo / sizeof uio_MemDebug_logTypeInfo[0])); uio_MemDebug_logs = uio_malloc(uio_MemDebug_numLogTypes * sizeof (HashTable_HashTable *)); for (i = 0; i < uio_MemDebug_numLogTypes; i++) { uio_MemDebug_logs[i] = HashTable_newHashTable( uio_MemDebug_pointerHash, uio_MemDebug_pointerCompare, uio_MemDebug_pointerCopy, uio_MemDebug_pointerFree, 4, 0.85, 0.90); } } void uio_MemDebug_unInit(void) { int i; for (i = 0; i < uio_MemDebug_numLogTypes; i++) HashTable_deleteHashTable(uio_MemDebug_logs[i]); uio_free(uio_MemDebug_logs); } static uio_uint32 uio_MemDebug_pointerHash(const void *ptr) { uio_uintptr ptrInt; ptrInt = (uio_uintptr) ptr; return (uio_uint32) (ptrInt ^ (ptrInt >> 10) ^ (ptrInt >> 20)); } static uio_bool uio_MemDebug_pointerCompare(const void *ptr1, const void *ptr2) { return ptr1 == ptr2; } static void * uio_MemDebug_pointerCopy(const void *ptr) { return unconst(ptr); } static void uio_MemDebug_pointerFree(void *ptr) { (void) ptr; } void uio_MemDebug_logAllocation(uio_MemDebug_LogType type, void *ptr) { uio_MemDebug_PointerInfo *pointerInfo; if (ptr == NULL) { fprintf(stderr, "Fatal: Allocated pointer is (%s *) NULL.\n", uio_MemDebug_logTypeInfo[(int) type].name); abort(); } if (uio_MemDebug_logTypeInfo[(int) type].flags & uio_MemDebug_PRINT_ALLOC) { fprintf(stderr, "Alloc "); uio_MemDebug_printPointer(stderr, type, ptr); fprintf(stderr, "\n"); } pointerInfo = uio_MemDebug_PointerInfo_new(1); HashTable_add(uio_MemDebug_logs[type], ptr, (void *) pointerInfo); } void uio_MemDebug_logDeallocation(uio_MemDebug_LogType type, void *ptr) { uio_MemDebug_PointerInfo *pointerInfo; if (ptr == NULL) { fprintf(stderr, "Fatal: Attempt to free (%s *) NULL pointer.\n", uio_MemDebug_logTypeInfo[(int) type].name); abort(); } if (uio_MemDebug_logTypeInfo[(int) type].flags & uio_MemDebug_PRINT_FREE) { fprintf(stderr, "Free "); uio_MemDebug_printPointer(stderr, type, ptr); fprintf(stderr, "\n"); } pointerInfo = HashTable_find(uio_MemDebug_logs[type], ptr); if (pointerInfo == NULL) { fprintf(stderr, "Fatal: Attempt to free unallocated pointer " "(%s *) %p.\n", uio_MemDebug_logTypeInfo[(int) type].name, ptr); abort(); } #if 0 if (pointerInfo->ref != 0) { fprintf(stderr, "Fatal: Attempt to free pointer with references " "left (%s *) %p.\n", uio_MemDebug_logTypeInfo[(int) type].name, ptr); abort(); } #endif uio_MemDebug_PointerInfo_free(pointerInfo); HashTable_remove(uio_MemDebug_logs[type], ptr); } void uio_MemDebug_logRef(uio_MemDebug_LogType type, void *ptr) { uio_MemDebug_PointerInfo *pointerInfo; if (ptr == NULL) { fprintf(stderr, "Fatal: Attempt to increment reference to a " "(%s *) NULL pointer.\n", uio_MemDebug_logTypeInfo[(int) type].name); abort(); } pointerInfo = HashTable_find(uio_MemDebug_logs[type], ptr); if (pointerInfo == NULL) { fprintf(stderr, "Fatal: Attempt to increment reference to " "unallocated pointer (%s *) %p.\n", uio_MemDebug_logTypeInfo[(int) type].name, ptr); abort(); } pointerInfo->pointerRef++; if (uio_MemDebug_logTypeInfo[(int) type].flags & uio_MemDebug_PRINT_REF) { fprintf(stderr, "Ref++ to %d, ", pointerInfo->pointerRef); uio_MemDebug_printPointer(stderr, type, ptr); fprintf(stderr, "\n"); } } void uio_MemDebug_logUnref(uio_MemDebug_LogType type, void *ptr) { uio_MemDebug_PointerInfo *pointerInfo; if (ptr == NULL) { fprintf(stderr, "Fatal: Attempt to decrement reference to a " "(%s *) NULL pointer.\n", uio_MemDebug_logTypeInfo[(int) type].name); abort(); } pointerInfo = HashTable_find(uio_MemDebug_logs[type], ptr); if (pointerInfo == NULL) { fprintf(stderr, "Fatal: Attempt to decrement reference to " "unallocated pointer (%s *) %p.\n", uio_MemDebug_logTypeInfo[(int) type].name, ptr); abort(); } if (pointerInfo->pointerRef == 0) { fprintf(stderr, "Fatal: Attempt to decrement reference below 0 for " "pointer (%s *) %p.\n", uio_MemDebug_logTypeInfo[(int) type].name, ptr); abort(); } pointerInfo->pointerRef--; if (uio_MemDebug_logTypeInfo[(int) type].flags & uio_MemDebug_PRINT_UNREF) { fprintf(stderr, "Ref-- to %d, ", pointerInfo->pointerRef); uio_MemDebug_printPointer(stderr, type, ptr); fprintf(stderr, "\n"); } } void uio_MemDebug_printPointer(FILE *out, uio_MemDebug_LogType type, void *ptr) { fprintf(out, "(%s *) %p", uio_MemDebug_logTypeInfo[(int) type].name, ptr); if (uio_MemDebug_logTypeInfo[(int) type].printFunction != NULL) { fprintf(out, ": "); uio_MemDebug_logTypeInfo[(int) type].printFunction(out, ptr); } } void uio_MemDebug_printPointersType(FILE *out, uio_MemDebug_LogType type) { HashTable_Iterator *iterator; for (iterator = HashTable_getIterator(uio_MemDebug_logs[type]); !HashTable_iteratorDone(iterator); iterator = HashTable_iteratorNext(iterator)) { uio_MemDebug_printPointer(out, type, HashTable_iteratorKey(iterator)); fprintf(out, "\n"); } HashTable_freeIterator(iterator); } void uio_MemDebug_printPointers(FILE *out) { int i; for (i = 0; i < uio_MemDebug_numLogTypes; i++) uio_MemDebug_printPointersType(out, i); } static inline uio_MemDebug_PointerInfo * uio_MemDebug_PointerInfo_new(int ref) { uio_MemDebug_PointerInfo *result; result = uio_MemDebug_PointerInfo_alloc(); result->pointerRef = ref; return result; } static inline void uio_MemDebug_PointerInfo_delete(uio_MemDebug_PointerInfo *pointerInfo) { uio_MemDebug_PointerInfo_free(pointerInfo); } static inline uio_MemDebug_PointerInfo * uio_MemDebug_PointerInfo_alloc(void) { return uio_malloc(sizeof (uio_MemDebug_PointerInfo)); } static inline void uio_MemDebug_PointerInfo_free(uio_MemDebug_PointerInfo *pointerInfo) { uio_free(pointerInfo); } uqm-0.6.2/sc2/src/sc2code/libs/uio/gphys.c0000600000175000017500000004107710543202051016633 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #define uio_INTERNAL_PHYSICAL #define uio_INTERNAL_GPHYS typedef void *uio_NativeHandle; typedef void *uio_GPRootExtra; typedef void *uio_GPDirExtra; typedef void *uio_GPFileExtra; #include #include #include "gphys.h" #include "paths.h" #include "uioport.h" #ifdef uio_MEM_DEBUG # include "memdebug.h" #endif static void uio_GPDir_deepPersistentUnref(uio_GPDir *gPDir); static uio_GPRoot *uio_GPRoot_alloc(void); static void uio_GPRoot_free(uio_GPRoot *gPRoot); static inline uio_GPDir *uio_GPDir_alloc(void); void uio_GPDir_delete(uio_GPDir *gPDir); static inline void uio_GPDir_free(uio_GPDir *gPDir); static inline uio_GPFile *uio_GPFile_alloc(void); void uio_GPFile_delete(uio_GPFile *gPFile); static inline void uio_GPFile_free(uio_GPFile *gPFile); // Call this when you need to edit a file 'dirName' in the GPDir 'gPDir'. // a new entry is created when necessary. // uio_gPDirCommitSubDir should be called when you're done with it. // // a copy of dirName is made if needed; the caller remains responsible for // freeing the original // Allocates a new dir if necessary. uio_GPDir * uio_GPDir_prepareSubDir(uio_GPDir *gPDir, const char *dirName) { uio_GPDir *subDir; uio_GPDirEntry *entry; entry = uio_GPDirEntries_find(gPDir->entries, dirName); if (entry != NULL) { if (uio_GPDirEntry_isDir(entry)) { // Return existing subdir. uio_GPDir_ref((uio_GPDir *) entry); return (uio_GPDir *) entry; } else { // There already exists a file with the same name. // This should not happen within one file system. fprintf(stderr, "Directory %s shadows file with the same name " "from the same filesystem.\n", dirName); } } // return new subdir subDir = uio_GPDir_new(gPDir->pRoot, NULL, uio_GPDir_DETACHED); // subDir->ref is initialised at 1 return subDir; } // call this when you're done with a dir acquired by a call to // uio_gPDirPrepareSubDir void uio_GPDir_commitSubDir(uio_GPDir *gPDir, const char *dirName, uio_GPDir *subDir) { if (subDir->flags & uio_GPDir_DETACHED) { // New dir. // reference to the subDir is passed along to the upDir, // so subDir->ref should not be changed. uio_GPDirEntries_add(gPDir->entries, dirName, subDir); subDir->flags &= ~uio_GPDir_DETACHED; if (!(subDir->flags & uio_GPDir_PERSISTENT)) { // Persistent dirs have an extra reference. uio_GPDir_unref(subDir); } } else { uio_GPDir_unref(subDir); } } // a copy of fileName is made if needed; the caller remains responsible for // freeing the original void uio_GPDir_addFile(uio_GPDir *gPDir, const char *fileName, uio_GPFile *file) { // A file will never already exist in a dir. There can only be // one entry in a physical dir with the same name. uio_GPDirEntries_add(gPDir->entries, fileName, (uio_GPDirEntry *) file); } // Pre: 'fileName' exists in 'gPDir' and is a dir. void uio_GPDir_removeFile(uio_GPDir *gPDir, const char *fileName) { uio_GPDirEntry *entry; uio_GPFile *file; uio_bool retVal; entry = uio_GPDirEntries_find(gPDir->entries, fileName); if (entry == NULL) { // This means the file has no associated GPFile. // This can happen when the GPFile structure is only used for caching. return; } assert(!uio_GPDirEntry_isDir(entry)); file = (uio_GPFile *) entry; uio_GPFile_unref(file); retVal = uio_GPDirEntries_remove(gPDir->entries, fileName); assert(retVal); } // Pre: 'dirName' exists in 'gPDir' and is a dir. void uio_GPDir_removeSubDir(uio_GPDir *gPDir, const char *dirName) { uio_GPDirEntry *entry; uio_GPDir *subDir; uio_bool retVal; entry = uio_GPDirEntries_find(gPDir->entries, dirName); if (entry == NULL) { // This means the directory has no associated GPDir. // This can happen when the GPDir structure is only used for caching. return; } assert(uio_GPDirEntry_isDir(entry)); subDir = (uio_GPDir *) entry; if (subDir->flags & uio_GPDir_PERSISTENT) { // Persistent dirs have an extra reference. uio_GPDir_unref(subDir); } retVal = uio_GPDirEntries_remove(gPDir->entries, dirName); assert(retVal); } void uio_GPDir_setComplete(uio_GPDir *gPDir, uio_bool flag) { if (flag) { gPDir->flags |= uio_GPDir_COMPLETE; } else gPDir->flags &= ~uio_GPDir_COMPLETE; } int uio_GPDir_entryCount(const uio_GPDir *gPDir) { return uio_GPDirEntries_count(gPDir->entries); } static void uio_GPDir_access(uio_GPDir *gPDir) { if (!(gPDir->flags & uio_GPDir_COMPLETE)) uio_GPDir_fill(gPDir); } // The ref counter for the dir entry is not incremented. uio_GPDirEntry * uio_GPDir_getGPDirEntry(uio_GPDir *gPDir, const char *name) { uio_GPDir_access(gPDir); return uio_GPDirEntries_find(gPDir->entries, name); } // The ref counter for the dir entry is not incremented. uio_PDirEntryHandle * uio_GPDir_getPDirEntryHandle(const uio_PDirHandle *pDirHandle, const char *name) { uio_GPDirEntry *gPDirEntry; gPDirEntry = uio_GPDir_getGPDirEntry(pDirHandle->extra, name); if (gPDirEntry == NULL) return NULL; uio_GPDirEntry_ref(gPDirEntry); if (uio_GPDirEntry_isDir(gPDirEntry)) { return (uio_PDirEntryHandle *) uio_PDirHandle_new(pDirHandle->pRoot, (uio_GPDir *) gPDirEntry); } else { return (uio_PDirEntryHandle *) uio_PFileHandle_new(pDirHandle->pRoot, (uio_GPFile *) gPDirEntry); } } /* * Follow a path starting from a specified physical dir as long as possible. * When you can get no further, 'endGPDir' will be filled in with the dir * where you ended up, and 'pathRest' will point into the original path. to * the beginning of the part that was not matched. * It is allowed to have endGPDir point to gPDir and/or restPath * point to path when calling this function.i * returns: 0 if the complete path was matched * ENOENT if some component (the next one) didn't exists * ENODIR if a component (the next one) exists but isn't a dir * See also uio_walkPhysicalPath. The difference is that this one works * directly on the GPDirs and is faster because of that. */ int uio_walkGPPath(uio_GPDir *startGPDir, const char *path, size_t pathLen, uio_GPDir **endGPDir, const char **pathRest) { const char *pathEnd; const char *partStart, *partEnd; char *tempBuf; uio_GPDir *gPDir; uio_GPDirEntry *entry; int retVal; gPDir = startGPDir; tempBuf = uio_alloca(strlen(path) + 1); pathEnd = path + pathLen; getFirstPathComponent(path, pathEnd, &partStart, &partEnd); while (1) { if (partStart == pathEnd) { retVal = 0; break; } memcpy(tempBuf, partStart, partEnd - partStart); tempBuf[partEnd - partStart] = '\0'; entry = uio_GPDir_getGPDirEntry(gPDir, tempBuf); if (entry == NULL) { retVal = ENOENT; break; } if (!uio_GPDirEntry_isDir(entry)) { retVal = ENOTDIR; break; } gPDir = (uio_GPDir *) entry; getNextPathComponent(pathEnd, &partStart, &partEnd); } *pathRest = partStart; *endGPDir = gPDir; return retVal; } uio_GPDirEntries_Iterator * uio_GPDir_openEntries(uio_PDirHandle *pDirHandle) { uio_GPDir_access(pDirHandle->extra); return uio_GPDirEntries_getIterator(pDirHandle->extra->entries); } // the start of 'buf' will be filled with pointers to strings // those strings are stored elsewhere in buf. // The function returns the number of strings passed along, or -1 for error. // If there are no more entries, the last pointer will be NULL. // (this pointer counts towards the return value) int uio_GPDir_readEntries(uio_GPDirEntries_Iterator **iterator, char *buf, size_t len) { char *end; char **start; int num; const char *name; size_t nameLen; // buf will be filled like this: // The start of buf will contain pointers to char *, // the end will contain the actual char[] that those pointers point to. // The start and the end will grow towards eachother. start = (char **) buf; end = buf + len; num = 0; while (!uio_GPDirEntries_iteratorDone(*iterator)) { name = uio_GPDirEntries_iteratorName(*iterator); nameLen = strlen(name) + 1; // Does this work with systems that need memory access to be // aligned on a certain number of bytes? if ((size_t) (sizeof (char *) + nameLen) > (size_t) (end - (char *) start)) { // Not enough room to fit the pointer (at the beginning) and // the string (at the end). return num; } end -= nameLen; memcpy(end, name, nameLen); *start = end; start++; num++; *iterator = uio_GPDirEntries_iteratorNext(*iterator); } if (sizeof (char *) > (size_t) (end - (char *) start)) { // not enough room to fit the NULL pointer. // It will have to be reported seperately the next time. return num; } *start = NULL; num++; return num; } void uio_GPDir_closeEntries(uio_GPDirEntries_Iterator *iterator) { uio_GPDirEntries_freeIterator(iterator); } void uio_GPDir_fill(uio_GPDir *gPDir) { if ((gPDir->flags & uio_GPDir_COMPLETE) && !(gPDir->flags & uio_GPDir_NOCACHE)) return; assert(gPDir->pRoot->extra->ops->fillGPDir != NULL); gPDir->pRoot->extra->ops->fillGPDir(gPDir); } void uio_GPRoot_deleteGPRootExtra(uio_GPRoot *gPRoot) { if (gPRoot->extra == NULL) return; assert(gPRoot->ops->deleteGPRootExtra != NULL); gPRoot->ops->deleteGPRootExtra(gPRoot->extra); } void uio_GPDir_deleteGPDirExtra(uio_GPDir *gPDir) { if (gPDir->extra == NULL) return; assert(gPDir->pRoot->extra->ops->deleteGPDirExtra != NULL); gPDir->pRoot->extra->ops->deleteGPDirExtra(gPDir->extra); } void uio_GPFile_deleteGPFileExtra(uio_GPFile *gPFile) { if (gPFile->extra == NULL) return; assert(gPFile->pRoot->extra->ops->deleteGPFileExtra != NULL); gPFile->pRoot->extra->ops->deleteGPFileExtra(gPFile->extra); } int uio_gPDirFlagsFromPRootFlags(int flags) { int newFlags; newFlags = 0; if (flags & uio_PRoot_NOCACHE) newFlags |= uio_GPDir_NOCACHE; return newFlags; } int uio_gPFileFlagsFromPRootFlags(int flags) { int newFlags; newFlags = 0; if (flags & uio_PRoot_NOCACHE) newFlags |= uio_GPFile_NOCACHE; return newFlags; } // This function is to be called from the physical layer. // uio_GPDirHandle is the extra information for an uio_PDirHandle. // This is in practice a pointer to the uio_GPDir. void uio_GPDirHandle_delete(uio_GPDirHandle *gPDirHandle) { uio_GPDir_unref((uio_GPDir *) gPDirHandle); (void) gPDirHandle; } // This function is to be called from the physical layer. // uio_GPFileHandle is the extra information for an uio_PFileHandle. // This is in practice a pointer to the uio_GPFile. void uio_GPFileHandle_delete(uio_GPFileHandle *gPFileHandle) { uio_GPFile_unref((uio_GPFile *) gPFileHandle); (void) gPFileHandle; } void uio_GPDirEntry_delete(uio_GPDirEntry *gPDirEntry) { if (uio_GPDirEntry_isDir(gPDirEntry)) { uio_GPDir_delete((uio_GPDir *) gPDirEntry); } else { uio_GPFile_delete((uio_GPFile *) gPDirEntry); } } // note: sets ref count to 1 uio_GPDir * uio_GPDir_new(uio_PRoot *pRoot, uio_GPDirExtra extra, int flags) { uio_GPDir *gPDir; gPDir = uio_GPDir_alloc(); gPDir->ref = 1; gPDir->pRoot = pRoot; gPDir->entries = uio_GPDirEntries_new(); gPDir->extra = extra; flags |= uio_gPDirFlagsFromPRootFlags(gPDir->pRoot->flags); if (pRoot->extra->flags & uio_GPRoot_PERSISTENT) flags |= uio_GPDir_PERSISTENT; gPDir->flags = flags | uio_GPDirEntry_TYPE_DIR; return gPDir; } // pre: There are no more references to within the gPDir, and // gPDir is the last reference to the gPDir itself. void uio_GPDir_delete(uio_GPDir *gPDir) { #if 0 uio_GPDirEntry *entry; uio_GPDirEntries_Iterator *iterator; iterator = uio_GPDirEntries_getIterator(gPDir->entries); while (!uio_GPDirEntries_iteratorDone(iterator)) { entry = uio_GPDirEntries_iteratorItem(iterator); assert(entry->ref == 0); if (uio_GPDirEntry_isDir(entry)) { uio_GPDir_delete((uio_GPDir *) entry); } else { uio_GPFile_delete((uio_GPFile *) entry); } iterator = uio_GPDirEntries_iteratorNext(iterator); } #endif assert(gPDir->ref == 0); uio_GPDirEntries_deleteHashTable(gPDir->entries); uio_GPDir_deleteGPDirExtra(gPDir); uio_GPDir_free(gPDir); } static void uio_GPDir_deepPersistentUnref(uio_GPDir *gPDir) { uio_GPDirEntry *entry; uio_GPDirEntries_Iterator *iterator; iterator = uio_GPDirEntries_getIterator(gPDir->entries); while (!uio_GPDirEntries_iteratorDone(iterator)) { entry = uio_GPDirEntries_iteratorItem(iterator); if (uio_GPDirEntry_isDir(entry)) { uio_GPDir_deepPersistentUnref((uio_GPDir *) entry); } else { uio_GPFile_unref((uio_GPFile *) entry); } iterator = uio_GPDirEntries_iteratorNext(iterator); } uio_GPDirEntries_freeIterator(iterator); if (gPDir->flags & uio_GPDir_PERSISTENT) { uio_GPDir_unref(gPDir); } else { gPDir->flags &= ~uio_GPDir_COMPLETE; } } static inline uio_GPDir * uio_GPDir_alloc(void) { uio_GPDir *result = uio_malloc(sizeof (uio_GPDir)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_GPDir, (void *) result); #endif return result; } static inline void uio_GPDir_free(uio_GPDir *gPDir) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_GPDir, (void *) gPDir); #endif uio_free(gPDir); } // note: sets ref count to 1 uio_GPFile * uio_GPFile_new(uio_PRoot *pRoot, uio_GPFileExtra extra, int flags) { uio_GPFile *gPFile; gPFile = uio_GPFile_alloc(); gPFile->ref = 1; gPFile->pRoot = pRoot; gPFile->extra = extra; gPFile->flags = flags; return gPFile; } void uio_GPFile_delete(uio_GPFile *gPFile) { assert(gPFile->ref == 0); uio_GPFile_deleteGPFileExtra(gPFile); uio_GPFile_free(gPFile); } static inline uio_GPFile * uio_GPFile_alloc(void) { uio_GPFile *result = uio_malloc(sizeof (uio_GPFile)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_GPFile, (void *) result); #endif return result; } static inline void uio_GPFile_free(uio_GPFile *gPFile) { uio_free(gPFile); #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_GPFile, (void *) gPFile); #endif } // The ref counter to 'handle' is not incremented. uio_PRoot * uio_GPRoot_makePRoot(uio_FileSystemHandler *handler, int pRootFlags, uio_GPRoot_Operations *ops, uio_GPRootExtra gPRootExtra, int gPRootFlags, uio_Handle *handle, uio_GPDirExtra gPDirExtra, int gPDirFlags) { uio_PRoot *result; uio_GPDir *gPTopDir; uio_GPRoot *gPRoot; gPRoot = uio_GPRoot_new(ops, gPRootExtra, gPRootFlags); result = uio_PRoot_new(NULL, handler, handle, gPRoot, pRootFlags); gPTopDir = uio_GPDir_new(result, gPDirExtra, gPDirFlags); if (gPRoot->flags & uio_GPRoot_PERSISTENT) uio_GPDir_ref(gPTopDir); result->rootDir = uio_GPDir_makePDirHandle(gPTopDir); return result; } // Pre: there are no more references to PRoot or anything inside it. int uio_GPRoot_umount(uio_PRoot *pRoot) { uio_PDirHandle *topDirHandle; uio_GPDir *topDir; topDirHandle = uio_PRoot_getRootDirHandle(pRoot); topDir = topDirHandle->extra; if (pRoot->extra->flags & uio_GPRoot_PERSISTENT) uio_GPDir_deepPersistentUnref(topDir); uio_PDirHandle_unref(topDirHandle); (void) pRoot; return 0; } uio_GPRoot * uio_GPRoot_new(uio_GPRoot_Operations *ops, uio_GPRootExtra extra, int flags) { uio_GPRoot *result; result = uio_GPRoot_alloc(); result->ops = ops; result->extra = extra; result->flags = flags; return result; } void uio_GPRoot_delete(uio_GPRoot *gPRoot) { uio_GPRoot_deleteGPRootExtra(gPRoot); uio_GPRoot_free(gPRoot); } static uio_GPRoot * uio_GPRoot_alloc(void) { uio_GPRoot *result = uio_malloc(sizeof (uio_GPRoot)); #ifdef uio_MEM_DEBUG uio_MemDebug_debugAlloc(uio_GPRoot, (void *) result); #endif return result; } static void uio_GPRoot_free(uio_GPRoot *gPRoot) { #ifdef uio_MEM_DEBUG uio_MemDebug_debugFree(uio_GPRoot, (void *) gPRoot); #endif uio_free(gPRoot); } // The ref counter to the gPDir is not inremented. uio_PDirHandle * uio_GPDir_makePDirHandle(uio_GPDir *gPDir) { return uio_PDirHandle_new(gPDir->pRoot, gPDir); } #ifdef DEBUG void uio_GPDirEntry_print(FILE *outStream, uio_GPDirEntry *gPDirEntry) { if (uio_GPDirEntry_isDir(gPDirEntry)) { uio_GPDir_print(outStream, (uio_GPDir *) gPDirEntry); } else { uio_GPFile_print(outStream, (uio_GPFile *) gPDirEntry); } } void uio_GPDir_print(FILE *outStream, uio_GPDir *gPDir) { (void) outStream; (void) gPDir; } void uio_GPFile_print(FILE *outStream, uio_GPFile *gPFile) { (void) outStream; (void) gPFile; } #endif uqm-0.6.2/sc2/src/sc2code/libs/net.h0000600000175000017500000000200210543202055015465 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NET_H #define _NET_H #include "network/network.h" #include "network/netmanager/netmanager.h" #include "network/connect/connect.h" #include "network/connect/listen.h" #include "network/connect/resolve.h" #endif /* _NET_H */ uqm-0.6.2/sc2/src/sc2code/libs/cdplib.h0000600000175000017500000000151110543202055016140 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _CDPLIB_H #define _CDPLIB_H #include "cdp/cdp.h" #endif /* _CDPLIB_H */ uqm-0.6.2/sc2/src/sc2code/libs/video/0000755000175000017500000000000010552600274015657 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/video/vfileins.c0000600000175000017500000000160610543202043017625 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "vidlib.h" #include "video.h" VIDEO_REF LoadVideoFile (const char *pStr) { return _init_video_file (pStr); } uqm-0.6.2/sc2/src/sc2code/libs/video/video.h0000600000175000017500000000322310543202044017117 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UQM_VIDEO_H #define _UQM_VIDEO_H #include "options.h" #include "misc.h" #include "vidlib.h" #include "libs/graphics/tfb_draw.h" #include "types.h" #include "videodec.h" #include "libs/sound/sound.h" #include "libs/tasklib.h" typedef struct tfb_videoclip { TFB_VideoDecoder *decoder; // decoder to read from float length; // total length of clip seconds uint32 w, h; // video player data RECT dst_rect; // destination screen rect RECT src_rect; // source rect MUSIC_REF hAudio; Task play_task; uint32 frame_time; // time when next frame should be rendered TFB_Image* frame; // frame preped and optimized for rendering uint32 cur_frame; // index of frame currently displayed uint32 max_frame_wait; bool playing; Mutex guard; uint32 want_frame; // audio-signaled desired frame index void* data; // user-defined data } TFB_VideoClip; extern VIDEO_REF _init_video_file(const char *pStr); #endif // _UQM_VIDEO_H uqm-0.6.2/sc2/src/sc2code/libs/video/vidplayer.h0000600000175000017500000000211610543202044020010 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _VIDPLAYER_H #define _VIDPLAYER_H #include "video.h" bool TFB_InitVideoPlayer (void); void TFB_UninitVideoPlayer (void); void TFB_FadeClearScreen (void); bool TFB_PlayVideo (VIDEO_REF VidRef, uint32 x, uint32 y); void TFB_StopVideo (VIDEO_REF VidRef); bool TFB_VideoPlaying (VIDEO_REF VidRef); void TFB_VideoInput (VIDEO_REF VidRef); #endif // _VIDPLAYER_H uqm-0.6.2/sc2/src/sc2code/libs/video/video.c0000600000175000017500000000602710543202044017117 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "video.h" #include "setup.h" #include "vidplayer.h" #include "libs/inplib.h" #define NULL_VIDEO_REF (0) static VIDEO_REF _cur_video = NULL_VIDEO_REF; BOOLEAN InitVideo (BOOLEAN useCDROM) //useCDROM doesn't really apply to us { TFB_PixelFormat fmt; TFB_DrawCanvas_GetScreenFormat (&fmt); if (!VideoDecoder_Init (0, fmt.BitsPerPixel, fmt.Rmask, fmt.Gmask, fmt.Bmask, 0)) return FALSE; return TFB_InitVideoPlayer (); (void)useCDROM; /* dodge compiler warning */ } void UninitVideo () { TFB_UninitVideoPlayer (); VideoDecoder_Uninit (); } void VidStop () { if (_cur_video) { TFB_StopVideo (_cur_video); TFB_FadeClearScreen (); } _cur_video = NULL_VIDEO_REF; } VIDEO_REF VidPlaying () // this should just probably return BOOLEAN { if (!_cur_video) return NULL_VIDEO_REF; if (TFB_VideoPlaying (_cur_video)) return _cur_video; return NULL_VIDEO_REF; } VIDEO_TYPE VidPlay (VIDEO_REF VidRef, const char *loopname, BOOLEAN uninit) // uninit was used to uninit the game kernel // before spawning duck exe { VIDEO_TYPE ret; TFB_VideoClip* vid = (TFB_VideoClip*) VidRef; if (!vid) return NO_FMV; if (_cur_video) TFB_StopVideo (_cur_video); _cur_video = NULL_VIDEO_REF; TFB_FadeClearScreen (); FlushInput (); LockMutex (GraphicsLock); SetContext (ScreenContext); // play video in the center of the screen if (TFB_PlayVideo (VidRef, (SCREEN_WIDTH - vid->w) / 2, (SCREEN_HEIGHT - vid->h) / 2)) { _cur_video = VidRef; ret = SOFTWARE_FMV; } else { ret = NO_FMV; } UnlockMutex (GraphicsLock); /* dodge compiler warnings */ (void) loopname; (void) uninit; return ret; } void VidDoInput (void) { if (_cur_video) TFB_VideoInput (_cur_video); } VIDEO_REF _init_video_file(const char *pStr) { TFB_VideoClip* vid; TFB_VideoDecoder* dec; dec = VideoDecoder_Load (contentDir, pStr); if (!dec) return NULL_VIDEO_REF; vid = (TFB_VideoClip*) HCalloc (sizeof (*vid)); vid->decoder = dec; vid->length = dec->length; vid->w = vid->decoder->w; vid->h = vid->decoder->h; vid->guard = CreateMutex ("video guard", SYNC_CLASS_VIDEO); return (VIDEO_REF) vid; } BOOLEAN DestroyVideo (VIDEO_REF VideoRef) { TFB_VideoClip* vid = (TFB_VideoClip*) VideoRef; if (!vid) return FALSE; VideoDecoder_Free (vid->decoder); DestroyMutex (vid->guard); HFree (vid); return TRUE; } uqm-0.6.2/sc2/src/sc2code/libs/video/dukvid.h0000600000175000017500000000210110543202044017271 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _DUKVID_H #define _DUKVID_H #include "libs/video/videodec.h" extern TFB_VideoDecoderFuncs dukv_DecoderVtbl; typedef enum { // positive values are the same as in errno dukve_None = 0, dukve_Unknown = -1, dukve_BadFile = -2, dukve_BadArg = -3, dukve_OutOfBuf = -4, dukve_EOF = -5, dukve_Other = -1000, } DukVid_Error; #endif // _DUKVID_H uqm-0.6.2/sc2/src/sc2code/libs/video/videodec.c0000600000175000017500000001745310543202044017600 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "video.h" #include "videodec.h" #include "dukvid.h" #include "libs/log.h" #define MAX_REG_DECODERS 31 static bool vd_inited = false; static TFB_PixelFormat vd_vidfmt; static int vd_flags = 0; struct TFB_RegVideoDecoder { bool builtin; bool used; // ever used indicator const char* ext; const TFB_VideoDecoderFuncs* funcs; }; static TFB_RegVideoDecoder vd_decoders[MAX_REG_DECODERS + 1] = { {true, true, "duk", &dukv_DecoderVtbl}, {false, false, NULL, NULL}, // null term }; static void vd_computeMasks (uint32 mask, DWORD* shift, DWORD* loss); const char* VideoDecoder_GetName (TFB_VideoDecoder *decoder) { if (!decoder || !decoder->funcs) return "(Null)"; return decoder->funcs->GetName (); } bool VideoDecoder_Init (int flags, int depth, uint32 Rmask, uint32 Gmask, uint32 Bmask, uint32 Amask) { TFB_RegVideoDecoder* info; vd_inited = false; if (depth < 15 || depth > 32) { log_add (log_Error, "VideoDecoder_Init: " "Unsupported video depth %d", depth); return false; } if ((Rmask & Gmask) || (Rmask & Bmask) || (Rmask & Amask) || (Gmask & Bmask) || (Gmask & Amask) || (Bmask & Amask)) { log_add (log_Error, "VideoDecoder_Init: Invalid channel masks"); return false; } // BEGIN: adapted from SDL vd_vidfmt.BitsPerPixel = depth; vd_vidfmt.BytesPerPixel = (depth + 7) / 8; vd_vidfmt.Rmask = Rmask; vd_vidfmt.Gmask = Gmask; vd_vidfmt.Bmask = Bmask; vd_vidfmt.Amask = Amask; vd_computeMasks (Rmask, &vd_vidfmt.Rshift, &vd_vidfmt.Rloss); vd_computeMasks (Gmask, &vd_vidfmt.Gshift, &vd_vidfmt.Gloss); vd_computeMasks (Bmask, &vd_vidfmt.Bshift, &vd_vidfmt.Bloss); vd_computeMasks (Amask, &vd_vidfmt.Ashift, &vd_vidfmt.Aloss); // END: adapted from SDL // init built-in decoders for (info = vd_decoders; info->ext; info++) { if (!info->funcs->InitModule (flags)) { log_add (log_Error, "VideoDecoder_Init(): " "%s video decoder init failed", info->funcs->GetName ()); } } vd_flags = flags; vd_inited = true; return true; } void VideoDecoder_Uninit (void) { TFB_RegVideoDecoder* info; // uninit all decoders // and unregister loaded decoders for (info = vd_decoders; info->used; info++) { if (info->ext) // check if present info->funcs->TermModule (); if (!info->builtin) { info->used = false; info->ext = NULL; } } vd_inited = false; } TFB_RegVideoDecoder* VideoDecoder_Register (const char* fileext, TFB_VideoDecoderFuncs* decvtbl) { TFB_RegVideoDecoder* info; TFB_RegVideoDecoder* newslot = NULL; if (!decvtbl) { log_add (log_Warning, "VideoDecoder_Register(): Null decoder table"); return NULL; } if (!fileext) { log_add (log_Warning, "VideoDecoder_Register(): Bad file type for %s", decvtbl->GetName ()); return NULL; } // check if extension already registered for (info = vd_decoders; info->used && (!info->ext || strcmp (info->ext, fileext) != 0); ++info) { // and pick up an empty slot (where available) if (!newslot && !info->ext) newslot = info; } if (info >= vd_decoders + MAX_REG_DECODERS) { log_add (log_Warning, "VideoDecoder_Register(): Decoders limit reached"); return NULL; } else if (info->ext) { log_add (log_Warning, "VideoDecoder_Register(): " "'%s' decoder already registered (%s denied)", fileext, decvtbl->GetName ()); return NULL; } if (!decvtbl->InitModule (vd_flags)) { log_add (log_Warning, "VideoDecoder_Register(): %s decoder init failed", decvtbl->GetName ()); return NULL; } if (!newslot) { newslot = info; newslot->used = true; // make next one a term info[1].builtin = false; info[1].used = false; info[1].ext = NULL; } newslot->ext = fileext; newslot->funcs = decvtbl; return newslot; } void VideoDecoder_Unregister (TFB_RegVideoDecoder* regdec) { if (regdec < vd_decoders || regdec >= vd_decoders + MAX_REG_DECODERS || !regdec->ext || !regdec->funcs) { log_add (log_Warning, "VideoDecoder_Unregister(): " "Invalid or expired decoder passed"); return; } regdec->funcs->TermModule (); regdec->ext = NULL; regdec->funcs = NULL; } const TFB_VideoDecoderFuncs* VideoDecoder_Lookup (const char* fileext) { TFB_RegVideoDecoder* info; for (info = vd_decoders; info->used && (!info->ext || strcmp (info->ext, fileext) != 0); ++info) ; return info->ext ? info->funcs : NULL; } TFB_VideoDecoder* VideoDecoder_Load (uio_DirHandle *dir, const char *filename) { const char* pext; TFB_RegVideoDecoder* info; TFB_VideoDecoder* decoder; if (!vd_inited) return NULL; pext = strrchr (filename, '.'); if (!pext) { log_add (log_Warning, "VideoDecoder_Load: Unknown file type"); return NULL; } ++pext; for (info = vd_decoders; info->used && (!info->ext || strcmp (info->ext, pext) != 0); ++info) ; if (!info->ext) { log_add (log_Warning, "VideoDecoder_Load: Unsupported file type"); return NULL; } decoder = (TFB_VideoDecoder*) HCalloc (info->funcs->GetStructSize ()); decoder->funcs = info->funcs; if (!decoder->funcs->Init (decoder, &vd_vidfmt)) { log_add (log_Warning, "VideoDecoder_Load: " "Cannot init '%s' decoder, code %d", decoder->funcs->GetName (), decoder->funcs->GetError (decoder)); HFree (decoder); return NULL; } decoder->dir = dir; decoder->filename = (char *) HMalloc (strlen (filename) + 1); strcpy (decoder->filename, filename); decoder->error = VIDEODECODER_OK; if (!decoder->funcs->Open (decoder, dir, filename)) { log_add (log_Warning, "VideoDecoder_Load: " "'%s' decoder did not load %s, code %d", decoder->funcs->GetName (), filename, decoder->funcs->GetError (decoder)); VideoDecoder_Free (decoder); return NULL; } return decoder; } // return: >0 = OK, 0 = EOF, <0 = Error int VideoDecoder_Decode (TFB_VideoDecoder *decoder) { int ret; if (!decoder) return 0; decoder->cur_frame = decoder->funcs->GetFrame (decoder); decoder->pos = decoder->funcs->GetTime (decoder); ret = decoder->funcs->DecodeNext (decoder); if (ret == 0) decoder->error = VIDEODECODER_EOF; else if (ret < 0) decoder->error = VIDEODECODER_ERROR; else decoder->error = VIDEODECODER_OK; return ret; } float VideoDecoder_Seek (TFB_VideoDecoder *decoder, float pos) { if (!decoder) return 0.0; decoder->pos = decoder->funcs->SeekTime (decoder, pos); decoder->cur_frame = decoder->funcs->GetFrame (decoder); return decoder->pos; } uint32 VideoDecoder_SeekFrame (TFB_VideoDecoder *decoder, uint32 frame) { if (!decoder) return 0; decoder->cur_frame = decoder->funcs->SeekFrame (decoder, frame); decoder->pos = decoder->funcs->GetTime (decoder); return decoder->cur_frame; } void VideoDecoder_Rewind (TFB_VideoDecoder *decoder) { if (!decoder) return; VideoDecoder_Seek (decoder, 0); } void VideoDecoder_Free (TFB_VideoDecoder *decoder) { if (!decoder) return; decoder->funcs->Close (decoder); decoder->funcs->Term (decoder); HFree (decoder->filename); HFree (decoder); } // BEGIN: adapted from SDL static void vd_computeMasks (uint32 mask, DWORD* shift, DWORD* loss) { *shift = 0; *loss = 8; if (mask) { for (; !(mask & 1); mask >>= 1 ) ++*shift; for (; (mask & 1); mask >>= 1 ) --*loss; } } // END: adapted from SDL uqm-0.6.2/sc2/src/sc2code/libs/video/videodec.h0000600000175000017500000000704310543202044017577 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _VIDEODEC_H #define _VIDEODEC_H #include "vidlib.h" #include "libs/video/video.h" #include "reslib.h" // forward-declare typedef struct tfb_videodecoder TFB_VideoDecoder; #define THIS_PTR TFB_VideoDecoder* typedef struct tfb_videodecoderfunc { const char* (* GetName) (void); bool (* InitModule) (int flags); void (* TermModule) (void); uint32 (* GetStructSize) (void); int (* GetError) (THIS_PTR); bool (* Init) (THIS_PTR, TFB_PixelFormat* fmt); void (* Term) (THIS_PTR); bool (* Open) (THIS_PTR, uio_DirHandle *dir, const char *filename); void (* Close) (THIS_PTR); int (* DecodeNext) (THIS_PTR); uint32 (* SeekFrame) (THIS_PTR, uint32 frame); float (* SeekTime) (THIS_PTR, float time); uint32 (* GetFrame) (THIS_PTR); float (* GetTime) (THIS_PTR); } TFB_VideoDecoderFuncs; // decoder will call these to get info // from the player typedef struct tfb_videocallbacks { // any decoder calls this void* (* GetCanvasLine) (THIS_PTR, uint32 line); // non-audio-driven decoders call this to figure out // when the next frame should be drawn uint32 (* GetTicks) (THIS_PTR); // non-audio-driven decoders call this to inform // the player when the next frame should be drawn bool (* SetTimer) (THIS_PTR, uint32 msecs); } TFB_VideoCallbacks; #undef THIS_PTR struct tfb_videodecoder { // decoder virtual funcs - R/O const TFB_VideoDecoderFuncs *funcs; // video formats - R/O const TFB_PixelFormat *format; // decoder-set data - R/O uint32 w, h; float length; // total length in seconds uint32 frame_count; uint32 max_frame_wait; // maximum interframe delay in msecs bool audio_synced; // decoder callbacks TFB_VideoCallbacks callbacks; // other - public bool looping; void* data; // user-defined data // info - public R/O sint32 error; float pos; // position in seconds uint32 cur_frame; // semi-private uio_DirHandle *dir; char *filename; }; // return values enum { VIDEODECODER_OK, VIDEODECODER_ERROR, VIDEODECODER_EOF, }; typedef struct TFB_RegVideoDecoder TFB_RegVideoDecoder; TFB_RegVideoDecoder* VideoDecoder_Register (const char* fileext, TFB_VideoDecoderFuncs* decvtbl); void VideoDecoder_Unregister (TFB_RegVideoDecoder* regdec); const TFB_VideoDecoderFuncs* VideoDecoder_Lookup (const char* fileext); bool VideoDecoder_Init (int flags, int depth, uint32 Rmask, uint32 Gmask, uint32 Bmask, uint32 Amask); void VideoDecoder_Uninit (void); TFB_VideoDecoder* VideoDecoder_Load (uio_DirHandle *dir, const char *filename); int VideoDecoder_Decode (TFB_VideoDecoder *decoder); float VideoDecoder_Seek (TFB_VideoDecoder *decoder, float time_pos); uint32 VideoDecoder_SeekFrame (TFB_VideoDecoder *decoder, uint32 frame_pos); void VideoDecoder_Rewind (TFB_VideoDecoder *decoder); void VideoDecoder_Free (TFB_VideoDecoder *decoder); const char* VideoDecoder_GetName (TFB_VideoDecoder *decoder); #endif // _VIDEODEC_H uqm-0.6.2/sc2/src/sc2code/libs/video/Makeinfo0000600000175000017500000000010010543202044017303 0ustar joeyjoeyuqm_CFILES="vfileins.c video.c videodec.c vidplayer.c dukvid.c" uqm-0.6.2/sc2/src/sc2code/libs/video/dukvid.c0000600000175000017500000003453710543202044017306 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* DUCK video player * * Status: fully functional */ #include "video.h" #include "dukvid.h" #include #include "libs/uio.h" #include "endian_uqm.h" #define THIS_PTR TFB_VideoDecoder* This static const char* dukv_GetName (void); static bool dukv_InitModule (int flags); static void dukv_TermModule (void); static uint32 dukv_GetStructSize (void); static int dukv_GetError (THIS_PTR); static bool dukv_Init (THIS_PTR, TFB_PixelFormat* fmt); static void dukv_Term (THIS_PTR); static bool dukv_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); static void dukv_Close (THIS_PTR); static int dukv_DecodeNext (THIS_PTR); static uint32 dukv_SeekFrame (THIS_PTR, uint32 frame); static float dukv_SeekTime (THIS_PTR, float time); static uint32 dukv_GetFrame (THIS_PTR); static float dukv_GetTime (THIS_PTR); TFB_VideoDecoderFuncs dukv_DecoderVtbl = { dukv_GetName, dukv_InitModule, dukv_TermModule, dukv_GetStructSize, dukv_GetError, dukv_Init, dukv_Term, dukv_Open, dukv_Close, dukv_DecodeNext, dukv_SeekFrame, dukv_SeekTime, dukv_GetFrame, dukv_GetTime, }; typedef struct tfb_duckvideoheader { uint32 version; uint32 scrn_x_ofs; // horz screen offset in pixels uint32 scrn_y_ofs; // vert screen offset in pixels uint16 wb, hb; // width + height in blocks sint16 lumas[8]; // future luminance deltas sint16 chromas[8]; // future chrominance deltas } TFB_DuckVideoHeader; #define NUM_VEC_ITEMS 0x010 #define NUM_VECTORS 0x100 typedef struct tfb_duckvideodeltas { sint32 lumas[NUM_VECTORS][NUM_VEC_ITEMS]; sint32 chromas[NUM_VECTORS][NUM_VEC_ITEMS]; } TFB_DuckVideoDeltas; // specific video decoder struct derived from TFB_VideoDecoder // the only sane way in C one can :) typedef struct tfb_duckvideodecoder { // always the first member TFB_VideoDecoder decoder; sint32 last_error; uio_DirHandle* basedir; char* basename; uio_Stream *stream; // loaded from disk uint32* frames; uint32 cframes; uint32 iframe; uint32 version; uint32 wb, hb; // width, height in blocks // generated TFB_DuckVideoDeltas d; uint8* inbuf; uint32* decbuf; } TFB_DuckVideoDecoder; #define DUCK_GENERAL_FPS 14.622f #define DUCK_MAX_FRAME_SIZE 0x8000U #define DUCK_END_OF_SEQUENCE 1 static void dukv_DecodeFrame (uint8* src_p, uint32* dst_p, uint32 wb, uint32 hb, TFB_DuckVideoDeltas* deltas) { int iVec; int iSeq; uint32 x, y; sint32 w; uint32 *d_p0, *d_p1; int i; w = wb * 4; iVec = *(src_p++); iSeq = 0; for (y = 0; y < hb; ++y) { sint32 accum0, accum1, corr, corr0, corr1, delta; sint32 pix[4]; d_p0 = dst_p + y * w * 2; d_p1 = d_p0 + w; accum0 = 0; accum1 = 0; corr0 = 0; corr1 = 0; for (x = 0; x < wb; ++x) { if (y == 0) { pix[0] = pix[1] = pix[2] = pix[3] = 0; } else { uint32* p_p = d_p0 - w; pix[0] = p_p[0]; pix[1] = p_p[1]; pix[2] = p_p[2]; pix[3] = p_p[3]; } // start with chroma delta delta = deltas->chromas[iVec][iSeq++]; iSeq++; // correctors ignored accum0 += delta >> 1; if (delta & 1) { iVec = *(src_p++); iSeq = 0; } // line 0 for (i = 0; i < 4; ++i, ++d_p0) { delta = deltas->lumas[iVec][iSeq++]; corr = deltas->lumas[iVec][iSeq++]; accum0 += delta >> 1; corr0 ^= corr; pix[i] += accum0; pix[i] ^= corr0; if (delta & 1) { iVec = *(src_p++); iSeq = 0; } *d_p0 = pix[i]; } // line 1 for (i = 0; i < 4; ++i, ++d_p1) { delta = deltas->lumas[iVec][iSeq++]; corr = deltas->lumas[iVec][iSeq++]; accum1 += delta >> 1; corr1 ^= corr; pix[i] += accum1; pix[i] ^= corr1; if (delta & 1) { iVec = *(src_p++); iSeq = 0; } *d_p1 = pix[i]; } } } } static void dukv_DecodeFrameV3 (uint8* src_p, uint32* dst_p, uint32 wb, uint32 hb, TFB_DuckVideoDeltas* deltas) { int iVec; int iSeq; uint32 x, y; sint32 w; uint32* d_p; int i; iVec = *(src_p++); iSeq = 0; hb *= 2; w = wb * 4; for (y = 0; y < hb; ++y) { sint32 accum, delta, pix; d_p = dst_p + y * w; accum = 0; for (x = 0; x < wb; ++x) { // start with chroma delta delta = deltas->chromas[iVec][iSeq]; iSeq += 2; // correctors ignored accum += delta >> 1; if (delta & DUCK_END_OF_SEQUENCE) { iVec = *(src_p++); iSeq = 0; } for (i = 0; i < 4; ++i, ++d_p) { if (y == 0) pix = 0; else pix = d_p[-w]; // get next luma delta delta = deltas->lumas[iVec][iSeq]; iSeq += 2; // correctors ignored accum += delta >> 1; pix += accum; if (delta & DUCK_END_OF_SEQUENCE) { iVec = *(src_p++); iSeq = 0; } *d_p = pix; } } } } static bool dukv_OpenStream (TFB_DuckVideoDecoder* dukv) { char filename[280]; strcat (strcpy (filename, dukv->basename), ".duk"); return (dukv->stream = uio_fopen (dukv->basedir, filename, "rb")) != NULL; } static bool dukv_ReadFrames (TFB_DuckVideoDecoder* dukv) { char filename[280]; uint32 i; uio_Stream *fp; strcat (strcpy (filename, dukv->basename), ".frm"); if (!(fp = uio_fopen (dukv->basedir, filename, "rb"))) return false; // get number of frames uio_fseek (fp, 0, SEEK_END); dukv->cframes = uio_ftell (fp) / sizeof (uint32); uio_fseek (fp, 0, SEEK_SET); dukv->frames = (uint32*) HMalloc (dukv->cframes * sizeof (uint32)); if (uio_fread (dukv->frames, sizeof (uint32), dukv->cframes, fp) != dukv->cframes) { HFree (dukv->frames); dukv->frames = 0; return 0; } uio_fclose (fp); for (i = 0; i < dukv->cframes; ++i) dukv->frames[i] = UQM_SwapBE32 (dukv->frames[i]); return true; } static bool dukv_ReadVectors (TFB_DuckVideoDecoder* dukv, uint8* vectors) { uio_Stream *fp; char filename[280]; int ret; strcat (strcpy (filename, dukv->basename), ".tbl"); if (!(fp = uio_fopen (dukv->basedir, filename, "rb"))) return false; ret = uio_fread (vectors, NUM_VEC_ITEMS, NUM_VECTORS, fp); uio_fclose (fp); return ret == NUM_VECTORS; } static bool dukv_ReadHeader (TFB_DuckVideoDecoder* dukv, sint32* pl, sint32* pc) { uio_Stream *fp; char filename[280]; int ret; int i; TFB_DuckVideoHeader hdr; strcat (strcpy (filename, dukv->basename), ".hdr"); if (!(fp = uio_fopen (dukv->basedir, filename, "rb"))) return false; ret = uio_fread (&hdr, sizeof (hdr), 1, fp); uio_fclose (fp); if (!ret) return false; dukv->version = UQM_SwapBE32 (hdr.version); dukv->wb = UQM_SwapBE16 (hdr.wb); dukv->hb = UQM_SwapBE16 (hdr.hb); for (i = 0; i < 8; ++i) { pl[i] = (sint16) UQM_SwapBE16 (hdr.lumas[i]); pc[i] = (sint16) UQM_SwapBE16 (hdr.chromas[i]); } dukv->decoder.w = dukv->wb * 4; dukv->decoder.h = dukv->hb * 4; return true; } static sint32 dukv_make_delta (sint32* protos, bool is_chroma, int i1, int i2) { sint32 d1, d2; if (!is_chroma) { // 0x421 is (r,g,b)=(1,1,1) in 15bit pixel coding d1 = (protos[i1] >> 1) * 0x421; d2 = (protos[i2] >> 1) * 0x421; return ((d1 << 16) + d2) << 1; } else { d1 = (protos[i1] << 10) + protos[i2]; return ((d1 << 16) + d1) << 1; } } static sint32 dukv_make_corr (sint32* protos, bool is_chroma, int i1, int i2) { sint32 d1, d2; if (!is_chroma) { d1 = (protos[i1] & 1) << 15; d2 = (protos[i2] & 1) << 15; return (d1 << 16) + d2; } else { return (i1 << 3) + i2; } } static void dukv_DecodeVector (uint8* vec, sint32* p, bool is_chroma, sint32* deltas) { int citems = vec[0]; int i; for (i = 0; i < citems; i += 2, vec += 2, deltas += 2) { sint32 d = dukv_make_delta (p, is_chroma, vec[1], vec[2]); if (i == citems - 2) d |= DUCK_END_OF_SEQUENCE; deltas[0] = d; deltas[1] = dukv_make_corr (p, is_chroma, vec[1], vec[2]); } } static void dukv_InitDeltas (TFB_DuckVideoDecoder* dukv, uint8* vectors, sint32* pl, sint32* pc) { int i; for (i = 0; i < NUM_VECTORS; ++i) { uint8* vector = vectors + i * NUM_VEC_ITEMS; dukv_DecodeVector (vector, pl, false, dukv->d.lumas[i]); dukv_DecodeVector (vector, pc, true, dukv->d.chromas[i]); } } static inline uint32 dukv_PixelConv (uint16 pix, const TFB_PixelFormat* fmt) { uint32 r, g, b; r = (pix >> 7) & 0xf8; g = (pix >> 2) & 0xf8; b = (pix << 3) & 0xf8; return ((r >> fmt->Rloss) << fmt->Rshift) | ((g >> fmt->Gloss) << fmt->Gshift) | ((b >> fmt->Bloss) << fmt->Bshift); } static void dukv_RenderFrame (THIS_PTR) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; const TFB_PixelFormat* fmt = This->format; uint32 h, x, y; uint32* dec = dukv->decbuf; h = dukv->decoder.h / 2; // separate bpp versions for speed switch (fmt->BytesPerPixel) { case 2: { for (y = 0; y < h; ++y) { uint16 *dst0, *dst1; dst0 = (uint16*) This->callbacks.GetCanvasLine (This, y * 2); dst1 = (uint16*) This->callbacks.GetCanvasLine (This, y * 2 + 1); for (x = 0; x < dukv->decoder.w; ++x, ++dec, ++dst0, ++dst1) { uint32 pair = *dec; *dst0 = dukv_PixelConv ((uint16)(pair >> 16), fmt); *dst1 = dukv_PixelConv ((uint16)(pair & 0xffff), fmt); } } break; } case 3: { for (y = 0; y < h; ++y) { uint8 *dst0, *dst1; dst0 = (uint8*) This->callbacks.GetCanvasLine (This, y * 2); dst1 = (uint8*) This->callbacks.GetCanvasLine (This, y * 2 + 1); for (x = 0; x < dukv->decoder.w; ++x, ++dec, dst0 += 3, dst1 += 3) { uint32 pair = *dec; *(uint32*)dst0 = dukv_PixelConv ((uint16)(pair >> 16), fmt); *(uint32*)dst1 = dukv_PixelConv ((uint16)(pair & 0xffff), fmt); } } break; } case 4: { for (y = 0; y < h; ++y) { uint32 *dst0, *dst1; dst0 = (uint32*) This->callbacks.GetCanvasLine (This, y * 2); dst1 = (uint32*) This->callbacks.GetCanvasLine (This, y * 2 + 1); for (x = 0; x < dukv->decoder.w; ++x, ++dec, ++dst0, ++dst1) { uint32 pair = *dec; *dst0 = dukv_PixelConv ((uint16)(pair >> 16), fmt); *dst1 = dukv_PixelConv ((uint16)(pair & 0xffff), fmt); } } break; } default: ; } } static const char* dukv_GetName (void) { return "DukVid"; } static bool dukv_InitModule (int flags) { // no flags are defined for now return true; (void)flags; // dodge compiler warning } static void dukv_TermModule (void) { // do an extensive search on the word 'nothing' } static uint32 dukv_GetStructSize (void) { return sizeof (TFB_DuckVideoDecoder); } static int dukv_GetError (THIS_PTR) { return This->error; } static bool dukv_Init (THIS_PTR, TFB_PixelFormat* fmt) { This->format = fmt; This->audio_synced = true; return true; } static void dukv_Term (THIS_PTR) { //TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; dukv_Close (This); } static bool dukv_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; char* pext; sint32 lumas[8], chromas[8]; uint8* vectors; dukv->basedir = dir; dukv->basename = HMalloc (strlen (filename) + 1); strcpy (dukv->basename, filename); pext = strrchr (dukv->basename, '.'); if (pext) // strip extension *pext = 0; vectors = HMalloc (NUM_VEC_ITEMS * NUM_VECTORS); if (!dukv_OpenStream (dukv) || !dukv_ReadFrames (dukv) || !dukv_ReadHeader (dukv, lumas, chromas) || !dukv_ReadVectors (dukv, vectors)) { HFree (vectors); dukv_Close (This); dukv->last_error = dukve_BadFile; return false; } dukv_InitDeltas (dukv, vectors, lumas, chromas); HFree (vectors); This->length = (float) dukv->cframes / DUCK_GENERAL_FPS; This->frame_count = dukv->cframes; This->max_frame_wait = (uint32) (1000.0f / DUCK_GENERAL_FPS * 1.1); dukv->inbuf = HMalloc (DUCK_MAX_FRAME_SIZE); dukv->decbuf = HMalloc ( dukv->decoder.w * dukv->decoder.h * sizeof (uint16)); return true; } static void dukv_Close (THIS_PTR) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; if (dukv->basename) { HFree (dukv->basename); dukv->basename = NULL; } if (dukv->frames) { HFree (dukv->frames); dukv->frames = NULL; } if (dukv->stream) { uio_fclose (dukv->stream); dukv->stream = NULL; } if (dukv->inbuf) { HFree (dukv->inbuf); dukv->inbuf = NULL; } if (dukv->decbuf) { HFree (dukv->decbuf); dukv->decbuf = NULL; } } static int dukv_DecodeNext (THIS_PTR) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; uint32 fh[2]; uint32 vofs; uint32 vsize; uint16 ver; if (!dukv->stream || dukv->iframe >= dukv->cframes) return 0; uio_fseek (dukv->stream, dukv->frames[dukv->iframe], SEEK_SET); if (uio_fread (&fh, sizeof (fh), 1, dukv->stream) != 1) { dukv->last_error = dukve_EOF; return 0; } vofs = UQM_SwapBE32 (fh[0]); vsize = UQM_SwapBE32 (fh[1]); if (vsize > DUCK_MAX_FRAME_SIZE) { dukv->last_error = dukve_OutOfBuf; return -1; } uio_fseek (dukv->stream, vofs, SEEK_CUR); if (uio_fread (dukv->inbuf, 1, vsize, dukv->stream) != vsize) { dukv->last_error = dukve_EOF; return 0; } ver = UQM_SwapBE16 (*(uint16*)dukv->inbuf); if (ver == 0x0300) dukv_DecodeFrameV3 (dukv->inbuf + 0x10, dukv->decbuf, dukv->wb, dukv->hb, &dukv->d); else dukv_DecodeFrame (dukv->inbuf + 0x10, dukv->decbuf, dukv->wb, dukv->hb, &dukv->d); dukv->iframe++; dukv_RenderFrame (This); return 1; } static uint32 dukv_SeekFrame (THIS_PTR, uint32 frame) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; if (frame > dukv->cframes) frame = dukv->cframes; // EOS return dukv->iframe = frame; } static float dukv_SeekTime (THIS_PTR, float time) { //TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; uint32 frame = (uint32) (time * DUCK_GENERAL_FPS); return (float) dukv_SeekFrame (This, frame) / DUCK_GENERAL_FPS; } static uint32 dukv_GetFrame (THIS_PTR) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; return dukv->iframe; } static float dukv_GetTime (THIS_PTR) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; return (float) dukv->iframe / DUCK_GENERAL_FPS; } uqm-0.6.2/sc2/src/sc2code/libs/video/vidplayer.c0000600000175000017500000003127710543202044020015 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "vidplayer.h" #include "controls.h" #include "settings.h" #include "setup.h" #include "sounds.h" #include "libs/graphics/gfx_common.h" #include "libs/graphics/tfb_draw.h" #include "libs/log.h" // video callbacks static void* vp_GetCanvasLine (TFB_VideoDecoder*, uint32 line); static uint32 vp_GetTicks (TFB_VideoDecoder*); static bool vp_SetTimer (TFB_VideoDecoder*, uint32 msecs); TFB_VideoCallbacks vp_DecoderCBs = { vp_GetCanvasLine, vp_GetTicks, vp_SetTimer }; // audio stream callbacks static bool vp_AudioStart (TFB_SoundSample* sample); static void vp_AudioEnd (TFB_SoundSample* sample); static void vp_BufferTag (TFB_SoundSample* sample, TFB_SoundTag* tag); static void vp_QueueBuffer (TFB_SoundSample* sample, audio_Object buffer); static TFB_SoundCallbacks vp_AudioCBs = { vp_AudioStart, NULL, vp_AudioEnd, vp_BufferTag, vp_QueueBuffer }; // inter-thread param guarded by mutex static Semaphore vp_interthread_lock = 0; static void* vp_interthread_clip = NULL; typedef struct { // standard state required by DoInput BOOLEAN (*InputFunc) (PVOID pInputState); COUNT MenuRepeatDelay; VIDEO_REF CurVideo; } VIDEO_INPUT_STATE; bool TFB_InitVideoPlayer (void) { // creation probably needs better handling vp_interthread_lock = CreateSemaphore (1, "inter-thread param lock", SYNC_CLASS_VIDEO); return vp_interthread_lock != 0; } void TFB_UninitVideoPlayer (void) { DestroySemaphore (vp_interthread_lock); } void TFB_FadeClearScreen (void) { BYTE xform_buf[1]; RECT r = {{0, 0}, {SCREEN_WIDTH, SCREEN_HEIGHT}}; xform_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ( (COLORMAPPTR) xform_buf, ONE_SECOND / 2)); // paint black rect over screen LockMutex (GraphicsLock); SetContext (ScreenContext); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); DrawFilledRectangle (&r); UnlockMutex (GraphicsLock); // fade in black rect instantly xform_buf[0] = FadeAllToColor; XFormColorMap ((COLORMAPPTR) xform_buf, 0); } // audio-synced video playback task // the frame rate and timing is dictated by the audio static int as_video_play_task (void *data) { Task task = (Task) data; volatile TFB_VideoClip* vid; int ret; uint32 want_frame; TimeCount TimeOut; int bTerm; uint32 clagged; // snatch the clip pointer and release vid = vp_interthread_clip; vp_interthread_clip = NULL; ClearSemaphore (vp_interthread_lock); LockMutex (vid->guard); want_frame = vid->want_frame; PlayMusic (vid->hAudio, FALSE, 1); UnlockMutex (vid->guard); clagged = 0; // this works like so (audio-synced): // 1. you call VideoDecoder_Seek() [when necessary] and // VideoDecoder_Decode() // 2. wait till the audio signals it's time for this frame // or the maximum inter-frame timeout elapses; the timeout // is necessary because the audio signaling is not precise // (see vp_AudioStart, vp_AudioEnd, vp_BufferTag) // 3. output the frame; if the timeout elapsed, increment the // the lag counter // 4. set the next frame timeout; lag counter increases the // timeout to allow audio to catch up // 5. on a seek operation, the audio stream is moved to the // correct position and then the audio signals the frame // that should be rendered // The system of timeouts and lag counts should make the video // *relatively* smooth // ret = VideoDecoder_Decode (vid->decoder); TimeOut = GetTimeCounter () + vid->decoder->max_frame_wait * ONE_SECOND / 1000; while (!(bTerm = Task_ReadState (task, TASK_EXIT)) && ret > 0) { // wait till its time to render next frame while (!(bTerm = Task_ReadState (task, TASK_EXIT)) && want_frame == vid->cur_frame - clagged && TimeOut > GetTimeCounter ()) { TaskSwitch (); LockMutex (vid->guard); want_frame = vid->want_frame; UnlockMutex (vid->guard); } if (bTerm) break; if (want_frame == vid->cur_frame - clagged) { // timed out - draw the next frame ++clagged; } else if (want_frame > vid->cur_frame - clagged && want_frame <= vid->cur_frame) { // catching up clagged = vid->cur_frame - want_frame; // try again continue; } else if (want_frame != vid->cur_frame + 1) { // out of sequence frame, let's get it vid->cur_frame = VideoDecoder_SeekFrame ( vid->decoder, want_frame); ret = VideoDecoder_Decode (vid->decoder); clagged = 0; } else { clagged = 0; } vid->cur_frame = vid->decoder->cur_frame; // draw the frame if (ret > 0) { LockMutex (GraphicsLock); SetContext (ScreenContext); TFB_DrawScreen_Image (vid->frame, vid->dst_rect.corner.x, vid->dst_rect.corner.y, GSCALE_IDENTITY, NULL, TFB_SCREEN_MAIN); UnlockMutex (GraphicsLock); FlushGraphics (); // needed to prevent half-frame updates } // increase timeout with lag-count to allow audio to catch up TimeOut = GetTimeCounter () + vid->decoder->max_frame_wait * ONE_SECOND / 1000 + clagged * ONE_SECOND / 100; ret = VideoDecoder_Decode (vid->decoder); } StopMusic (); vid->playing = false; FinishTask (task); return 0; } // audio-independent video playback task // the frame rate and timing is dictated by the video decoder static int video_play_task (void *data) { Task task = (Task) data; TFB_VideoClip* vid; int ret; // snatch the clip pointer and release vid = vp_interthread_clip; vp_interthread_clip = NULL; ClearSemaphore (vp_interthread_lock); LockMutex (vid->guard); if (vid->hAudio) PlayMusic (vid->hAudio, FALSE, 1); UnlockMutex (vid->guard); // this works like so: // 1. you call VideoDecoder_Seek() [when necessary] and // VideoDecoder_Decode() // 2. the decoder calls back vp_GetTicks() and vp_SetTimer() // to figure out and tell you when to render the frame // being decoded // On a seek operation, the decoder should reset its internal // clock and call vp_GetTicks() again // ret = VideoDecoder_Decode (vid->decoder); while (!Task_ReadState (task, TASK_EXIT) && ret > 0) { // wait till its time to render next frame SleepThreadUntil (vid->frame_time); vid->cur_frame = vid->decoder->cur_frame; LockMutex (GraphicsLock); SetContext (ScreenContext); TFB_DrawScreen_Image (vid->frame, vid->dst_rect.corner.x, vid->dst_rect.corner.y, GSCALE_IDENTITY, NULL, TFB_SCREEN_MAIN); UnlockMutex (GraphicsLock); FlushGraphics (); // needed to prevent half-frame updates ret = VideoDecoder_Decode (vid->decoder); } vid->playing = false; if (vid->hAudio) StopMusic (); FinishTask (task); return 0; } bool TFB_PlayVideo (VIDEO_REF VidRef, uint32 x, uint32 y) { TFB_VideoClip* vid = (TFB_VideoClip*) VidRef; RECT scrn_r; RECT clip_r = {{0, 0}, {vid->w, vid->h}}; RECT vid_r = {{0, 0}, {SCREEN_WIDTH, SCREEN_HEIGHT}}; RECT dr = {{x, y}, {vid->w, vid->h}}; RECT sr; if (!vid) return false; // calculate the frame-source and screen-destination rects GetContextClipRect (&scrn_r); if (scrn_r.extent.width <= 0 || scrn_r.extent.height <= 0) { // bad or empty rect scrn_r = vid_r; } else if (!BoxIntersect(&scrn_r, &vid_r, &scrn_r)) return false; // drawing outside visible sr = dr; sr.corner.x = -sr.corner.x; sr.corner.y = -sr.corner.y; if (!BoxIntersect (&clip_r, &sr, &sr)) return false; // drawing outside visible dr.corner.x += scrn_r.corner.x; dr.corner.y += scrn_r.corner.y; if (!BoxIntersect (&scrn_r, &dr, &vid->dst_rect)) return false; // drawing outside visible vid->src_rect = vid->dst_rect; vid->src_rect.corner.x = sr.corner.x; vid->src_rect.corner.y = sr.corner.y; vid->decoder->callbacks = vp_DecoderCBs; vid->decoder->data = vid; vid->frame = TFB_DrawImage_CreateForScreen (vid->w, vid->h, FALSE); vid->cur_frame = -1; vid->want_frame = -1; vid->hAudio = LoadMusicFile (vid->decoder->filename); StopMusic (); if (vid->decoder->audio_synced) { TFB_SoundSample **pmus; if (!vid->hAudio) { log_add (log_Warning, "TFB_PlayVideo: " "Cannot load sound-track for audio-synced video"); return false; } // nasty hack for now LockMusicData (vid->hAudio, &pmus); (*pmus)->buffer_tag = HCalloc ( sizeof (TFB_SoundTag) * (*pmus)->num_buffers); (*pmus)->callbacks = vp_AudioCBs; (*pmus)->data = vid; // hijack data ;) UnlockMusicData (vid->hAudio); } SetSemaphore (vp_interthread_lock); vp_interthread_clip = vid; vid->playing = true; if (vid->decoder->audio_synced) vid->play_task = AssignTask ( as_video_play_task, 4096, "a/s video player"); else vid->play_task = AssignTask ( video_play_task, 4096, "video player"); if (!vid->play_task) { vid->playing = false; ClearSemaphore (vp_interthread_lock); TFB_StopVideo (VidRef); return false; } return true; } void TFB_StopVideo (VIDEO_REF VidRef) { TFB_VideoClip* vid = (TFB_VideoClip*) VidRef; if (!vid) return; vid->playing = false; if (vid->play_task) ConcludeTask (vid->play_task); if (vid->hAudio) { StopMusic (); DestroyMusic (vid->hAudio); vid->hAudio = 0; } if (vid->frame) { TFB_DrawScreen_DeleteImage (vid->frame); vid->frame = NULL; } } bool TFB_VideoPlaying (VIDEO_REF VidRef) { TFB_VideoClip* vid = (TFB_VideoClip*) VidRef; if (!vid) return false; return vid->playing; } static BOOLEAN TFB_DoVideoInput (PVOID pIS) { VIDEO_INPUT_STATE* pVIS = (VIDEO_INPUT_STATE*) pIS; TFB_VideoClip* vid = (TFB_VideoClip*) pVIS->CurVideo; if (!pVIS->CurVideo || !TFB_VideoPlaying (pVIS->CurVideo)) return FALSE; if (PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_CANCEL] || PulsedInputState.menu[KEY_MENU_SPECIAL] || (GLOBAL (CurrentActivity) & CHECK_ABORT)) { // abort movie TFB_StopVideo (pVIS->CurVideo); return FALSE; } else if (PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_RIGHT]) { if (vid->decoder->audio_synced) { float newpos; LockMutex (vid->guard); newpos = vid->decoder->pos; UnlockMutex (vid->guard); if (PulsedInputState.menu[KEY_MENU_LEFT]) newpos -= 2; else if (PulsedInputState.menu[KEY_MENU_RIGHT]) newpos += 1; if (newpos < 0) newpos = 0; LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); SeekStream (MUSIC_SOURCE, (uint32) (newpos * 1000)); UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); TaskSwitch (); } // non a/s decoder seeking is not supported yet } return TRUE; } void TFB_VideoInput (VIDEO_REF VidRef) { VIDEO_INPUT_STATE vis; vis.MenuRepeatDelay = 0; vis.InputFunc = TFB_DoVideoInput; vis.CurVideo = VidRef; SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); DoInput (&vis, TRUE); } static void* vp_GetCanvasLine (TFB_VideoDecoder* decoder, uint32 line) { TFB_VideoClip* vid = (TFB_VideoClip*) decoder->data; if (!vid) return NULL; return TFB_DrawCanvas_GetLine (vid->frame->NormalImg, line); } static uint32 vp_GetTicks (TFB_VideoDecoder* decoder) { uint32 ctr = GetTimeCounter (); return (ctr / ONE_SECOND) * 1000 + ((ctr % ONE_SECOND) * 1000) / ONE_SECOND; (void)decoder; // gobble up compiler warning } static bool vp_SetTimer (TFB_VideoDecoder* decoder, uint32 msecs) { TFB_VideoClip* vid = (TFB_VideoClip*) decoder->data; if (!vid) return false; // time when next frame should be displayed vid->frame_time = GetTimeCounter () + msecs * ONE_SECOND / 1000; return true; } static bool vp_AudioStart (TFB_SoundSample* sample) { TFB_VideoClip* vid = sample->data; LockMutex (vid->guard); vid->want_frame = SoundDecoder_GetFrame (sample->decoder); UnlockMutex (vid->guard); return true; } static void vp_AudioEnd (TFB_SoundSample* sample) { TFB_VideoClip* vid = sample->data; LockMutex (vid->guard); vid->want_frame = vid->decoder->frame_count; // end it UnlockMutex (vid->guard); } static void vp_BufferTag (TFB_SoundSample* sample, TFB_SoundTag* tag) { TFB_VideoClip* vid = sample->data; uint32 frame = (uint32) (intptr_t) tag->data; LockMutex (vid->guard); vid->want_frame = frame; // let it go! UnlockMutex (vid->guard); } static void vp_QueueBuffer (TFB_SoundSample* sample, audio_Object buffer) { //TFB_VideoClip* vid = sample->data; TFB_TagBuffer (sample, buffer, (void *) (intptr_t) SoundDecoder_GetFrame (sample->decoder)); } uqm-0.6.2/sc2/src/sc2code/libs/memlib.h0000600000175000017500000001054110543202055016153 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MEMLIB_H #define _MEMLIB_H #include "compiler.h" #define MEM_NULL 0L #define NULL_HANDLE (MEM_HANDLE)MEM_NULL typedef signed long MEM_SIZE; typedef MEM_SIZE *PMEM_SIZE; typedef long MEM_OFFS; typedef SWORD MEM_HANDLE; typedef MEM_HANDLE *PMEM_HANDLE; typedef BOOLEAN MEM_BOOL; #define MEM_FAILURE FALSE #define MEM_SUCCESS TRUE enum { SAME_MEM_USAGE = 0, MEM_SIMPLE, MEM_COMPLEX }; typedef BYTE MEM_USAGE; #define NO_MEM_USAGE (MEM_USAGE)SAME_MEM_USAGE #define DEFAULT_MEM_USAGE (MEM_USAGE)MEM_SIMPLE enum { MEM_NO_ACCESS = 0, MEM_READ_ONLY, MEM_WRITE_ONLY, MEM_READ_WRITE }; typedef BYTE MEM_ACCESS_MODE; enum { MEM_SEEK_REL, MEM_SEEK_ABS }; typedef BYTE MEM_SEEK_MODE; enum { MEM_FORWARD, MEM_BACKWARD }; typedef BYTE MEM_DIRECTION; typedef struct mem_size_request { MEM_SIZE min_size, size, max_size; MEM_DIRECTION direction; } MEM_SIZE_REQUEST; typedef MEM_SIZE_REQUEST *PMEM_SIZE_REQUEST; typedef SBYTE MEM_PRIORITY; typedef UWORD MEM_FLAGS; #define DEFAULT_MEM_FLAGS (MEM_FLAGS)0 #define SAME_MEM_FLAGS (MEM_FLAGS)0 #define MEM_CONSTRAINED (MEM_FLAGS)(1 << 2) #define MEM_DISCARDABLE (MEM_FLAGS)(1 << 3) #define MEM_NODISCARD (MEM_FLAGS)(1 << 4) #define MEM_DISCARDED (MEM_FLAGS)(1 << 5) #define MEM_ACCESSED (MEM_FLAGS)(1 << 6) #define MEM_STATIC (MEM_FLAGS)(1 << 7) #define MEM_PRIMARY (MEM_FLAGS)(1 << 8) #define MEM_ZEROINIT (MEM_FLAGS)(1 << 9) #define MEM_GRAPHICS (MEM_FLAGS)(1 << 10) #define MEM_SOUND (MEM_FLAGS)(1 << 11) #define DEFAULT_MEM_PRIORITY (MEM_PRIORITY)0 #define SAME_MEM_PRIORITY (MEM_PRIORITY)0 #define HIGHEST_MEM_PRIORITY (MEM_PRIORITY)1 #define LOWEST_MEM_PRIORITY (MEM_PRIORITY)100 typedef struct mem_header { MEM_HANDLE handle; } _ALIGNED_ANY MEM_HEADER; #define GET_MEM_HEADER(addr) ((MEM_HEADER *) \ (((char *) addr) - sizeof (MEM_HEADER))) //Newer verion from w_memlib.c to follow... /* extern MEM_BOOL mem_init (MEM_SIZE core_size, PMEM_SIZE pmin_addressable, PSTR disk_name);*/ extern MEM_BOOL mem_init (void); extern MEM_BOOL mem_uninit (void); extern MEM_HANDLE mem_allocate (MEM_SIZE size, MEM_FLAGS flags, MEM_PRIORITY priority, MEM_USAGE usage); #define mem_request(size) \ mem_allocate((MEM_SIZE)(size), DEFAULT_MEM_FLAGS, DEFAULT_MEM_PRIORITY, DEFAULT_MEM_USAGE) extern MEM_BOOL mem_release (MEM_HANDLE handle); extern MEM_HANDLE mem_reallocate (MEM_HANDLE handle, MEM_SIZE size, MEM_FLAGS flags, MEM_PRIORITY priority, MEM_USAGE usage); #define mem_resize(h, size) \ mem_reallocate(h, (MEM_SIZE)size, SAME_MEM_FLAGS, SAME_MEM_PRIORITY, SAME_MEM_USAGE) extern MEM_HANDLE mem_static (PVOID pVoid, MEM_SIZE size, MEM_USAGE usage); extern MEM_HANDLE mem_dup (MEM_HANDLE handle, MEM_USAGE usage); extern PVOID mem_simple_access (MEM_HANDLE handle); extern MEM_BOOL mem_simple_unaccess (MEM_HANDLE handle); #define mem_lock mem_simple_access #define mem_unlock mem_simple_unaccess extern PVOID mem_complex_access (MEM_HANDLE handle, MEM_SIZE pos, PMEM_SIZE_REQUEST pSizeRequest, MEM_ACCESS_MODE access_mode); extern MEM_BOOL mem_complex_unaccess (MEM_HANDLE handle); extern PVOID mem_complex_seek (MEM_HANDLE handle, MEM_OFFS offset, PMEM_SIZE_REQUEST pSizeRequest, MEM_SEEK_MODE seek_mode); extern MEM_SIZE mem_get_memavailable (MEM_SIZE size, MEM_PRIORITY priority); extern MEM_SIZE mem_get_size (MEM_HANDLE handle); extern MEM_USAGE mem_get_usage (MEM_HANDLE handle); extern MEM_BOOL mem_set_flags (MEM_HANDLE handle, MEM_FLAGS mem_flags); extern MEM_FLAGS mem_get_flags (MEM_HANDLE handle); extern MEM_BOOL mem_set_priority (MEM_HANDLE handle, MEM_PRIORITY mem_priority); extern MEM_PRIORITY mem_get_priority (MEM_HANDLE handle); #endif /* _MEMLIB_H */ uqm-0.6.2/sc2/src/sc2code/libs/log.h0000644000175000017500000000136510552135701015506 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "log/uqmlog.h" uqm-0.6.2/sc2/src/sc2code/libs/tasklib.h0000600000175000017500000000342010543202055016335 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Michael Martin, 2002-09-21 */ /* The task libraries are a set of facilities for controlling synchronous * processes. They are built on top of threads, but add the ability to * modify a "state" variable to pass messages back and forth. */ #ifndef _TASKLIB_H #define _TASKLIB_H #include "libs/threadlib.h" /* Bitmasks for setting task state. */ #define TASK_INUSE 1 #define TASK_EXIT 2 struct taskstruct { Mutex state_mutex; volatile DWORD state; // Protected by state_mutex const char *name; volatile Thread thread; }; typedef struct taskstruct *Task; extern void InitTaskSystem (void); extern void CleanupTaskSystem (void); extern Task AssignTask (ThreadFunction task_func, SDWORD Stacksize, const char *name); extern DWORD Task_SetState (Task task, DWORD state_mask); extern DWORD Task_ClearState (Task task, DWORD state_mask); extern DWORD Task_ToggleState (Task task, DWORD state_mask); extern DWORD Task_ReadState (Task task, DWORD state_mask); extern void FinishTask (Task task); extern void ConcludeTask (Task task); #endif uqm-0.6.2/sc2/src/sc2code/libs/resource/0000755000175000017500000000000010552600275016401 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/resource/mapres.c0000600000175000017500000000671710543202036020030 0ustar joeyjoey/* mapres.h, Copyright (c) 2005 Michael C. Martin */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope thta it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "libs/reslib.h" #include "alist.h" #include "stringbank.h" static alist *map = NULL; static void check_map_init (void) { if (map == NULL) { map = Alist_New (); } } void res_ClearTables (void) { if (map != NULL) { Alist_Free (map); map = NULL; } } /* Type conversion routines. */ static const char * bool2str (BOOLEAN b) { return b ? "yes" : "no"; } static const char * int2str (int i) { char buf[20]; sprintf (buf, "%d", i); return StringBank_AddOrFindString (map->bank, buf); } static int str2int (const char *s) { return atoi(s); } static BOOLEAN str2bool (const char *s) { if (!stricmp (s, "yes") || !stricmp (s, "true") || !stricmp (s, "1") ) return TRUE; return FALSE; } void res_LoadFile (uio_Stream *s) { alist *d; check_map_init (); d = Alist_New_FromFile (s); if (d) { Alist_PutAll (map, d); Alist_Free (d); } } void res_LoadFilename (uio_DirHandle *path, const char *fname) { alist *d; check_map_init (); d = Alist_New_FromFilename (path, fname); if (d) { Alist_PutAll (map, d); Alist_Free (d); } } void res_SaveFile (uio_Stream *f, const char *root) { check_map_init (); Alist_Dump (map, f, root); } void res_SaveFilename (uio_DirHandle *path, const char *fname, const char *root) { uio_Stream *f; check_map_init (); f = res_OpenResFile (path, fname, "wb"); if (f) { res_SaveFile (f, root); res_CloseResFile (f); } } BOOLEAN res_IsBoolean (const char *key) { const char *d; check_map_init (); d = res_GetString (key); if (!d) return 0; return !stricmp (d, "yes") || !stricmp (d, "no") || !stricmp (d, "true") || !stricmp (d, "false") || !stricmp (d, "0") || !stricmp (d, "1") || !stricmp (d, ""); } BOOLEAN res_IsInteger (const char *key) { const char *d; check_map_init (); d = res_GetString (key); while (*d) { if (!isdigit (*d)) return 0; d++; } return 1; } const char * res_GetString (const char *key) { check_map_init (); return Alist_GetString (map, key); } void res_PutString (const char *key, const char *value) { check_map_init (); Alist_PutString (map, key, value); } int res_GetInteger (const char *key) { check_map_init (); return str2int (res_GetString (key)); } void res_PutInteger (const char *key, int value) { check_map_init (); res_PutString (key, int2str(value)); } BOOLEAN res_GetBoolean (const char *key) { check_map_init (); return str2bool (res_GetString (key)); } void res_PutBoolean (const char *key, BOOLEAN value) { check_map_init (); res_PutString (key, bool2str(value)); } BOOLEAN res_HasKey (const char *key) { check_map_init (); return (res_GetString (key) != NULL); } uqm-0.6.2/sc2/src/sc2code/libs/resource/stringbank.c0000600000175000017500000000742610543202036020701 0ustar joeyjoey/* stringbank.c, Copyright (c) 2005 Michael C. Martin */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope thta it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "stringbank.h" typedef stringbank chunk; static stringbank * add_chunk (stringbank *bank) { stringbank *n = malloc (sizeof (stringbank)); n->len = 0; n->next = NULL; if (bank) { while (bank->next) bank = bank->next; bank->next = n; } return n; } stringbank * StringBank_Create (void) { return add_chunk (NULL); } void StringBank_Free (stringbank *bank) { if (bank) { StringBank_Free (bank->next); free (bank); } } const char * StringBank_AddString (stringbank *bank, const char *str) { unsigned int len = strlen (str) + 1; stringbank *x = bank; if (len > STRBANK_CHUNK_SIZE) return NULL; while (x) { unsigned int remaining = STRBANK_CHUNK_SIZE - x->len; if (len < remaining) { char *result = x->data + x->len; strcpy (result, str); x->len += len; return result; } x = x->next; } /* No room in any currently existing chunk */ x = add_chunk (bank); strcpy (x->data, str); x->len += len + 1; return x->data; } const char * StringBank_AddOrFindString (stringbank *bank, const char *str) { unsigned int len = strlen (str) + 1; stringbank *x = bank; if (len > STRBANK_CHUNK_SIZE) return NULL; while (x) { int i = 0; while (i < x->len) { if (!strcmp (x->data + i, str)) return x->data + i; while (x->data[i]) i++; i++; } x = x->next; } /* We didn't find it, so add it */ return StringBank_AddString (bank, str); } static char buffer[STRBANK_CHUNK_SIZE]; const char * StringBank_AddSubstring (stringbank *bank, const char *str, unsigned int n) { unsigned int len = strlen (str); if (n > len) { return StringBank_AddString (bank, str); } if (n >= STRBANK_CHUNK_SIZE) { return NULL; } strncpy (buffer, str, n); buffer[n] = '\0'; return StringBank_AddString(bank, buffer); } const char * StringBank_AddOrFindSubstring (stringbank *bank, const char *str, unsigned int n) { unsigned int len = strlen (str); if (n > len) { return StringBank_AddOrFindString (bank, str); } if (n >= STRBANK_CHUNK_SIZE) { return NULL; } strncpy (buffer, str, n); buffer[n] = '\0'; return StringBank_AddOrFindString(bank, buffer); } int SplitString (const char *s, char splitchar, int n, const char **result, stringbank *bank) { int i; const char *index = s; for (i = 0; i < n-1; i++) { const char *next; int len; next = strchr (index, splitchar); if (!next) { break; } len = next - index; result[i] = StringBank_AddOrFindSubstring (bank, index, len); index = next+1; } result[i] = StringBank_AddOrFindString (bank, index); return i+1; } #ifdef SB_DEBUG void StringBank_Dump (stringbank *bank, FILE *s) { stringbank *x = bank; while (x) { int i = 0; while (i < x->len) { fprintf (s, "\"%s\"\n", x->data + i); while (x->data[i]) i++; i++; } x = x->next; } } #endif uqm-0.6.2/sc2/src/sc2code/libs/resource/resdata.c0000600000175000017500000000201010543202036020142 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "resintrn.h" static ResourceIndex *curResourceIndex; void _set_current_index_header (ResourceIndex *newResourceIndex) { curResourceIndex = newResourceIndex; } ResourceIndex * _get_current_index_header (void) { return curResourceIndex; } uqm-0.6.2/sc2/src/sc2code/libs/resource/alist.c0000600000175000017500000001244510543202036017650 0ustar joeyjoey/* alist.c, Copyright (c) 2005 Michael C. Martin */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope thta it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "libs/reslib.h" #include "libs/log.h" #include "alist.h" alist_entry * AlistEntry_New (alist *m, const char *key, const char *value) { alist_entry *e; e = malloc (sizeof(alist_entry)); e->key = StringBank_AddOrFindString(m->bank, key); e->value = StringBank_AddOrFindString(m->bank, value); e->next = NULL; return e; } void AlistEntry_Free (alist_entry *e) { if (e == NULL) return; AlistEntry_Free (e->next); free (e); } alist * Alist_New (void) { alist *result = malloc (sizeof(alist)); result->first = NULL; result->bank = StringBank_Create (); return result; } void Alist_Free (alist *m) { if (m == NULL) return; AlistEntry_Free (m->first); StringBank_Free (m->bank); free (m); } alist_entry * Alist_GetEntry (alist *m, const char *key) { alist_entry *x = m->first; while (x != NULL) { if (!strcmp (x->key, key)) return x; x = x->next; } return NULL; } const char * Alist_GetString (alist *m, const char *key) { alist_entry *x = Alist_GetEntry (m, key); return x ? x->value : NULL; } void Alist_PutString (alist *m, const char *key, const char *value) { alist_entry *e = Alist_GetEntry (m, key); if (e == NULL) { e = AlistEntry_New(m, key, value); e->next = m->first; m->first = e; } else { e->value = StringBank_AddOrFindString(m->bank, value); } } void Alist_PutAll (alist *dst, alist *src) { alist_entry *e = src->first; while (e) { Alist_PutString (dst, StringBank_AddOrFindString(dst->bank, e->key), StringBank_AddOrFindString(dst->bank, e->value)); e = e->next; } } alist * Alist_New_FromFile (uio_Stream *f) { long flen; alist *m; char *data; flen = LengthResFile (f); data = malloc (flen + 1); if (!data) { return NULL; } flen = ReadResFile (data, 1, flen, f); data[flen] = '\0'; m = Alist_New_FromString (data); free (data); return m; } alist * Alist_New_FromFilename (uio_DirHandle *path, const char *fname) { alist *result; uio_Stream *f = res_OpenResFile (path, fname, "rt"); if (!f) { return NULL; } result = Alist_New_FromFile (f); res_CloseResFile(f); return result; } alist * Alist_New_FromString (char *d) { alist *m = Alist_New (); int len, i; if (!m) return NULL; len = strlen(d); i = 0; while (i < len) { int key_start, key_end, value_start, value_end; /* Starting a line: search for non-whitespace */ while ((i < len) && isspace (d[i])) i++; if (i >= len) break; /* Done parsing! */ /* If it was a comment, skip to end of comment/file */ if (d[i] == '#') { while ((i < len) && (d[i] != '\n')) i++; if (i >= len) break; continue; /* Back to keyword search */ } key_start = i; /* Find the = on this line */ while ((i < len) && (d[i] != '=') && (d[i] != '\n') && (d[i] != '#')) i++; if (i >= len) { /* Bare key at EOF */ log_add (log_Warning, "Warning: Bare keyword at EOF"); break; } /* Comments here mean incomplete line too */ if (d[i] != '=') { log_add (log_Warning, "Warning: Key without value"); while ((i < len) && (d[i] != '\n')) i++; if (i >= len) break; continue; /* Back to keyword search */ } /* Key ends at first whitespace before = , or at key_start*/ key_end = i; while ((key_end > key_start) && isspace (d[key_end-1])) key_end--; /* Consume the = */ i++; /* Value starts at first non-whitespace after = on line... */ while ((i < len) && (d[i] != '#') && (d[i] != '\n') && isspace (d[i])) i++; value_start = i; /* Until first non-whitespace before terminator */ while ((i < len) && (d[i] != '#') && (d[i] != '\n')) i++; value_end = i; while ((value_end > value_start) && isspace (d[value_end-1])) value_end--; /* Skip past EOL or EOF */ while ((i < len) && (d[i] != '\n')) i++; i++; /* We now have start and end values for key and value. We terminate the strings for both by writing \0s, then make a new map entry. */ d[key_end] = '\0'; d[value_end] = '\0'; Alist_PutString (m, StringBank_AddOrFindString(m->bank, d+key_start), StringBank_AddOrFindString(m->bank, d+value_start)); } return m; } void Alist_Dump (alist *m, uio_Stream *s, const char *prefix) { alist_entry *e = m->first; int prefix_len = 0; if (prefix) prefix_len = strlen (prefix); while (e) { if (!prefix || !strncmp (prefix, e->key, prefix_len)) { WriteResFile (e->key, 1, strlen (e->key), s); PutResFileChar(' ', s); PutResFileChar('=', s); PutResFileChar(' ', s); WriteResFile (e->value, 1, strlen (e->value), s); PutResFileNewline(s); } e = e->next; } return; } uqm-0.6.2/sc2/src/sc2code/libs/resource/index.h0000600000175000017500000000323210543202036017642 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _INDEX_H #define _INDEX_H #include typedef struct { RESOURCE res; char *path; MEM_HANDLE handle; //COUNT ref; } ResourceDesc; typedef struct { ResourceLoadFun *loadFun; ResourceFreeFun *freeFun; } ResourceHandlers; typedef struct { RES_TYPE numTypes; /* Number of types in the handlers array (whether NULL or not). * == the highest stored handler number + 1. */ ResourceHandlers *handlers; } ResourceTypeInfo; typedef struct { ResourceDesc **res; ResourceTypeInfo typeInfo; size_t numRes; } ResourceIndex; void forAllResourceIndices( void (*callback) (ResourceIndex *idx, void *extra), void *extra); #define INDEX_HEADER_PRIORITY DEFAULT_MEM_PRIORITY static inline ResourceIndex * lockResourceIndex (MEM_HANDLE h) { return (ResourceIndex *) mem_lock (h); } static inline void unlockResourceIndex (MEM_HANDLE h) { mem_unlock (h); } #endif /* _INDEX_H */ uqm-0.6.2/sc2/src/sc2code/libs/resource/direct.c0000644000175000017500000000533310546776500020033 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "libs/strings/strintrn.h" #include "port.h" #include "libs/uio.h" #include DIRENTRY_REF LoadDirEntryTable (uio_DirHandle *dirHandle, const char *path, const char *pattern, match_MatchType matchType, PCOUNT pnum_entries) { uio_DirList *dirList; COUNT num_entries, length; COUNT i; COUNT slen; uio_DirHandle *dir; STRING_TABLE StringTable; STRING_TABLEPTR lpST; PSTR lpStr; PDWORD lpLastOffs; dir = uio_openDirRelative (dirHandle, path, 0); assert(dir != NULL); dirList = uio_getDirList (dir, "", pattern, matchType); assert(dirList != NULL); num_entries = 0; length = 0; // First, count the amount of space needed for (i = 0; i < dirList->numNames; i++) { struct stat sb; if (dirList->names[i][0] == '.') { dirList->names[i] = NULL; continue; } if (uio_stat (dir, dirList->names[i], &sb) == -1) { dirList->names[i] = NULL; continue; } if (!S_ISREG (sb.st_mode)) { dirList->names[i] = NULL; continue; } length += strlen (dirList->names[i]) + 1; num_entries++; } uio_closeDir (dir); if (num_entries == 0) { uio_DirList_free(dirList); *pnum_entries = 0; return ((DIRENTRY_REF) 0); } slen = sizeof (STRING_TABLE_DESC) + (num_entries * sizeof (DWORD)); StringTable = AllocResourceData (slen + length, 0); LockStringTable (StringTable, &lpST); if (lpST == 0) { FreeStringTable (StringTable); uio_DirList_free(dirList); *pnum_entries = 0; return ((DIRENTRY_REF) 0); } lpST->StringCount = num_entries; lpLastOffs = &lpST->StringOffsets[0]; *lpLastOffs = slen; lpStr = (PSTR)lpST + slen; for (i = 0; i < dirList->numNames; i++) { int size; if (dirList->names[i] == NULL) continue; size = strlen (dirList->names[i]) + 1; memcpy (lpStr, dirList->names[i], size); lpLastOffs[1] = lpLastOffs[0] + size; lpLastOffs++; lpStr += size; } uio_DirList_free(dirList); *pnum_entries = num_entries; UnlockStringTable (StringTable); return ((DIRENTRY_REF) StringTable); } uqm-0.6.2/sc2/src/sc2code/libs/resource/filecntl.c0000600000175000017500000000506110543202036020330 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef WIN32 #include #endif #include #include #include #include #include "port.h" #include "resintrn.h" #include "libs/uio.h" uio_Stream * res_OpenResFile (uio_DirHandle *dir, const char *filename, const char *mode) { uio_Stream *fp; struct stat sb; if (uio_stat (dir, filename, &sb) == 0 && S_ISDIR(sb.st_mode)) return ((uio_Stream *) ~0); fp = uio_fopen (dir, filename, mode); return (fp); } BOOLEAN res_CloseResFile (uio_Stream *fp) { if (fp) { if (fp != (uio_Stream *)~0) uio_fclose (fp); return (TRUE); } return (FALSE); } BOOLEAN DeleteResFile (uio_DirHandle *dir, const char *filename) { return (uio_unlink (dir, filename) == 0); } int ReadResFile (PVOID lpBuf, COUNT size, COUNT count, uio_Stream *fp) { int retval; retval = uio_fread (lpBuf, size, count, fp); return (retval); } int WriteResFile (PCVOID lpBuf, COUNT size, COUNT count, uio_Stream *fp) { int retval; retval = uio_fwrite (lpBuf, size, count, fp); return (retval); } int GetResFileChar (uio_Stream *fp) { int retval; retval = uio_getc (fp); return (retval); } int PutResFileChar (char ch, uio_Stream *fp) { int retval; retval = uio_putc (ch, fp); return (retval); } int PutResFileNewline (uio_Stream *fp) { int retval; #ifdef WIN32 PutResFileChar ('\r', fp); #endif retval = PutResFileChar ('\n', fp); return (retval); } long SeekResFile (uio_Stream *fp, long offset, int whence) { long retval; retval = uio_fseek (fp, offset, whence); return (retval); } long TellResFile (uio_Stream *fp) { long retval; retval = uio_ftell (fp); return (retval); } long LengthResFile (uio_Stream *fp) { struct stat sb; if (fp == (uio_Stream *)~0) return (1); if (uio_fstat(uio_streamHandle(fp), &sb) == -1) return 1; return sb.st_size; } uqm-0.6.2/sc2/src/sc2code/libs/resource/resinit.c0000600000175000017500000002453310543202036020212 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "resintrn.h" #include "misc.h" #include "options.h" #include "types.h" #include "libs/list.h" #include "libs/log.h" #include #include static bool copyResTypeHandlers (ResourceIndex *dest, const ResourceIndex *src); static bool setResTypeHandlers (ResourceIndex *idx, RES_TYPE resType, const ResourceHandlers *handlers); static MEM_HANDLE allocResourceIndex(void); static void freeResourceIndex (MEM_HANDLE h); static List_List *indexList; static void initIndexList (void) { indexList = List_newList (); } static void uninitIndexList (void) { List_deleteList (indexList); indexList = NULL; } void forAllResourceIndices( void (*callback) (ResourceIndex *idx, void *extra), void *extra) { List_Link *link; for (link = indexList->first; link != NULL; link = link->next) { ResourceIndex *idx = (ResourceIndex *) link->entry; (*callback) (idx, extra); } } #if 0 static ResourceDesc * lookupResourceIndex (const char *path) { List_Link *link; for (link = indexList->first; link != NULL; link = link->next) { ResourceDesc *desc = (ResourceDesc *) link->entry; if (strcmp (desc->path, path) == 0) return link->entry; } return NULL; } #endif static ResourceDesc * newResourceDesc (RESOURCE res, char *path) { ResourceDesc *result; result = HMalloc (sizeof (ResourceDesc)); if (result == NULL) return NULL; result->res = res; result->path = path; result->handle = NULL_HANDLE; //result->ref = 0; return result; } static MEM_HANDLE loadResourceIndex (uio_Stream *stream, const char *fileName) { size_t lineNum; ResourceDesc **descs = NULL; COUNT numRes; int numDescsAlloced = 0; MEM_HANDLE indexHandle = NULL_HANDLE; ResourceIndex *ndx = NULL; #ifdef DEBUG RESOURCE lastResource = 0x00000000; #endif // This loop parses lines of the format " ". // Resnum is in hex. '#' can be used to add comments. lineNum = 0; numRes = 0; for (;;) { char lineBuf[PATH_MAX + 80]; char *ptr; char *endPtr; char *path; char *newPath; RESOURCE res; ResourceDesc *desc; if (uio_fgets (lineBuf, sizeof lineBuf, stream) == NULL) { if (uio_ferror (stream)) goto err; else break; // EOF } lineNum++; // Skip comments. ptr = strchr (lineBuf, '#'); if (ptr != NULL) *ptr = '\0'; // Omit leading whitespace. ptr = lineBuf; while (isspace (*ptr)) ptr++; // Omit trailing whitespace. endPtr = ptr + strlen(ptr); while (endPtr != ptr && isspace (endPtr[-1])) { endPtr--; *endPtr = '\0'; } // If the line is empty (apart from comments and whitespace) // go to the next one. if (*ptr == 0) continue; { unsigned int resPackage; unsigned int resInstance; unsigned int resType; unsigned int numParsed; if (sscanf (ptr, "%i %i %i %n", &resPackage, &resInstance, &resType, &numParsed) != 3) { log_add (log_Warning, "Resource index '%s': Invalid line %d.", fileName, lineNum); continue; } path = ptr + numParsed; res = MAKE_RESOURCE (resPackage, resType, resInstance); } while (isspace (*path)) path++; if (*path == '\0') { // No path supplied. log_add (log_Warning, "Resource index '%s': Invalid line %d.", fileName, lineNum); continue; } #ifdef DEBUG // We need the list to be sorted, as we binary search through it. if (res <= lastResource) { log_add (log_Fatal, "Fatal: resource index '%s' is not sorted " "on the resource number, or contains a double entry. " "Problem encountered on line %d.", fileName, lineNum); explode (); } lastResource = res; #endif #define DESC_NUM_INCREMENT 80 if (numDescsAlloced <= numRes) { // Need to enlarge the array of resource descs. ResourceDesc **newDescs = HRealloc (descs, sizeof (ResourceDesc *) * (numDescsAlloced + DESC_NUM_INCREMENT)); if (newDescs == NULL) goto err; // Original descs is untouched. descs = newDescs; numDescsAlloced += DESC_NUM_INCREMENT; } // Can't use strdup; it doesn't use HMalloc. newPath = HMalloc (endPtr - path + 1); if (newPath == NULL) goto err; strcpy (newPath, path); desc = newResourceDesc (res, newPath); if (desc == NULL) goto err; descs[numRes] = desc; numRes++; } { ResourceDesc **newDescs = HRealloc (descs, sizeof (ResourceDesc *) * numRes); if (newDescs == NULL && numRes != 0) goto err; // Original descs is untouched. descs = newDescs; } if (numRes == 0) log_add (log_Debug, "Warning: Resource index '%s' contains no valid " "entries.", fileName); indexHandle = allocResourceIndex (); if (indexHandle == NULL_HANDLE) goto err; ndx = lockResourceIndex (indexHandle); ndx->res = descs; ndx->numRes = numRes; ndx->typeInfo.numTypes = 0; ndx->typeInfo.handlers = NULL; List_add (indexList, (void *) ndx); unlockResourceIndex (indexHandle); return indexHandle; err: if (indexHandle != NULL_HANDLE) freeResourceIndex (indexHandle); HFree (descs); return NULL_HANDLE; } // Get the data associated with a resource of type RES_INDEX // (In other words, a ResourceIndex) MEM_HANDLE _GetResFileData (uio_Stream *res_fp, DWORD fileLength) { MEM_HANDLE handle; ResourceIndex *ndx; ResourceIndex *parentNdx; #if 0 ResourceDesc *desc; desc = lookupResourceIndex (_cur_resfile_name); assert(desc != NULL); if (desc->handle != NULL_HANDLE) return desc->handle; #endif handle = loadResourceIndex (res_fp, _cur_resfile_name); if (handle == NULL_HANDLE) return NULL_HANDLE; ndx = lockResourceIndex (handle); parentNdx = _get_current_index_header (); if (parentNdx != NULL) copyResTypeHandlers (ndx, parentNdx); unlockResourceIndex (handle); (void) fileLength; return handle; } BOOLEAN _ReleaseResFileData (MEM_HANDLE handle) { ResourceIndex *ndx; ndx = lockResourceIndex (handle); if (ndx->typeInfo.handlers != NULL) HFree (ndx->typeInfo.handlers); unlockResourceIndex (handle); mem_release (handle); return TRUE; } MEM_HANDLE InitResourceSystem (const char *resfile, RES_TYPE resType, BOOLEAN (*FileErrorFun) (const char *filename)) { MEM_HANDLE handle; ResourceIndex *ndx; ResourceHandlers handlers; initIndexList (); handlers.loadFun = _GetResFileData; handlers.freeFun = _ReleaseResFileData; SetResourceIndex (NULL_HANDLE); handle = loadResource (resfile, handlers.loadFun); if (handle == NULL_HANDLE) return NULL_HANDLE; ndx = lockResourceIndex (handle); setResTypeHandlers (ndx, resType, &handlers); unlockResourceIndex (handle); SetResourceIndex (handle); (void) FileErrorFun; return handle; } void UninitResourceSystem (void) { #if 0 List_Link *link; for (link = indexList->first; link != NULL; link = link->next) { ResourceIndex *ndx = (ResourceIndex *) link->entry; } #endif uninitIndexList (); SetResourceIndex (NULL_HANDLE); } MEM_HANDLE OpenResourceIndexInstance (RESOURCE res) { MEM_HANDLE hRH; hRH = res_GetResource (res); if (hRH) res_DetachResource (res); return (hRH); } // Sets the current global resource index. // This is the index res_GetResource() calls will use. MEM_HANDLE SetResourceIndex (MEM_HANDLE newIndexHandle) { static MEM_HANDLE currentIndexHandle; // NB: currentIndexHandle is locked. MEM_HANDLE oldIndexHandle; if (currentIndexHandle != NULL_HANDLE) unlockResourceIndex (currentIndexHandle); oldIndexHandle = currentIndexHandle; currentIndexHandle = newIndexHandle; if (currentIndexHandle != NULL_HANDLE) { ResourceIndex *ndx; ndx = lockResourceIndex (currentIndexHandle); _set_current_index_header (ndx); } else _set_current_index_header (NULL); return oldIndexHandle; } BOOLEAN CloseResourceIndex (MEM_HANDLE handle) { ResourceIndex *ndx; unlockResourceIndex (handle); ndx = lockResourceIndex (handle); if (ndx == _get_current_index_header ()) SetResourceIndex (NULL_HANDLE); List_remove ((void *) indexList, ndx); unlockResourceIndex (handle); _ReleaseResFileData (handle); return TRUE; } BOOLEAN InstallResTypeVectors (RES_TYPE resType, ResourceLoadFun *loadFun, ResourceFreeFun *freeFun) { ResourceHandlers handlers; handlers.loadFun = loadFun; handlers.freeFun = freeFun; setResTypeHandlers(_get_current_index_header (), resType, &handlers); return TRUE; } static bool setResTypeHandlers (ResourceIndex *idx, RES_TYPE resType, const ResourceHandlers *handlers) { if (resType >= idx->typeInfo.numTypes) { // Have to enlarge the handler array. ResourceHandlers *newHandlers = HRealloc (idx->typeInfo.handlers, (resType + 1) * sizeof (ResourceHandlers)); if (newHandlers == NULL) return false; // idx->typeInfo.handlers is untouched // Clear the space for new entries. No need to init the last one; // it's going to be used immediately. memset (&newHandlers[idx->typeInfo.numTypes], 0, (resType - idx->typeInfo.numTypes /* + 1 - 1 */) * sizeof (ResourceHandlers)); idx->typeInfo.handlers = newHandlers; idx->typeInfo.numTypes = resType + 1; } idx->typeInfo.handlers[resType] = *handlers; return true; } static bool copyResTypeHandlers (ResourceIndex *dest, const ResourceIndex *src) { assert (src != dest); if (dest->typeInfo.handlers != NULL) HFree (dest->typeInfo.handlers); dest->typeInfo.handlers = HMalloc (src->typeInfo.numTypes * sizeof (ResourceHandlers)); if (dest->typeInfo.handlers == NULL) return false; memcpy (dest->typeInfo.handlers, src->typeInfo.handlers, src->typeInfo.numTypes * sizeof (ResourceHandlers)); dest->typeInfo.numTypes = src->typeInfo.numTypes; return true; } static MEM_HANDLE allocResourceIndex (void) { return mem_allocate (sizeof (ResourceIndex), MEM_PRIMARY, INDEX_HEADER_PRIORITY, MEM_SIMPLE); } static void freeResourceIndex (MEM_HANDLE h) { mem_release (h); } uqm-0.6.2/sc2/src/sc2code/libs/resource/alist.h0000600000175000017500000000430210543202036017646 0ustar joeyjoey/* alist.h, Copyright (c) 2005 Michael C. Martin */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope thta it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ALIST_H_ #define _ALIST_H_ #include "libs/uio.h" #include "stringbank.h" /* Associative List types. */ typedef struct _alist_entry { const char *key, *value; struct _alist_entry *next; } alist_entry; typedef struct _alist_map { alist_entry *first; stringbank *bank; } alist; /* ***** alist_entry operations ***** */ /* Constructor and destructor */ alist_entry *AlistEntry_New (alist *m, const char *key, const char *value); void AlistEntry_Free (alist_entry *e); /* ***** alist operations ***** */ /* Standard constructor and destructor */ alist *Alist_New (void); void Alist_Free (alist *m); /* Specialized constructors: Parse an alist out of a stream, file, or string. It expects a bunch of key=value statements, one per line. */ alist *Alist_New_FromFile (uio_Stream *f); alist *Alist_New_FromFilename (uio_DirHandle *path, const char *fname); alist *Alist_New_FromString (char *d); /* Getting and Setting operations */ alist_entry *Alist_GetEntry (alist *m, const char *key); const char *Alist_GetString (alist *m, const char *key); void Alist_PutString (alist *m, const char *key, const char *value); void Alist_PutAll (alist *dest, alist *src); /* Dump the alist to the specified stream in a form that could be read later by the Alist_New_From* routines. Dump only keys that begin with the prefix; NULL means all keys. */ void Alist_Dump (alist *m, uio_Stream *s, const char *prefix); #endif /* _ALIST_H_ */ uqm-0.6.2/sc2/src/sc2code/libs/resource/getres.c0000600000175000017500000001204110543202036020015 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "options.h" #include "port.h" #include "resintrn.h" #include "libs/misc.h" #include "libs/log.h" const char *_cur_resfile_name; // When a file is being loaded, _cur_resfile_name is set to its name. // At other times, it is NULL. static ResourceDesc * lookupResourceDesc (ResourceIndex *idx, RESOURCE res) { // Binary search through the resources. COUNT l, h; if (idx->numRes == 0) return NULL; l = 0; h = idx->numRes; while (l + 1 != h) { COUNT m = (l + h) / 2; if (idx->res[m]->res <= res) l = m; else h = m; } if (idx->res[l]->res == res) return idx->res[l]; return NULL; } // Load every resource in a package. static void loadPackage (ResourceIndex *idx, RES_PACKAGE pkg) { COUNT i; for (i = 0; i < idx->numRes; i++) { if (GET_PACKAGE (idx->res[i]->res) != pkg) continue; if (idx->res[i]->handle != NULL_HANDLE) continue; // Already loaded loadResourceDesc (idx, idx->res[i]); } } MEM_HANDLE loadResourceDesc (ResourceIndex *idx, ResourceDesc *desc) { RES_TYPE resType = GET_TYPE (desc->res); if (resType >= idx->typeInfo.numTypes || idx->typeInfo.handlers[resType].loadFun == NULL) { log_add (log_Warning, "Warning: Unable to load '%s'; no handler " "for type %d defined.", desc->path, resType); return NULL_HANDLE; } desc->handle = loadResource (desc->path, idx->typeInfo.handlers[resType].loadFun); return desc->handle; } MEM_HANDLE loadResource(const char *path, ResourceLoadFun *loadFun) { uio_Stream *stream; long dataLen; MEM_HANDLE handle; stream = res_OpenResFile (contentDir, path, "rb"); if (stream == NULL) { log_add (log_Warning, "Warning: Can't open '%s'", path); return NULL_HANDLE; } dataLen = LengthResFile (stream); log_add (log_Info, "\t'%s' -- %lu bytes", path, dataLen); if (dataLen == 0) { log_add (log_Warning, "Warning: Trying to load empty file '%s'.", path); goto err; } _cur_resfile_name = path; handle = (*loadFun) (stream, dataLen); _cur_resfile_name = NULL; res_CloseResFile (stream); return handle; err: res_CloseResFile (stream); return NULL_HANDLE; } // Get a resource by its resource ID. // For historical reasons, if the resource is not already loaded, // the *entire* package will be (pre-)loaded. // NB. It may be better to add an extra flag to res_GetResource() to // indicate whether you really want this, or add a separate function // for preloading the entire package. MEM_HANDLE res_GetResource (RESOURCE res) { ResourceIndex *resourceIndex; ResourceDesc *desc; resourceIndex = _get_current_index_header (); desc = lookupResourceDesc (resourceIndex, res); if (desc == NULL) { log_add (log_Warning, "Trying to get undefined resource %08x", (DWORD) res); return NULL_HANDLE; } if (desc->handle != NULL_HANDLE) return desc->handle; // Load the entire package, for historical reasons. loadPackage (resourceIndex, GET_PACKAGE (res)); return desc->handle; // May still be NULL_HANDLE, if the load failed. } // NB: this function appears to be never called! void res_FreeResource (RESOURCE res) { ResourceDesc *desc; ResourceFreeFun *freeFun; ResourceIndex *idx; desc = lookupResourceDesc (_get_current_index_header(), res); if (desc == NULL) { log_add (log_Debug, "Warning: trying to free an unrecognised " "resource."); return; } if (desc->handle == NULL_HANDLE) { log_add (log_Debug, "Warning: trying to free not loaded " "resource."); return; } idx = _get_current_index_header (); freeFun = idx->typeInfo.handlers[GET_TYPE (res)].freeFun; (*freeFun) (desc->handle); desc->handle = NULL_HANDLE; } // By calling this function the caller will be responsible of unloading // the resource. If res_GetResource() get called again for this // resource, a NEW copy will be loaded, regardless of whether a detached // copy still exists. MEM_HANDLE res_DetachResource (RESOURCE res) { ResourceDesc *desc; MEM_HANDLE result; desc = lookupResourceDesc (_get_current_index_header(), res); if (desc == NULL) { log_add (log_Debug, "Warning: trying to detach from an unrecognised " "resource."); return NULL_HANDLE; } if (desc->handle == NULL_HANDLE) { log_add (log_Debug, "Warning: trying to detach from a not loaded " "resource."); return NULL_HANDLE; } result = desc->handle; desc->handle = NULL_HANDLE; return result; } uqm-0.6.2/sc2/src/sc2code/libs/resource/loadres.c0000600000175000017500000000357710543202036020173 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "resintrn.h" #include "declib.h" MEM_HANDLE GetResourceData (uio_Stream *fp, DWORD length, MEM_FLAGS mem_flags) { MEM_HANDLE RData; DECODE_REF fh; if (length == ~(DWORD)0) length = LengthResFile (fp), fh = 0; else if ((fh = copen (fp, FILE_STREAM, STREAM_READ))) cfilelength (fh, &length); else length -= sizeof (DWORD); RData = AllocResourceData (length, mem_flags); if (RData) { RESOURCE_DATAPTR RDPtr; LockResourceData (RData, &RDPtr); if (RDPtr == NULL_PTR) { FreeResourceData (RData); RData = 0; } else { COUNT num_read; do { #define READ_LENGTH 0x00007FFFL num_read = length >= READ_LENGTH ? (COUNT)READ_LENGTH : (COUNT)length; if (fh) { if (cread (RDPtr, 1, num_read, fh) != num_read) break; } else { if ((int)(ReadResFile (RDPtr, 1, num_read, fp)) != (int)num_read) break; } RDPtr = (RESOURCE_DATAPTR) ((BYTE *) RDPtr + num_read); } while (length -= num_read); UnlockResourceData (RData); if (length > 0) { FreeResourceData (RData); RData = 0; } } } cclose (fh); return (RData); } uqm-0.6.2/sc2/src/sc2code/libs/resource/resintrn.h0000600000175000017500000000222110543202036020374 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _RESINTRN_H #define _RESINTRN_H #include #include "libs/reslib.h" #include "index.h" MEM_HANDLE loadResourceDesc (ResourceIndex *idx, ResourceDesc *desc); MEM_HANDLE loadResource(const char *path, ResourceLoadFun *loadFun); void _set_current_index_header (ResourceIndex *newResourceIndex); ResourceIndex *_get_current_index_header (void); #endif /* _RESINTRN_H */ uqm-0.6.2/sc2/src/sc2code/libs/resource/Makeinfo0000600000175000017500000000015010543202036020032 0ustar joeyjoeyuqm_CFILES="alist.c direct.c filecntl.c getres.c loadres.c mapres.c resdata.c resinit.c stringbank.c" uqm-0.6.2/sc2/src/sc2code/libs/resource/stringbank.h0000600000175000017500000000420010543202036020671 0ustar joeyjoey/* stringbank.h, Copyright (c) 2005 Michael C. Martin */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope thta it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRINGBANK_H_ #define _STRINGBANK_H_ #ifdef SB_DEBUG #include #endif #define STRBANK_CHUNK_SIZE (1024 - sizeof (void *) - sizeof (int)) typedef struct _stringbank_chunk { char data[STRBANK_CHUNK_SIZE]; int len; struct _stringbank_chunk *next; } stringbank; /* Constructors and destructors */ stringbank *StringBank_Create (void); void StringBank_Free (stringbank *bank); /* Put str or n chars after str into the string bank. */ const char *StringBank_AddString (stringbank *bank, const char *str); const char *StringBank_AddSubstring (stringbank *bank, const char *str, unsigned int n); /* Put str or n chars after str into the string bank if it's not already there. Much slower. */ const char *StringBank_AddOrFindString (stringbank *bank, const char *str); const char *StringBank_AddOrFindSubstring (stringbank *bank, const char *str, unsigned int n); /* Split a string s into at most n substrings, separated by splitchar. Pointers to these substrings will be stored in result; the substrings themselves will be filed in the specified stringbank. */ int SplitString (const char *s, char splitchar, int n, const char **result, stringbank *bank); #ifdef SB_DEBUG /* Print out a list of the contents of the string bank to the named stream. */ void StringBank_Dump (stringbank *bank, FILE *s); #endif /* SB_DEBUG */ #endif /* _STRINGBANK_H_ */ uqm-0.6.2/sc2/src/sc2code/libs/reslib.h0000600000175000017500000001167010543202055016172 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _RESLIB_H #define _RESLIB_H //#include #include "port.h" #include "memlib.h" #include "libs/uio.h" typedef DWORD RESOURCE; typedef BYTE RES_TYPE; typedef COUNT RES_INSTANCE; typedef COUNT RES_PACKAGE; #define TYPE_BITS 8 #define INSTANCE_BITS 13 #define PACKAGE_BITS 11 #define GET_TYPE(res) \ ((RES_TYPE)(res) & (RES_TYPE)((1 << TYPE_BITS) - 1)) #define GET_INSTANCE(res) \ ((RES_INSTANCE)((res) >> TYPE_BITS) & ((1 << INSTANCE_BITS) - 1)) #define GET_PACKAGE(res) \ ((RES_PACKAGE)((res) >> (TYPE_BITS + INSTANCE_BITS)) & \ ((1 << PACKAGE_BITS) - 1)) #define MAKE_RESOURCE(p,t,i) \ (((RESOURCE)(p) << (TYPE_BITS + INSTANCE_BITS)) | \ ((RESOURCE)(i) << TYPE_BITS) | \ ((RESOURCE)(t))) extern const char *_cur_resfile_name; typedef MEM_HANDLE (ResourceLoadFun) (uio_Stream *fp, DWORD len); typedef BOOLEAN (ResourceFreeFun) (MEM_HANDLE handle); extern uio_Stream *res_OpenResFile (uio_DirHandle *dir, const char *filename, const char *mode); extern int ReadResFile (PVOID lpBuf, COUNT size, COUNT count, uio_Stream *fp); extern int WriteResFile (PCVOID lpBuf, COUNT size, COUNT count, uio_Stream *fp); extern int GetResFileChar (uio_Stream *fp); extern int PutResFileChar (char ch, uio_Stream *fp); extern int PutResFileNewline (uio_Stream *fp); extern long SeekResFile (uio_Stream *fp, long offset, int whence); extern long TellResFile (uio_Stream *fp); extern long LengthResFile (uio_Stream *fp); extern BOOLEAN res_CloseResFile (uio_Stream *fp); extern BOOLEAN DeleteResFile (uio_DirHandle *dir, const char *filename); extern MEM_HANDLE InitResourceSystem (const char *resfile, RES_TYPE resType, BOOLEAN (*FileErrorFun) (const char *filename)); extern void UninitResourceSystem (void); extern BOOLEAN InstallResTypeVectors (RES_TYPE res_type, ResourceLoadFun *loadFun, ResourceFreeFun *freeFun); extern MEM_HANDLE res_GetResource (RESOURCE res); extern MEM_HANDLE res_DetachResource (RESOURCE res); extern BOOLEAN FreeResource (RESOURCE res); extern COUNT CountResourceTypes (void); extern MEM_HANDLE OpenResourceIndexFile (const char *resfile); extern MEM_HANDLE OpenResourceIndexInstance (RESOURCE res); extern MEM_HANDLE SetResourceIndex (MEM_HANDLE newIndexHandle); extern BOOLEAN CloseResourceIndex (MEM_HANDLE newIndexHandle); extern MEM_HANDLE GetResourceData (uio_Stream *fp, DWORD length, MEM_FLAGS mem_flags); #define RESOURCE_PRIORITY DEFAULT_MEM_PRIORITY #define RESOURCE_DATAPTR PBYTE #define AllocResourceData(s,mf) \ mem_allocate ((MEM_SIZE)(s), (mf), RESOURCE_PRIORITY, MEM_SIMPLE) #define LockResourceData(h,lp) \ do \ { \ *(lp) = mem_lock ((MEM_HANDLE)(h)); \ } while (0) #define UnlockResourceData mem_unlock #define FreeResourceData mem_release #include "strlib.h" typedef STRING_TABLE DIRENTRY_REF; typedef STRING DIRENTRY; typedef STRINGPTR DIRENTRYPTR; extern DIRENTRY_REF LoadDirEntryTable (uio_DirHandle *dirHandle, const char *path, const char *pattern, match_MatchType matchType, PCOUNT pnum_entries); #define CaptureDirEntryTable CaptureStringTable #define ReleaseDirEntryTable ReleaseStringTable #define DestroyDirEntryTable DestroyStringTable #define GetDirEntryTableRef GetStringTable #define GetDirEntryTableCount GetStringTableCount #define GetDirEntryTableIndex GetStringTableIndex #define SetAbsDirEntryTableIndex SetAbsStringTableIndex #define SetRelDirEntryTableIndex SetRelStringTableIndex #define GetDirEntryLength GetStringLengthBin #define GetDirEntryAddress GetStringAddress #define GetDirEntryContents GetStringContents /* Key-Value resources */ void res_ClearTables (void); void res_LoadFilename (uio_DirHandle *path, const char *fname); void res_SaveFilename (uio_DirHandle *path, const char *fname, const char *root); void res_LoadFile (uio_Stream *fname); void res_SaveFile (uio_Stream *fname, const char *root); BOOLEAN res_HasKey (const char *key); const char *res_GetString (const char *key); void res_PutString (const char *key, const char *value); BOOLEAN res_IsInteger (const char *key); int res_GetInteger (const char *key); void res_PutInteger (const char *key, int value); BOOLEAN res_IsBoolean (const char *key); BOOLEAN res_GetBoolean (const char *key); void res_PutBoolean (const char *key, BOOLEAN value); #endif /* _RESLIB_H */ uqm-0.6.2/sc2/src/sc2code/libs/list/0000755000175000017500000000000010552600274015524 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/list/list.h0000600000175000017500000000407010543202044016632 0ustar joeyjoey/* * Copyright (C) 2005 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ // The 'already included' check must be done slightly more complicated // than usually. This file may be included directly only once, // but it may be included my derivative List definitions that use // this file as a template more than once. #if !defined(_LIST_H) || defined(LIST_GENERIC) #if defined(LIST_) # define LIST_GENERIC #endif #include "types.h" #include "port.h" // You can use inline lists, by using this file as a template. // To do this, make a new .h and .c file. In the .h file, define the macros // (and typedefs) from the LIST_ block below. // In the .c file, #define LIST_INTERNAL, #include the .h file // and list.c (in this order), and add the necessary functions. #ifndef LIST_ # define LIST_(identifier) List ## _ ## identifier typedef void *List_Entry; #endif typedef struct LIST_(List) LIST_(List); typedef struct LIST_(Link) LIST_(Link); struct LIST_(Link) { LIST_(Entry) entry; LIST_(Link) *next; }; struct LIST_(List) { LIST_(Link) *first; LIST_(Link) **end; }; LIST_(List) *LIST_(newList)(void); void LIST_(deleteList)(LIST_(List) *list); void LIST_(add)(LIST_(List) *list, LIST_(Entry) entry); void LIST_(remove)(LIST_(List) *list, LIST_(Entry) entry); #ifndef LIST_INTERNAL # undef LIST_ #endif #endif /* !defined(_LIST_H) || defined(LIST_GENERIC) */ uqm-0.6.2/sc2/src/sc2code/libs/list/list.c0000600000175000017500000000555610543202044016637 0ustar joeyjoey/* * Copyright (C) 2005 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef LIST_INTERNAL // If list is already defined, this file is included // as a template. In this case list.h has already been included. # define LIST_INTERNAL # include "list.h" #endif #include "misc.h" #define malloc HMalloc #define free HFree #define realloc HRealloc #include static inline LIST_(List) *LIST_(allocList)(void); static inline void LIST_(freeList)(LIST_(List) *list); static inline LIST_(Link) * LIST_(allocLink)(void); static inline void LIST_(freeLink)(LIST_(Link) *link); LIST_(List) * LIST_(newList)(void) { LIST_(List) *list; list = LIST_(allocList)(); if (list == NULL) return NULL; list->first = NULL; list->end = &list->first; return list; } void LIST_(deleteList)(LIST_(List) *list) { LIST_(Link) *link; LIST_(Link) *next; for (link = list->first; link != NULL; link = next) { next = link->next; LIST_(freeLink)(link); } LIST_(freeList)(list); } void LIST_(add)(LIST_(List) *list, LIST_(Entry) entry) { LIST_(Link) *link; link = LIST_(allocLink)(); link->entry = entry; link->next = NULL; *list->end = link; list->end = &link->next; } static inline LIST_(Link) ** LIST_(findLink)(LIST_(List) *list, LIST_(Entry) entry) { LIST_(Link) **linkPtr; for (linkPtr = &list->first; *linkPtr != NULL; linkPtr = &(*linkPtr)->next) { if ((*linkPtr)->entry == entry) return linkPtr; } return NULL; } static inline void LIST_(removeLink)(LIST_(List) *list, LIST_(Link) **linkPtr) { LIST_(Link) *link = *linkPtr; *linkPtr = link->next; if (&link->next == list->end) list->end = linkPtr; LIST_(freeLink)(link); } void LIST_(remove)(LIST_(List) *list, LIST_(Entry) entry) { LIST_(Link) **linkPtr; linkPtr = LIST_(findLink)(list, entry); assert(linkPtr != NULL); LIST_(removeLink)(list, linkPtr); } static inline LIST_(List) * LIST_(allocList)(void) { return malloc(sizeof (LIST_(List))); } static inline void LIST_(freeList)(LIST_(List) *list) { free(list); } static inline LIST_(Link) * LIST_(allocLink)(void) { return malloc(sizeof (LIST_(Link))); } static inline void LIST_(freeLink)(LIST_(Link) *link) { free(link); } uqm-0.6.2/sc2/src/sc2code/libs/list/Makeinfo0000600000175000017500000000002410543202044017155 0ustar joeyjoeyuqm_CFILES="list.c" uqm-0.6.2/sc2/src/sc2code/libs/compiler.h0000600000175000017500000000611410543202055016521 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _COMPILER_H #define _COMPILER_H #include "types.h" typedef uint8 BYTE; typedef BYTE *PBYTE; typedef uint8 UBYTE; typedef UBYTE *PUBYTE; typedef sint8 SBYTE; typedef SBYTE *PSBYTE; typedef uint16 UWORD; typedef UWORD *PUWORD; typedef sint16 SWORD; typedef SWORD *PSWORD; typedef uint32 DWORD; typedef DWORD *PDWORD; typedef sint32 SDWORD; typedef SDWORD *PSDWORD; typedef SBYTE *PSTR; typedef void *PVOID; typedef const void *PCVOID; typedef UWORD COUNT; typedef COUNT *PCOUNT; typedef SWORD SIZE; typedef SIZE *PSIZE; typedef unsigned char UNICODE; #define NULL_PTR 0L typedef enum { FALSE = 0, TRUE } BOOLEAN; typedef BOOLEAN *PBOOLEAN; typedef void (*PVOIDFUNC) (void); typedef BOOLEAN (*PBOOLFUNC) (void); typedef BYTE (*PBYTEFUNC) (void); typedef UWORD (*PUWORDFUNC) (void); typedef SWORD (*PSWORDFUNC) (void); typedef DWORD (*PDWORDFUNC) (void); #define MAKE_BYTE(lo, hi) ((BYTE) (((BYTE) (hi) << (BYTE) 4) | (BYTE) (lo))) #define LONIBBLE(x) ((BYTE) ((BYTE) (x) & (BYTE) 0x0F)) #define HINIBBLE(x) ((BYTE) ((BYTE) (x) >> (BYTE) 4)) #define MAKE_WORD(lo, hi) ((UWORD) ((BYTE) (hi) << 8) | (BYTE) (lo)) #define LOBYTE(x) ((BYTE) ((UWORD) (x))) #define HIBYTE(x) ((BYTE) ((UWORD) (x) >> 8)) #define MAKE_DWORD(lo, hi) (((DWORD) (hi) << 16) | (UWORD) (lo)) #define LOWORD(x) ((UWORD) ((DWORD) (x))) #define HIWORD(x) ((UWORD) ((DWORD) (x) >> 16)) // To be moved to port.h: // _ALIGNED_ANY specifies an alignment suitable for any type // _ALIGNED_ON specifies a caller-supplied alignment (should be a power of 2) #if defined(__GNUC__) # define _PACKED __attribute__((packed)) # define _ALIGNED_ANY __attribute__((aligned)) # define _ALIGNED_ON(bytes) __attribute__((aligned(bytes))) #elif defined(_MSC_VER) # define _ALIGNED_ANY //# define _ALIGNED_ON(bytes) __declspec(align(bytes)) // __declspec(align(bytes)) expects a constant. 'sizeof (type)' // will not do. This is something that needs some attention, // once we find someone with a 64 bits Windows machine. // Leaving it alone for now. # define _PACKED # define _ALIGNED_ON(bytes) #endif #endif /* _COMPILER_H */ uqm-0.6.2/sc2/src/sc2code/libs/alarm.h0000600000175000017500000000003510543202055015777 0ustar joeyjoey#include "callback/alarm.h" uqm-0.6.2/sc2/src/sc2code/libs/sndlib.h0000600000175000017500000000710210543202055016160 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SNDLIB_H #define _SNDLIB_H #include "strlib.h" #include "memlib.h" typedef STRING_TABLE SOUND_REF; typedef STRING SOUND; typedef STRINGPTR SOUNDPTR; typedef struct soundposition { BOOLEAN positional; int x, y; } SoundPosition; #define InitSoundResources InitStringTableResources #define CaptureSound CaptureStringTable #define ReleaseSound ReleaseStringTable #define GetSoundRef GetStringTable #define GetSoundCount GetStringTableCount #define GetSoundIndex GetStringTableIndex #define SetAbsSoundIndex SetAbsStringTableIndex #define SetRelSoundIndex SetRelStringTableIndex #define GetSoundAddress GetStringAddress #define GetSoundContents GetStringContents typedef MEM_HANDLE MUSIC_REF; extern BOOLEAN InitSound (int argc, char *argv[]); extern void UninitSound (void); extern SOUND_REF LoadSoundFile (PVOID pStr); extern MUSIC_REF LoadMusicFile (PVOID pStr); extern BOOLEAN InstallAudioResTypes (COUNT sound_type, COUNT music_type); extern SOUND_REF LoadSoundInstance (DWORD res); extern MUSIC_REF LoadMusicInstance (DWORD res); extern BOOLEAN DestroySound (SOUND_REF SoundRef); extern BOOLEAN DestroyMusic (MUSIC_REF MusicRef); #define MAX_CHANNELS 8 #define MAX_VOLUME 255 #define NORMAL_VOLUME 160 #define FIRST_SFX_CHANNEL 0 #define MIN_FX_CHANNEL 1 #define NUM_FX_CHANNELS 4 #define LAST_SFX_CHANNEL (MIN_FX_CHANNEL + NUM_FX_CHANNELS - 1) #define NUM_SFX_CHANNELS (MIN_FX_CHANNEL + NUM_FX_CHANNELS) extern void PLRPlaySong (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority); extern void PLRStop (MUSIC_REF MusicRef); extern BOOLEAN PLRPlaying (MUSIC_REF MusicRef); extern void PLRPause (MUSIC_REF MusicRef); extern void PLRResume (MUSIC_REF MusicRef); extern void PlayChannel (COUNT channel, PVOID sample, SoundPosition pos, void *positional_object, unsigned char priority); extern BOOLEAN ChannelPlaying (COUNT Channel); extern void * GetPositionalObject (COUNT channel); extern void SetPositionalObject (COUNT channel, void *positional_object); extern void UpdateSoundPosition (COUNT channel, SoundPosition pos); extern void StopChannel (COUNT Channel, BYTE Priority); extern void SetMusicVolume (COUNT Volume); extern void SetChannelVolume (COUNT Channel, COUNT Volume, BYTE Priority); extern void SetChannelRate (COUNT Channel, DWORD Rate, BYTE Priority); extern void StopSound (void); extern BOOLEAN SoundPlaying (void); extern void WaitForSoundEnd (COUNT Channel); #define TFBSOUND_WAIT_ALL ((COUNT)~0) extern BOOLEAN AllocHardwareSample (PBYTE lpSnd, DWORD SampleRate, COUNT SampleLength, COUNT LoopBegin, COUNT LoopLen); extern BOOLEAN FreeHardwareSample (PBYTE lpSnd, COUNT SampleLength); extern COUNT GetSampleRate (SOUND Sound); extern COUNT GetSampleLength (SOUND Sound); extern PBYTE GetSampleAddress (SOUND Sound); extern DWORD FadeMusic (BYTE end_vol, SIZE TimeInterval); #endif /* _SNDLIB_H */ uqm-0.6.2/sc2/src/sc2code/libs/threads/0000755000175000017500000000000010552600274016203 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/threads/thrcommon.h0000600000175000017500000000164110543202042020343 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Serge van den Boom, 2002-09-12 */ #ifndef _THRCOMMON_H #define _THRCOMMON_H #if THREADLIB == SDL #include "sdl/sdlthreads.h" #endif /* THREADLIB == SDL */ #endif /* _THR_COMMON_H */ uqm-0.6.2/sc2/src/sc2code/libs/threads/Makeinfo0000600000175000017500000000005310543202042017634 0ustar joeyjoeyuqm_SUBDIRS="sdl" uqm_CFILES="thrcommon.c" uqm-0.6.2/sc2/src/sc2code/libs/threads/thrcommon.c0000600000175000017500000001634610543202042020346 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Serge van den Boom, 2002-09-12 */ #include #include #include "libs/threadlib.h" #include "libs/timelib.h" #include "libs/misc.h" #include "libs/log.h" #include "thrcommon.h" #define LIFECYCLE_SIZE 8 typedef struct { ThreadFunction func; void *data; SDWORD stackSize; Semaphore sem; Thread value; #ifdef NAMED_SYNCHRO const char *name; #endif } SpawnRequest_struct; typedef SpawnRequest_struct *SpawnRequest; static Mutex lifecycleMutex; static SpawnRequest pendingBirth[LIFECYCLE_SIZE]; static Thread pendingDeath[LIFECYCLE_SIZE]; void InitThreadSystem (void) { int i; NativeInitThreadSystem (); for (i = 0; i < LIFECYCLE_SIZE; i++) { pendingBirth[i] = NULL; pendingDeath[i] = NULL; } lifecycleMutex = CreateMutex ("Thread Lifecycle Mutex", SYNC_CLASS_RESOURCE); } void UnInitThreadSystem (void) { NativeUnInitThreadSystem (); DestroyMutex (lifecycleMutex); } static Thread FlagStartThread (SpawnRequest s) { int i; LockMutex (lifecycleMutex); for (i = 0; i < LIFECYCLE_SIZE; i++) { if (pendingBirth[i] == NULL) { pendingBirth[i] = s; UnlockMutex (lifecycleMutex); if (s->sem) { Thread result; SetSemaphore (s->sem); DestroySemaphore (s->sem); result = s->value; HFree (s); return result; } return NULL; } } log_add (log_Fatal, "Thread Lifecycle array filled. This is a fatal error! Make LIFECYCLE_SIZE something larger than %d.", LIFECYCLE_SIZE); exit (EXIT_FAILURE); } void FinishThread (Thread thread) { int i; LockMutex (lifecycleMutex); for (i = 0; i < LIFECYCLE_SIZE; i++) { if (pendingDeath[i] == NULL) { pendingDeath[i] = thread; UnlockMutex (lifecycleMutex); return; } } log_add (log_Fatal, "Thread Lifecycle array filled. This is a fatal error! Make LIFECYCLE_SIZE something larger than %d.", LIFECYCLE_SIZE); exit (EXIT_FAILURE); } /* Only call from main thread! */ void ProcessThreadLifecycles (void) { int i; LockMutex (lifecycleMutex); for (i = 0; i < LIFECYCLE_SIZE; i++) { SpawnRequest s = pendingBirth[i]; if (s != NULL) { #ifdef NAMED_SYNCHRO s->value = NativeCreateThread (s->func, s->data, s->stackSize, s->name); #else s->value = NativeCreateThread (s->func, s->data, s->stackSize); #endif if (s->sem) { ClearSemaphore (s->sem); /* The spawning thread's FlagStartThread will clean up s */ } else { /* The thread value has been lost to the game logic. We must clean up s ourself. */ HFree (s); } pendingBirth[i] = NULL; } } for (i = 0; i < LIFECYCLE_SIZE; i++) { Thread t = pendingDeath[i]; if (t != NULL) { WaitThread (t, NULL); pendingDeath[i] = NULL; DestroyThread (t); } } UnlockMutex (lifecycleMutex); } /* The Create routines look different based on whether NAMED_SYNCHRO is defined or not. */ #ifdef NAMED_SYNCHRO Thread CreateThread_Core (ThreadFunction func, void *data, SDWORD stackSize, const char *name) { SpawnRequest s = HMalloc(sizeof (SpawnRequest_struct)); s->func = func; s->data = data; s->stackSize = stackSize; s->name = name; s->sem = CreateSemaphore (0, "SpawnRequest semaphore", SYNC_CLASS_RESOURCE); return FlagStartThread (s); } void StartThread_Core (ThreadFunction func, void *data, SDWORD stackSize, const char *name) { SpawnRequest s = HMalloc(sizeof (SpawnRequest_struct)); s->func = func; s->data = data; s->stackSize = stackSize; s->name = name; s->sem = NULL; FlagStartThread (s); } Mutex CreateMutex_Core (const char *name, DWORD syncClass) { return NativeCreateMutex (name, syncClass); } Semaphore CreateSemaphore_Core (DWORD initial, const char *name, DWORD syncClass) { return NativeCreateSemaphore (initial, name, syncClass); } RecursiveMutex CreateRecursiveMutex_Core (const char *name, DWORD syncClass) { return NativeCreateRecursiveMutex (name, syncClass); } CondVar CreateCondVar_Core (const char *name, DWORD syncClass) { return NativeCreateCondVar (name, syncClass); } #else /* These are the versions of Create* without the names. */ Thread CreateThread_Core (ThreadFunction func, void *data, SDWORD stackSize) { SpawnRequest s = HMalloc(sizeof (SpawnRequest_struct)); s->func = func; s->data = data; s->stackSize = stackSize; s->sem = CreateSemaphore (0, "SpawnRequest semaphore", SYNC_CLASS_RESOURCE); return FlagStartThread (s); } void StartThread_Core (ThreadFunction func, void *data, SDWORD stackSize) { SpawnRequest s = HMalloc(sizeof (SpawnRequest_struct)); s->func = func; s->data = data; s->stackSize = stackSize; s->sem = NULL; FlagStartThread (s); } Mutex CreateMutex_Core (void) { return NativeCreateMutex (); } Semaphore CreateSemaphore_Core (DWORD initial) { return NativeCreateSemaphore (initial); } RecursiveMutex CreateRecursiveMutex_Core (void) { return NativeCreateRecursiveMutex (); } CondVar CreateCondVar_Core (void) { return NativeCreateCondVar (); } #endif void DestroyThread (Thread t) { NativeDestroyThread (t); } ThreadLocal * CreateThreadLocal (void) { ThreadLocal *tl = HMalloc (sizeof (ThreadLocal)); tl->flushSem = CreateSemaphore (0, "FlushGraphics", SYNC_CLASS_VIDEO); return tl; } void DestroyThreadLocal (ThreadLocal *tl) { DestroySemaphore (tl->flushSem); HFree (tl); } ThreadLocal * GetMyThreadLocal (void) { return NativeGetMyThreadLocal (); } void WaitThread (Thread thread, int *status) { NativeWaitThread (thread, status); } void SleepThread (TimePeriod timePeriod) { NativeSleepThread (timePeriod); } void SleepThreadUntil (TimeCount wakeTime) { NativeSleepThreadUntil (wakeTime); } void TaskSwitch (void) { NativeTaskSwitch (); } void DestroyMutex (Mutex sem) { NativeDestroyMutex (sem); } void LockMutex (Mutex sem) { NativeLockMutex (sem); } void UnlockMutex (Mutex sem) { NativeUnlockMutex (sem); } void DestroySemaphore (Semaphore sem) { NativeDestroySemaphore (sem); } void SetSemaphore (Semaphore sem) { NativeSetSemaphore (sem); } void ClearSemaphore (Semaphore sem) { NativeClearSemaphore (sem); } void DestroyCondVar (CondVar cv) { NativeDestroyCondVar (cv); } void WaitCondVar (CondVar cv) { NativeWaitCondVar (cv); } void SignalCondVar (CondVar cv) { NativeSignalCondVar (cv); } void BroadcastCondVar (CondVar cv) { NativeBroadcastCondVar (cv); } void DestroyRecursiveMutex (RecursiveMutex mutex) { NativeDestroyRecursiveMutex (mutex); } void LockRecursiveMutex (RecursiveMutex mutex) { NativeLockRecursiveMutex (mutex); } void UnlockRecursiveMutex (RecursiveMutex mutex) { NativeUnlockRecursiveMutex (mutex); } int GetRecursiveMutexDepth (RecursiveMutex mutex) { return NativeGetRecursiveMutexDepth (mutex); } uqm-0.6.2/sc2/src/sc2code/libs/threads/sdl/0000755000175000017500000000000010552600274016765 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/threads/sdl/sdlthreads.c0000600000175000017500000003471710543202042021261 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Serge van den Boom */ #include #include "misc.h" #include "sdlthreads.h" #ifdef PROFILE_THREADS #include #include #endif #include "libs/log.h" #if defined(PROFILE_THREADS) && !defined(WIN32) #include #include #endif typedef struct _thread { void *native; #ifdef NAMED_SYNCHRO const char *name; #endif #ifdef PROFILE_THREADS int startTime; #endif /* PROFILE_THREADS */ ThreadLocal *localData; struct _thread *next; } *TrueThread; static volatile TrueThread threadQueue = NULL; static SDL_mutex *threadQueueMutex; struct ThreadStartInfo { ThreadFunction func; void *data; SDL_sem *sem; TrueThread thread; }; #ifdef PROFILE_THREADS static void SigUSR1Handler (int signr) { if (getpgrp () != getpid ()) { // Only act for the main process return; } PrintThreadsStats (); // It's not a good idea in general to do many things in a signal // handler, (and especially the locking) but I guess it will // have to do for now (and it's only for debugging). (void) signr; /* Satisfying compiler (unused parameter) */ } static void LocalStats (SDL_Thread *thread) { #if defined (WIN32) || !defined(SDL_PTHREADS) fprintf (stderr, "Thread ID %u\n", SDL_GetThreadID (thread)); #else /* !defined (WIN32) && defined(SDL_PTHREADS) */ // This only works if SDL implements threads as processes pid_t pid; struct rusage ru; long seconds; pid = (pid_t) SDL_GetThreadID (thread); fprintf (stderr, "Pid %d\n", (int) pid); getrusage(RUSAGE_SELF, &ru); seconds = ru.ru_utime.tv_sec + ru.ru_utime.tv_sec; fprintf (stderr, "Used %ld.%ld minutes of processor time.\n", seconds / 60, seconds % 60); #endif /* defined (WIN32) && defined(SDL_PTHREADS) */ } void PrintThreadsStats_SDL (void) { TrueThread ptr; int now; now = GetTimeCounter (); SDL_mutexP (threadQueueMutex); fprintf(stderr, "--- Active threads ---\n"); for (ptr = threadQueue; ptr != NULL; ptr = ptr->next) { fprintf (stderr, "Thread named '%s'.\n", ptr->name); fprintf (stderr, "Started %d.%d minutes ago.\n", (now - ptr->startTime) / 60000, ((now - ptr->startTime) / 1000) % 60); LocalStats (ptr->native); if (ptr->next != NULL) fprintf(stderr, "\n"); } SDL_mutexV (threadQueueMutex); fprintf(stderr, "----------------------\n"); fflush (stderr); } #endif /* PROFILE_THREADS */ void InitThreadSystem_SDL (void) { threadQueueMutex = SDL_CreateMutex (); #ifdef PROFILE_THREADS signal(SIGUSR1, SigUSR1Handler); #endif } void UnInitThreadSystem_SDL (void) { #ifdef PROFILE_THREADS signal(SIGUSR1, SIG_DFL); #endif SDL_DestroyMutex (threadQueueMutex); } static void QueueThread (TrueThread thread) { SDL_mutexP (threadQueueMutex); thread->next = threadQueue; threadQueue = thread; SDL_mutexV (threadQueueMutex); } static void UnQueueThread (TrueThread thread) { volatile TrueThread *ptr; ptr = &threadQueue; SDL_mutexP (threadQueueMutex); while (*ptr != thread) { #ifdef DEBUG_THREADS if (*ptr == NULL) { // Should not happen. log_add (log_Debug, "Error: Trying to remove non-present thread " "from thread queue."); fflush (stderr); explode (); } #endif /* DEBUG_THREADS */ ptr = &(*ptr)->next; } *ptr = (*ptr)->next; SDL_mutexV (threadQueueMutex); } static TrueThread FindThreadInfo (Uint32 threadID) { TrueThread ptr; ptr = threadQueue; SDL_mutexP (threadQueueMutex); while (ptr) { if (SDL_GetThreadID (ptr->native) == threadID) { SDL_mutexV (threadQueueMutex); return ptr; } ptr = ptr->next; } SDL_mutexV (threadQueueMutex); return NULL; } #ifdef NAMED_SYNCHRO static const char * MyThreadName (void) { TrueThread t = FindThreadInfo (SDL_ThreadID ()); return t ? t->name : "Unknown (probably renderer)"; } #endif static int ThreadHelper (void *startInfo) { ThreadFunction func; void *data; SDL_sem *sem; TrueThread thread; int result; func = ((struct ThreadStartInfo *) startInfo)->func; data = ((struct ThreadStartInfo *) startInfo)->data; sem = ((struct ThreadStartInfo *) startInfo)->sem; // Wait until the Thread structure is available. SDL_SemWait (sem); SDL_DestroySemaphore (sem); thread = ((struct ThreadStartInfo *) startInfo)->thread; HFree (startInfo); result = (*func) (data); #ifdef DEBUG_THREADS log_add (log_Debug, "Thread '%s' done (returned %d).", thread->name, result); fflush (stderr); #endif UnQueueThread (thread); DestroyThreadLocal (thread->localData); FinishThread (thread); /* Destroying the thread is the responsibility of ProcessThreadLifecycles() */ return result; } void DestroyThread_SDL (Thread t) { HFree (t); } Thread CreateThread_SDL (ThreadFunction func, void *data, SDWORD stackSize #ifdef NAMED_SYNCHRO , const char *name #endif ) { TrueThread thread; struct ThreadStartInfo *startInfo; thread = (struct _thread *) HMalloc (sizeof *thread); #ifdef NAMED_SYNCHRO thread->name = name; #endif #ifdef PROFILE_THREADS thread->startTime = GetTimeCounter (); #endif thread->localData = CreateThreadLocal (); startInfo = (struct ThreadStartInfo *) HMalloc (sizeof (*startInfo)); startInfo->func = func; startInfo->data = data; startInfo->sem = SDL_CreateSemaphore (0); startInfo->thread = thread; thread->native = SDL_CreateThread (ThreadHelper, (void *) startInfo); if (!(thread->native)) { DestroyThreadLocal (thread->localData); HFree (startInfo); HFree (thread); return NULL; } // The responsibility to free 'startInfo' and 'thread' is now by the new // thread. QueueThread (thread); #ifdef DEBUG_THREADS #if 0 log_add (log_Debug, "Thread '%s' created.", ThreadName (thread)); fflush (stderr); #endif #endif // Signal to the new thread that the thread structure is ready // and it can begin to use it. SDL_SemPost (startInfo->sem); (void) stackSize; /* Satisfying compiler (unused parameter) */ return thread; } void SleepThread_SDL (TimeCount sleepTime) { SDL_Delay (sleepTime * 1000 / ONE_SECOND); } void SleepThreadUntil_SDL (TimeCount wakeTime) { TimeCount now; now = GetTimeCounter (); if (wakeTime <= now) TaskSwitch_SDL (); else SDL_Delay ((wakeTime - now) * 1000 / ONE_SECOND); } void TaskSwitch_SDL (void) { SDL_Delay (1); } void WaitThread_SDL (Thread thread, int *status) { SDL_WaitThread (((TrueThread)thread)->native, status); } ThreadLocal * GetMyThreadLocal_SDL (void) { TrueThread t = FindThreadInfo (SDL_ThreadID ()); return t ? t->localData : NULL; } /* These are the SDL implementations of the UQM synchronization objects. */ /* Mutexes. */ /* TODO. The w_memlib uses Mutexes right now, so we can't use HMalloc * or HFree. Once that goes, this needs to change. */ typedef struct _mutex { SDL_mutex *mutex; #ifdef TRACK_CONTENTION Uint32 owner; #endif #ifdef NAMED_SYNCHRO const char *name; DWORD syncClass; #endif } Mut; Mutex #ifdef NAMED_SYNCHRO CreateMutex_SDL (const char *name, DWORD syncClass) #else CreateMutex_SDL (void) #endif { Mut *mutex = malloc (sizeof (Mut)); if (mutex != NULL) { mutex->mutex = SDL_CreateMutex(); #ifdef TRACK_CONTENTION mutex->owner = 0; #endif #ifdef NAMED_SYNCHRO mutex->name = name; mutex->syncClass = syncClass; #endif } if ((mutex == NULL) || (mutex->mutex == NULL)) { #ifdef NAMED_SYNCHRO /* logging depends on Mutexes, so we have to use the * non-threaded version instead */ log_add_nothread (log_Fatal, "Could not initialize mutex '%s':" "aborting.", name); #else log_add_nothread (log_Fatal, "Could not initialize mutex:" "aborting."); #endif exit (EXIT_FAILURE); } return mutex; } void DestroyMutex_SDL (Mutex m) { Mut *mutex = (Mut *)m; SDL_DestroyMutex (mutex->mutex); free (mutex); } void LockMutex_SDL (Mutex m) { Mut *mutex = (Mut *)m; #ifdef TRACK_CONTENTION /* This code isn't really quite right; race conditions between * check and lock remain and can produce reports of contention * where the thread never sleeps, or fail to report in * situations where it does. If tracking with perfect * accuracy becomes important, the TRACK_CONTENTION mutex will * need to handle its own wake/sleep cycles with condition * variables (check the history of this file for the * CrossThreadMutex code). This almost-measure is being added * because for the most part it should suffice. */ if (mutex->owner && (mutex->syncClass & TRACK_CONTENTION_CLASSES)) { /* logging depends on Mutexes, so we have to use the * non-threaded version instead */ log_add_nothread (log_Debug, "Thread '%s' blocking on mutex '%s'", MyThreadName (), mutex->name); } #endif while (SDL_mutexP (mutex->mutex) != 0) { TaskSwitch_SDL (); } #ifdef TRACK_CONTENTION mutex->owner = SDL_ThreadID (); #endif } void UnlockMutex_SDL (Mutex m) { Mut *mutex = (Mut *)m; #ifdef TRACK_CONTENTION mutex->owner = 0; #endif while (SDL_mutexV (mutex->mutex) != 0) { TaskSwitch_SDL (); } } /* Semaphores. */ typedef struct _sem { SDL_sem *sem; #ifdef NAMED_SYNCHRO const char *name; DWORD syncClass; #endif } Sem; Semaphore CreateSemaphore_SDL (DWORD initial #ifdef NAMED_SYNCHRO , const char *name, DWORD syncClass #endif ) { Sem *sem = (Sem *) HMalloc (sizeof (struct _sem)); #ifdef NAMED_SYNCHRO sem->name = name; sem->syncClass = syncClass; #endif sem->sem = SDL_CreateSemaphore (initial); if (sem->sem == NULL) { #ifdef NAMED_SYNCHRO log_add (log_Fatal, "Could not initialize semaphore '%s':" " aborting.", name); #else log_add (log_Fatal, "Could not initialize semaphore:" " aborting."); #endif exit (EXIT_FAILURE); } return sem; } void DestroySemaphore_SDL (Semaphore s) { Sem *sem = (Sem *)s; SDL_DestroySemaphore (sem->sem); HFree (sem); } void SetSemaphore_SDL (Semaphore s) { Sem *sem = (Sem *)s; #ifdef TRACK_CONTENTION BOOLEAN contention = !(SDL_SemValue (sem->sem)); if (contention && (sem->syncClass & TRACK_CONTENTION_CLASSES)) { log_add (log_Debug, "Thread '%s' blocking on semaphore '%s'", MyThreadName (), sem->name); } #endif while (SDL_SemWait (sem->sem) == -1) { TaskSwitch_SDL (); } #ifdef TRACK_CONTENTION if (contention && (sem->syncClass & TRACK_CONTENTION_CLASSES)) { log_add (log_Debug, "Thread '%s' awakens," " released from semaphore '%s'", MyThreadName (), sem->name); } #endif } void ClearSemaphore_SDL (Semaphore s) { Sem *sem = (Sem *)s; while (SDL_SemPost (sem->sem) == -1) { TaskSwitch_SDL (); } } /* Recursive mutexes. Adapted from mixSDL code, which was adapted from the original DCQ code. */ typedef struct _recm { SDL_mutex *mutex; Uint32 thread_id; Uint32 locks; #ifdef NAMED_SYNCHRO const char *name; DWORD syncClass; #endif } RecM; RecursiveMutex #ifdef NAMED_SYNCHRO CreateRecursiveMutex_SDL (const char *name, DWORD syncClass) #else CreateRecursiveMutex_SDL (void) #endif { RecM *mtx = (RecM *) HMalloc (sizeof (struct _recm)); mtx->thread_id = 0; mtx->mutex = SDL_CreateMutex (); if (mtx->mutex == NULL) { #ifdef NAMED_SYNCHRO log_add (log_Fatal, "Could not initialize recursive " "mutex '%s': aborting.", name); #else log_add (log_Fatal, "Could not initialize recursive " "mutex: aborting."); #endif exit (EXIT_FAILURE); } #ifdef NAMED_SYNCHRO mtx->name = name; mtx->syncClass = syncClass; #endif mtx->locks = 0; return (RecursiveMutex) mtx; } void DestroyRecursiveMutex_SDL (RecursiveMutex val) { RecM *mtx = (RecM *)val; SDL_DestroyMutex (mtx->mutex); HFree (mtx); } void LockRecursiveMutex_SDL (RecursiveMutex val) { RecM *mtx = (RecM *)val; Uint32 thread_id = SDL_ThreadID(); if (!mtx->locks || mtx->thread_id != thread_id) { #ifdef TRACK_CONTENTION if (mtx->thread_id && (mtx->syncClass & TRACK_CONTENTION_CLASSES)) { log_add (log_Debug, "Thread '%s' blocking on '%s'", MyThreadName (), mtx->name); } #endif while (SDL_mutexP (mtx->mutex)) TaskSwitch_SDL (); mtx->thread_id = thread_id; } mtx->locks++; } void UnlockRecursiveMutex_SDL (RecursiveMutex val) { RecM *mtx = (RecM *)val; Uint32 thread_id = SDL_ThreadID(); if (!mtx->locks || mtx->thread_id != thread_id) { #ifdef NAMED_SYNCHRO log_add (log_Debug, "'%s' attempted to unlock %s when it " "didn't hold it", MyThreadName (), mtx->name); #endif } else { mtx->locks--; if (!mtx->locks) { mtx->thread_id = 0; SDL_mutexV (mtx->mutex); } } } int GetRecursiveMutexDepth_SDL (RecursiveMutex val) { RecM *mtx = (RecM *)val; return mtx->locks; } typedef struct _cond { SDL_cond *cond; SDL_mutex *mutex; #ifdef NAMED_SYNCHRO const char *name; DWORD syncClass; #endif } cvar; CondVar #ifdef NAMED_SYNCHRO CreateCondVar_SDL (const char *name, DWORD syncClass) #else CreateCondVar_SDL (void) #endif { cvar *cv = (cvar *) HMalloc (sizeof (cvar)); cv->cond = SDL_CreateCond (); cv->mutex = SDL_CreateMutex (); if ((cv->cond == NULL) || (cv->mutex == NULL)) { #ifdef NAMED_SYNCHRO log_add (log_Fatal, "Could not initialize condition variable '%s':" " aborting.", name); #else log_add (log_Fatal, "Could not initialize condition variable:" " aborting."); #endif exit (EXIT_FAILURE); } #ifdef NAMED_SYNCHRO cv->name = name; cv->syncClass = syncClass; #endif return cv; } void DestroyCondVar_SDL (CondVar c) { cvar *cv = (cvar *) c; SDL_DestroyCond (cv->cond); SDL_DestroyMutex (cv->mutex); HFree (cv); } void WaitCondVar_SDL (CondVar c) { cvar *cv = (cvar *) c; SDL_mutexP (cv->mutex); #ifdef TRACK_CONTENTION if (cv->syncClass & TRACK_CONTENTION_CLASSES) { log_add (log_Debug, "Thread '%s' waiting for signal from '%s'", MyThreadName (), cv->name); } #endif while (SDL_CondWait (cv->cond, cv->mutex) != 0) { TaskSwitch_SDL (); } #ifdef TRACK_CONTENTION if (cv->syncClass & TRACK_CONTENTION_CLASSES) { log_add (log_Debug, "Thread '%s' received signal from '%s'," " awakening.", MyThreadName (), cv->name); } #endif SDL_mutexV (cv->mutex); } void SignalCondVar_SDL (CondVar c) { cvar *cv = (cvar *) c; SDL_CondSignal (cv->cond); } void BroadcastCondVar_SDL (CondVar c) { cvar *cv = (cvar *) c; SDL_CondBroadcast (cv->cond); } uqm-0.6.2/sc2/src/sc2code/libs/threads/sdl/sdlthreads.h0000600000175000017500000000753410543202042021263 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Serge van den Boom, 2002-09-12 */ #ifndef _SDLTHREAD_H #define _SDLTHREAD_H #include "port.h" #include SDL_INCLUDE(SDL.h) #include SDL_INCLUDE(SDL_thread.h) #include "libs/threadlib.h" #include "libs/timelib.h" void InitThreadSystem_SDL (void); void UnInitThreadSystem_SDL (void); #ifdef NAMED_SYNCHRO /* Prototypes with the "name" field */ Thread CreateThread_SDL (ThreadFunction func, void *data, SDWORD stackSize, const char *name); Mutex CreateMutex_SDL (const char *name, DWORD syncClass); Semaphore CreateSemaphore_SDL (DWORD initial, const char *name, DWORD syncClass); RecursiveMutex CreateRecursiveMutex_SDL (const char *name, DWORD syncClass); CondVar CreateCondVar_SDL (const char *name, DWORD syncClass); #else /* Prototypes without the "name" field. */ Thread CreateThread_SDL (ThreadFunction func, void *data, SDWORD stackSize); Mutex CreateMutex_SDL (void); Semaphore CreateSemaphore_SDL (DWORD initial); RecursiveMutex CreateRecursiveMutex_SDL (void); CondVar CreateCondVar_SDL (void); #endif ThreadLocal *GetMyThreadLocal_SDL (void); void SleepThread_SDL (TimeCount sleepTime); void SleepThreadUntil_SDL (TimeCount wakeTime); void TaskSwitch_SDL (void); void WaitThread_SDL (Thread thread, int *status); void DestroyThread_SDL (Thread thread); void DestroyMutex_SDL (Mutex m); void LockMutex_SDL (Mutex m); void UnlockMutex_SDL (Mutex m); void DestroySemaphore_SDL (Semaphore sem); void SetSemaphore_SDL (Semaphore sem); void ClearSemaphore_SDL (Semaphore sem); void DestroyCondVar_SDL (CondVar c); void WaitCondVar_SDL (CondVar c); void SignalCondVar_SDL (CondVar c); void BroadcastCondVar_SDL (CondVar c); void DestroyRecursiveMutex_SDL (RecursiveMutex m); void LockRecursiveMutex_SDL (RecursiveMutex m); void UnlockRecursiveMutex_SDL (RecursiveMutex m); int GetRecursiveMutexDepth_SDL (RecursiveMutex m); #define NativeInitThreadSystem InitThreadSystem_SDL #define NativeUnInitThreadSystem UnInitThreadSystem_SDL #define NativeGetMyThreadLocal GetMyThreadLocal_SDL #define NativeCreateThread CreateThread_SDL #define NativeSleepThread SleepThread_SDL #define NativeSleepThreadUntil SleepThreadUntil_SDL #define NativeTaskSwitch TaskSwitch_SDL #define NativeWaitThread WaitThread_SDL #define NativeDestroyThread DestroyThread_SDL #define NativeCreateMutex CreateMutex_SDL #define NativeDestroyMutex DestroyMutex_SDL #define NativeLockMutex LockMutex_SDL #define NativeUnlockMutex UnlockMutex_SDL #define NativeCreateSemaphore CreateSemaphore_SDL #define NativeDestroySemaphore DestroySemaphore_SDL #define NativeSetSemaphore SetSemaphore_SDL #define NativeClearSemaphore ClearSemaphore_SDL #define NativeCreateCondVar CreateCondVar_SDL #define NativeDestroyCondVar DestroyCondVar_SDL #define NativeWaitCondVar WaitCondVar_SDL #define NativeSignalCondVar SignalCondVar_SDL #define NativeBroadcastCondVar BroadcastCondVar_SDL #define NativeCreateRecursiveMutex CreateRecursiveMutex_SDL #define NativeDestroyRecursiveMutex DestroyRecursiveMutex_SDL #define NativeLockRecursiveMutex LockRecursiveMutex_SDL #define NativeUnlockRecursiveMutex UnlockRecursiveMutex_SDL #define NativeGetRecursiveMutexDepth GetRecursiveMutexDepth_SDL #endif /* _SDLTHREAD_H */ uqm-0.6.2/sc2/src/sc2code/libs/threads/sdl/Makeinfo0000600000175000017500000000003210543202042020413 0ustar joeyjoeyuqm_CFILES="sdlthreads.c" uqm-0.6.2/sc2/src/sc2code/libs/graphics/0000755000175000017500000000000010552600274016351 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/graphics/font.c0000600000175000017500000001504310543202053017447 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" #include "tfb_prim.h" #include "gfxother.h" #include "libs/log.h" extern void FixContextFontEffect (void); static inline TFB_Char *getCharFrame (FONT_DESC *fontPtr, wchar_t ch); static BYTE char_delta_array[MAX_DELTAS]; // XXX: This does not seem to be used. FONT SetContextFont (FONT Font) { FONT LastFont; LastFont = (FONT)_CurFontPtr; _CurFontPtr = (FONTPTR)Font; if (ContextActive ()) SwitchContextFont (Font); return (LastFont); } BOOLEAN DestroyFont (FONT_REF FontRef) { if (FontRef == 0) return (FALSE); if (_CurFontPtr && _CurFontPtr->FontRef == FontRef) SetContextFont ((FONT)0); return (FreeFont (FontRef)); } FONT CaptureFont (FONT_REF FontRef) { FONTPTR FontPtr; FontPtr = LockFont (FontRef); if (FontPtr) FontPtr->FontRef = FontRef; return ((FONT)FontPtr); } FONT_REF ReleaseFont (FONT Font) { FONTPTR FontPtr; FontPtr = (FONTPTR)Font; if (FontPtr) { FONT_REF FontRef; FontRef = FontPtr->FontRef; UnlockFont (FontRef); return (FontRef); } return (0); } void font_DrawText (PTEXT lpText) { FixContextFontEffect (); SetPrimType (&_locPrim, TEXT_PRIM); _locPrim.Object.Text = *lpText; DrawBatch (&_locPrim, 0, BATCH_SINGLE); } BOOLEAN GetContextFontLeading (PSIZE pheight) { if (_CurFontPtr != 0) { *pheight = (SIZE)_CurFontPtr->Leading; return (TRUE); } *pheight = 0; return (FALSE); } BOOLEAN GetContextFontLeadingWidth (PSIZE pwidth) { if (_CurFontPtr != 0) { *pwidth = (SIZE)_CurFontPtr->LeadingWidth; return (TRUE); } *pwidth = 0; return (FALSE); } BOOLEAN TextRect (PTEXT lpText, PRECT pRect, PBYTE pdelta) { FONTPTR FontPtr; FontPtr = _CurFontPtr; if (FontPtr != 0 && lpText->CharCount != 0) { COORD top_y, bot_y; SIZE width; wchar_t next_ch; const unsigned char *pStr; COUNT num_chars; num_chars = lpText->CharCount; /* At this point lpText->CharCount contains the *maximum* number of * characters that lpText->pStr may contain. * After the while loop below, it will contain the actual number. */ if (pdelta == 0) { pdelta = char_delta_array; if (num_chars > MAX_DELTAS) { num_chars = MAX_DELTAS; lpText->CharCount = MAX_DELTAS; } } top_y = 0; bot_y = 0; width = 0; pStr = lpText->pStr; if (num_chars > 0) { next_ch = getCharFromString (&pStr); if (next_ch == '\0') num_chars = 0; } while (num_chars--) { wchar_t ch; SIZE last_width; TFB_Char *charFrame; last_width = width; ch = next_ch; if (num_chars > 0) { next_ch = getCharFromString (&pStr); if (next_ch == '\0') { lpText->CharCount -= num_chars; num_chars = 0; } } charFrame = getCharFrame (FontPtr, ch); if (charFrame != NULL && charFrame->disp.width) { COORD y; y = -charFrame->HotSpot.y; if (y < top_y) top_y = y; y += charFrame->disp.height; if (y > bot_y) bot_y = y; width += charFrame->disp.width; #if 0 if (num_chars && next_ch < (UNICODE) MAX_CHARS && !(FontPtr->KernTab[ch] & (FontPtr->KernTab[next_ch] >> 2))) width -= FontPtr->KernAmount; #endif } *pdelta++ = (BYTE)(width - last_width); } if (width > 0 && (bot_y -= top_y) > 0) { /* subtract off default character spacing */ if (pdelta[-1] > 0) { --pdelta[-1]; --width; } if (lpText->align == ALIGN_LEFT) pRect->corner.x = 0; else if (lpText->align == ALIGN_CENTER) pRect->corner.x = -(width >> 1); else pRect->corner.x = -width; pRect->corner.y = top_y; pRect->extent.width = width; pRect->extent.height = bot_y; pRect->corner.x += lpText->baseline.x; pRect->corner.y += lpText->baseline.y; return (TRUE); } } pRect->corner = lpText->baseline; pRect->extent.width = 0; pRect->extent.height = 0; return (FALSE); } void _text_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr) { FONTPTR FontPtr; COUNT num_chars; wchar_t next_ch; const unsigned char *pStr; TEXTPTR TextPtr; POINT origin; TFB_Palette color; TFB_Image *backing; FontPtr = _CurFontPtr; if (FontPtr == NULL) return; backing = _get_context_font_backing (); if (!backing) return; COLORtoPalette (_get_context_fg_color (), &color); TextPtr = &PrimPtr->Object.Text; origin.x = _save_stamp.origin.x; origin.y = TextPtr->baseline.y; num_chars = TextPtr->CharCount; if (num_chars == 0) return; pStr = TextPtr->pStr; next_ch = getCharFromString (&pStr); if (next_ch == '\0') num_chars = 0; while (num_chars--) { wchar_t ch; TFB_Char* fontChar; ch = next_ch; if (num_chars > 0) { next_ch = getCharFromString (&pStr); if (next_ch == '\0') num_chars = 0; } fontChar = getCharFrame (FontPtr, ch); if (fontChar != NULL && fontChar->disp.width) { RECT r; r.corner.x = origin.x - fontChar->HotSpot.x; r.corner.y = origin.y - fontChar->HotSpot.y; r.extent.width = fontChar->disp.width; r.extent.height = fontChar->disp.height; _save_stamp.origin = r.corner; if (BoxIntersect (&r, pClipRect, &r)) { TFB_Prim_FontChar (&origin, fontChar, backing); } origin.x += fontChar->disp.width; #if 0 if (num_chars && next_ch < (UNICODE) MAX_CHARS && !(FontPtr->KernTab[ch] & (FontPtr->KernTab[next_ch] >> 2))) origin.x -= FontPtr->KernAmount; #endif } } } static inline TFB_Char * getCharFrame (FONT_DESC *fontPtr, wchar_t ch) { wchar_t pageStart = ch & CHARACTER_PAGE_MASK; size_t charIndex; FONT_PAGE *page = fontPtr->fontPages; for (;;) { if (page == NULL) return NULL; if (page->pageStart == pageStart) break; page = page->next; } charIndex = ch - page->firstChar; if (ch >= page->firstChar && charIndex < page->numChars && page->charDesc[charIndex].data) { return &page->charDesc[charIndex]; } else { log_add (log_Debug, "Character %u not present", (unsigned int) ch); return NULL; } } uqm-0.6.2/sc2/src/sc2code/libs/graphics/widgets.c0000600000175000017500000004644510543202053020161 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "graphics/gfx_common.h" #include "graphics/widgets.h" #include "colors.h" #include "strlib.h" #include "setup.h" #include "units.h" WIDGET *widget_focus = NULL; /* Some basic color defines */ #define WIDGET_ACTIVE_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x0E) #define WIDGET_INACTIVE_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x18, 0x18, 0x1F), 0x00) #define WIDGET_INACTIVE_SELECTED_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) #define WIDGET_CURSOR_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00) #define WIDGET_DIALOG_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x07) #define WIDGET_DIALOG_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00) void DrawShadowedBox(PRECT r, COLOR bg, COLOR dark, COLOR medium) { RECT t; COLOR oldcolor; BatchGraphics (); t.corner.x = r->corner.x - 2; t.corner.y = r->corner.y - 2; t.extent.width = r->extent.width + 4; t.extent.height = r->extent.height + 4; oldcolor = SetContextForeGroundColor (dark); DrawFilledRectangle (&t); t.corner.x += 2; t.corner.y += 2; t.extent.width -= 2; t.extent.height -= 2; SetContextForeGroundColor (medium); DrawFilledRectangle (&t); t.corner.x -= 1; t.corner.y += r->extent.height + 1; t.extent.height = 1; DrawFilledRectangle (&t); t.corner.x += r->extent.width + 2; t.corner.y -= r->extent.height + 2; t.extent.width = 1; DrawFilledRectangle (&t); SetContextForeGroundColor (bg); DrawFilledRectangle (r); SetContextForeGroundColor (oldcolor); UnbatchGraphics (); } void DrawLabelAsWindow(WIDGET_LABEL *label) { COLOR oldfg = SetContextForeGroundColor (WIDGET_DIALOG_TEXT_COLOR); FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); RECT r; TEXT t; int i, win_w, win_h; /* Compute the dimensions of the label */ win_h = label->height ((WIDGET *)label) + 16; win_w = 0; for (i = 0; i < label->line_count; i++) { int len = utf8StringCount (label->lines[i]); if (len > win_w) { win_w = len; } } win_w = (win_w * 6) + 16; BatchGraphics (); r.corner.x = (SCREEN_WIDTH - win_w) >> 1; r.corner.y = (SCREEN_HEIGHT - win_h) >> 1; r.extent.width = win_w; r.extent.height = win_h; DrawShadowedBox (&r, SHADOWBOX_BACKGROUND_COLOR, SHADOWBOX_DARK_COLOR, SHADOWBOX_MEDIUM_COLOR); t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.y = r.corner.y + 16; for (i = 0; i < label->line_count; i++) { t.pStr = label->lines[i]; t.align = ALIGN_CENTER; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += 8; } UnbatchGraphics (); SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldfg); } static void Widget_DrawToolTips (int numlines, const char **tips) { RECT r; FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); COLOR oldtext = SetContextForeGroundColor (WIDGET_INACTIVE_SELECTED_COLOR); TEXT t; int i; r.corner.x = 2; r.corner.y = 2; r.extent.width = SCREEN_WIDTH - 4; r.extent.height = SCREEN_HEIGHT - 4; t.align = ALIGN_CENTER; t.CharCount = ~0; t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.y = r.corner.y + (r.extent.height - 8 - 8 * numlines); for (i = 0; i < numlines; i++) { t.pStr = tips[i]; font_DrawText(&t); t.baseline.y += 8; } SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); } void Widget_DrawMenuScreen (WIDGET *_self, int x, int y) { RECT r; COLOR title, oldtext; COLOR inactive, default_color, selected; FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; int widget_index, height, widget_y; WIDGET_MENU_SCREEN *self = (WIDGET_MENU_SCREEN *)_self; r.corner.x = 2; r.corner.y = 2; r.extent.width = SCREEN_WIDTH - 4; r.extent.height = SCREEN_HEIGHT - 4; title = WIDGET_INACTIVE_SELECTED_COLOR; selected = WIDGET_ACTIVE_COLOR; inactive = WIDGET_INACTIVE_COLOR; default_color = title; DrawStamp (&self->bgStamp); oldtext = SetContextForeGroundColor (title); t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.y = r.corner.y + 8; t.pStr = self->title; t.align = ALIGN_CENTER; t.CharCount = ~0; font_DrawText (&t); t.baseline.y += 8; t.pStr = self->subtitle; font_DrawText (&t); height = 0; for (widget_index = 0; widget_index < self->num_children; widget_index++) { WIDGET *child = self->child[widget_index]; height += (*child->height)(child); height += 8; /* spacing */ } height -= 8; widget_y = (SCREEN_HEIGHT - height) >> 1; for (widget_index = 0; widget_index < self->num_children; widget_index++) { WIDGET *c = self->child[widget_index]; (*c->draw)(c, 0, widget_y); widget_y += (*c->height)(c) + 8; } SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); (void) x; (void) y; } void Widget_DrawChoice (WIDGET *_self, int x, int y) { WIDGET_CHOICE *self = (WIDGET_CHOICE *)_self; COLOR oldtext; COLOR inactive, default_color, selected; FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; int i, home_x, home_y; default_color = WIDGET_INACTIVE_SELECTED_COLOR; selected = WIDGET_ACTIVE_COLOR; inactive = WIDGET_INACTIVE_COLOR; t.baseline.x = x; t.baseline.y = y; t.align = ALIGN_LEFT; t.CharCount = ~0; t.pStr = self->category; if (widget_focus == _self) { oldtext = SetContextForeGroundColor (selected); } else { oldtext = SetContextForeGroundColor (default_color); } font_DrawText (&t); home_x = t.baseline.x + 3 * (SCREEN_WIDTH / ((self->maxcolumns + 1) * 2)); home_y = t.baseline.y; t.align = ALIGN_CENTER; for (i = 0; i < self->numopts; i++) { t.baseline.x = home_x + ((i % 3) * (SCREEN_WIDTH / (self->maxcolumns + 1))); t.baseline.y = home_y + (8 * (i / 3)); t.pStr = self->options[i].optname; if ((widget_focus == _self) && (self->highlighted == i)) { SetContextForeGroundColor (selected); Widget_DrawToolTips (3, self->options[i].tooltip); } else if (i == self->selected) { SetContextForeGroundColor (default_color); } else { SetContextForeGroundColor (inactive); } font_DrawText (&t); } SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); } void Widget_DrawButton (WIDGET *_self, int x, int y) { WIDGET_BUTTON *self = (WIDGET_BUTTON *)_self; COLOR oldtext; COLOR inactive, selected; FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; selected = WIDGET_ACTIVE_COLOR; inactive = WIDGET_INACTIVE_COLOR; t.baseline.x = 160; t.baseline.y = y; t.align = ALIGN_CENTER; t.CharCount = ~0; t.pStr = self->name; if (widget_focus == _self) { Widget_DrawToolTips (3, self->tooltip); oldtext = SetContextForeGroundColor (selected); } else { oldtext = SetContextForeGroundColor (inactive); } font_DrawText (&t); SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); (void) x; } void Widget_DrawLabel (WIDGET *_self, int x, int y) { WIDGET_LABEL *self = (WIDGET_LABEL *)_self; COLOR oldtext = SetContextForeGroundColor (WIDGET_INACTIVE_SELECTED_COLOR); FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; int i; t.baseline.x = 160; t.baseline.y = y; t.align = ALIGN_CENTER; t.CharCount = ~0; for (i = 0; i < self->line_count; i++) { t.pStr = self->lines[i]; font_DrawText (&t); t.baseline.y += 8; } SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); (void) x; } void Widget_DrawSlider(WIDGET *_self, int x, int y) { WIDGET_SLIDER *self = (WIDGET_SLIDER *)_self; COLOR oldtext; COLOR inactive, default_color, selected; FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; RECT r; int tick = (SCREEN_WIDTH - x) / 8; default_color = WIDGET_INACTIVE_SELECTED_COLOR; selected = WIDGET_ACTIVE_COLOR; inactive = WIDGET_INACTIVE_COLOR; t.baseline.x = x; t.baseline.y = y; t.align = ALIGN_LEFT; t.CharCount = ~0; t.pStr = self->category; if (widget_focus == _self) { Widget_DrawToolTips (3, self->tooltip); oldtext = SetContextForeGroundColor (selected); } else { oldtext = SetContextForeGroundColor (default_color); } font_DrawText (&t); r.corner.x = t.baseline.x + 3 * tick; r.corner.y = t.baseline.y - 4; r.extent.height = 2; r.extent.width = 3 * tick; DrawFilledRectangle (&r); r.extent.width = 3; r.extent.height = 8; r.corner.y = t.baseline.y - 7; r.corner.x = t.baseline.x + 3 * tick + (3 * tick * (self->value - self->min) / (self->max - self->min)) - 1; DrawFilledRectangle (&r); (*self->draw_value)(self, t.baseline.x + 7 * tick, t.baseline.y); SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); } void Widget_Slider_DrawValue (WIDGET_SLIDER *self, int x, int y) { TEXT t; char buffer[16]; sprintf (buffer, "%d", self->value); t.baseline.x = x; t.baseline.y = y; t.align = ALIGN_CENTER; t.CharCount = ~0; t.pStr = buffer; font_DrawText (&t); } void Widget_DrawTextEntry (WIDGET *_self, int x, int y) { WIDGET_TEXTENTRY *self = (WIDGET_TEXTENTRY *)_self; COLOR oldtext; COLOR inactive, default_color, selected; FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; default_color = WIDGET_INACTIVE_SELECTED_COLOR; selected = WIDGET_ACTIVE_COLOR; inactive = WIDGET_INACTIVE_COLOR; BatchGraphics (); t.baseline.x = x; t.baseline.y = y; t.align = ALIGN_LEFT; t.CharCount = ~0; t.pStr = self->category; if (widget_focus == _self) { oldtext = SetContextForeGroundColor (selected); } else { oldtext = SetContextForeGroundColor (default_color); } font_DrawText (&t); /* Force string termination */ self->value[WIDGET_TEXTENTRY_WIDTH-1] = 0; t.baseline.y = y; t.CharCount = utf8StringCount (self->value); t.pStr = self->value; if (!(self->state & WTE_EDITING)) { // normal or selected state t.baseline.x = 160; t.align = ALIGN_CENTER; if (widget_focus == _self) { oldtext = SetContextForeGroundColor (selected); } else { oldtext = SetContextForeGroundColor (inactive); } font_DrawText (&t); } else { // editing state COUNT i; RECT text_r; BYTE char_deltas[WIDGET_TEXTENTRY_WIDTH]; PBYTE pchar_deltas; RECT r; SIZE leading; t.baseline.x = 90; t.align = ALIGN_LEFT; // calc background box dimensions // XXX: this may need some tuning, especially if a // different font is used. The font 'leading' values // are not what they should be. #define BOX_VERT_OFFSET 2 GetContextFontLeading (&leading); r.corner.x = t.baseline.x - 1; r.corner.y = t.baseline.y - leading + BOX_VERT_OFFSET; r.extent.width = ScreenWidth - r.corner.x - 10; r.extent.height = leading + 2; TextRect (&t, &text_r, char_deltas); #if 0 // XXX: this should potentially be used in ChangeCallback if ((text_r.extent.width + 2) >= r.extent.width) { // the text does not fit the input box size and so // will not fit when displayed later UnbatchGraphics (); // disallow the change return (FALSE); } #endif oldtext = SetContextForeGroundColor (selected); DrawFilledRectangle (&r); // calculate the cursor position and draw it pchar_deltas = char_deltas; for (i = self->cursor_pos; i > 0; --i) r.corner.x += (SIZE)*pchar_deltas++; if (self->cursor_pos < t.CharCount) /* cursor mid-line */ --r.corner.x; if (self->state & WTE_BLOCKCUR) { // Use block cursor for keyboardless systems if (self->cursor_pos == t.CharCount) { // cursor at end-line -- use insertion point r.extent.width = 1; } else if (self->cursor_pos + 1 == t.CharCount) { // extra pixel for last char margin r.extent.width = (SIZE)*pchar_deltas + 2; } else { // normal mid-line char r.extent.width = (SIZE)*pchar_deltas + 1; } } else { // Insertion point cursor r.extent.width = 1; } // position cursor within input field rect ++r.corner.x; ++r.corner.y; r.extent.height -= 2; SetContextForeGroundColor (WIDGET_CURSOR_COLOR); DrawFilledRectangle (&r); SetContextForeGroundColor (inactive); font_DrawText (&t); } UnbatchGraphics (); SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); } void Widget_DrawControlEntry (WIDGET *_self, int x, int y) { WIDGET_CONTROLENTRY *self = (WIDGET_CONTROLENTRY *)_self; COLOR oldtext; COLOR inactive, default_color, selected; FONT oldfont = SetContextFont (StarConFont); FRAME oldFontEffect = SetContextFontEffect (NULL); TEXT t; int i, home_x, home_y; default_color = WIDGET_INACTIVE_SELECTED_COLOR; selected = WIDGET_ACTIVE_COLOR; inactive = WIDGET_INACTIVE_COLOR; t.baseline.x = x; t.baseline.y = y; t.align = ALIGN_LEFT; t.CharCount = ~0; t.pStr = self->category; if (widget_focus == _self) { oldtext = SetContextForeGroundColor (selected); } else { oldtext = SetContextForeGroundColor (default_color); } font_DrawText (&t); // 3 * SCREEN_WIDTH / ((self->maxcolumns + 1) * 2)) as per CHOICE, but only two options. home_x = t.baseline.x + (SCREEN_WIDTH / 2); home_y = t.baseline.y; t.align = ALIGN_CENTER; for (i = 0; i < 2; i++) { t.baseline.x = home_x + ((i % 3) * (SCREEN_WIDTH / 3)); // self->maxcolumns + 1 as per CHOICE. t.baseline.y = home_y + (8 * (i / 3)); t.pStr = self->controlname[i]; if (!t.pStr[0]) { t.pStr = "---"; } if ((widget_focus == _self) && (self->highlighted == i)) { SetContextForeGroundColor (selected); } else { SetContextForeGroundColor (default_color); } font_DrawText (&t); } SetContextFontEffect (oldFontEffect); SetContextFont (oldfont); SetContextForeGroundColor (oldtext); } int Widget_HeightChoice (WIDGET *_self) { return ((((WIDGET_CHOICE *)_self)->numopts + 2) / 3) * 8; } int Widget_HeightFullScreen (WIDGET *_self) { (void)_self; return SCREEN_HEIGHT; } int Widget_HeightOneLine (WIDGET *_self) { (void)_self; return 8; } int Widget_HeightLabel (WIDGET *_self) { WIDGET_LABEL *self = (WIDGET_LABEL *)_self; return self->line_count * 8; } int Widget_WidthFullScreen (WIDGET *_self) { (void)_self; return SCREEN_WIDTH; } int Widget_ReceiveFocusSimple (WIDGET *_self, int event) { widget_focus = _self; (void)event; return TRUE; } int Widget_ReceiveFocusChoice (WIDGET *_self, int event) { WIDGET_CHOICE *self = (WIDGET_CHOICE *)_self; widget_focus = _self; self->highlighted = self->selected; (void)event; return TRUE; } int Widget_ReceiveFocusControlEntry (WIDGET *_self, int event) { WIDGET_CONTROLENTRY *self = (WIDGET_CONTROLENTRY *)_self; int oldval = 0; if (widget_focus->tag == WIDGET_TYPE_CONTROLENTRY) { oldval = ((WIDGET_CONTROLENTRY *)widget_focus)->highlighted; } widget_focus = _self; self->highlighted = oldval; (void)event; return TRUE; } int Widget_ReceiveFocusMenuScreen (WIDGET *_self, int event) { WIDGET_MENU_SCREEN *self = (WIDGET_MENU_SCREEN *)_self; int x, last_x, dx; for (x = 0; x < self->num_children; x++) { self->child[x]->parent = _self; } if (event == WIDGET_EVENT_UP) { x = self->num_children - 1; dx = -1; last_x = -1; } else if (event == WIDGET_EVENT_DOWN) { x = 0; dx = 1; last_x = self->num_children; } else { /* Leave highlighted value the same */ WIDGET *child = self->child[self->highlighted]; child->receiveFocus (child, event); return TRUE; } for ( ; x != last_x; x += dx) { WIDGET *child = self->child[x]; if ((*child->receiveFocus)(child, event)) { self->highlighted = x; return TRUE; } } return FALSE; } int Widget_ReceiveFocusRefuseFocus (WIDGET *self, int event) { (void)self; (void)event; return FALSE; } int Widget_HandleEventIgnoreAll (WIDGET *self, int event) { (void)event; (void)self; return FALSE; } int Widget_HandleEventChoice (WIDGET *_self, int event) { WIDGET_CHOICE *self = (WIDGET_CHOICE *)_self; switch (event) { case WIDGET_EVENT_LEFT: self->highlighted -= 1; if (self->highlighted < 0) self->highlighted = self->numopts - 1; return TRUE; case WIDGET_EVENT_RIGHT: self->highlighted += 1; if (self->highlighted >= self->numopts) self->highlighted = 0; return TRUE; case WIDGET_EVENT_SELECT: { int oldval = self->selected; self->selected = self->highlighted; if (self->onChange) { (*(self->onChange))(self, oldval); } return TRUE; } default: return FALSE; } } int Widget_HandleEventSlider (WIDGET *_self, int event) { WIDGET_SLIDER *self = (WIDGET_SLIDER *)_self; switch (event) { case WIDGET_EVENT_LEFT: self->value -= self->step; if (self->value < self->min) self->value = self->min; return TRUE; case WIDGET_EVENT_RIGHT: self->value += self->step; if (self->value > self->max) self->value = self->max; return TRUE; default: return FALSE; } } int Widget_HandleEventMenuScreen (WIDGET *_self, int event) { WIDGET_MENU_SCREEN *self = (WIDGET_MENU_SCREEN *)_self; int x, last_x, dx; switch (event) { case WIDGET_EVENT_UP: dx = -1; break; case WIDGET_EVENT_DOWN: dx = 1; break; case WIDGET_EVENT_CANCEL: /* On cancel, shift focus to last element and send a SELECT. */ self->highlighted = self->num_children - 1; widget_focus = self->child[self->highlighted]; return (widget_focus->handleEvent)(widget_focus, WIDGET_EVENT_SELECT); default: return FALSE; } last_x = self->highlighted; x = self->highlighted + dx; while (x != last_x) { WIDGET *child; if (x == -1) x = self->num_children - 1; if (x == self->num_children) x = 0; child = self->child[x]; if ((*child->receiveFocus)(child, event)) { self->highlighted = x; return TRUE; } x += dx; } return FALSE; } int Widget_HandleEventTextEntry (WIDGET *_self, int event) { WIDGET_TEXTENTRY *self = (WIDGET_TEXTENTRY *)_self; if (event == WIDGET_EVENT_SELECT) { if (!self->handleEventSelect) return FALSE; return (*self->handleEventSelect)(self); } return FALSE; } int Widget_HandleEventControlEntry (WIDGET *_self, int event) { WIDGET_CONTROLENTRY *self = (WIDGET_CONTROLENTRY *)_self; if (event == WIDGET_EVENT_SELECT) { if (self->onChange) { (self->onChange)(self); return TRUE; } } if (event == WIDGET_EVENT_DELETE) { if (self->onDelete) { (self->onDelete)(self); return TRUE; } } if ((event == WIDGET_EVENT_RIGHT) || (event == WIDGET_EVENT_LEFT)) { self->highlighted = 1-self->highlighted; return TRUE; } return FALSE; } int Widget_Event (int event) { WIDGET *widget = widget_focus; while (widget != NULL) { if ((*widget->handleEvent)(widget, event)) return TRUE; widget = widget->parent; } return FALSE; } uqm-0.6.2/sc2/src/sc2code/libs/graphics/drawable.h0000600000175000017500000000636210543202054020274 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _DRAWABLE_H #define _DRAWABLE_H #include #include "tfb_draw.h" #define ValidPrimType(pt) ((pt)Bounds.width) #define GetFrameHeight(f) (((PFRAME_DESC)(f))->Bounds.height) #define SetFrameBounds(f,w,h) \ (((PFRAME_DESC)(f))->Bounds.width=(w), \ ((PFRAME_DESC)(f))->Bounds.height=(h)) #define DRAWABLE_PRIORITY DEFAULT_MEM_PRIORITY #define DRAWABLEPTR PDRAWABLE_DESC #define FRAMEPTR PFRAME_DESC #define COUNTPTR PCOUNT extern DRAWABLE AllocDrawable (COUNT num_frames); #define LockDrawable(D) ((DRAWABLEPTR)mem_lock (GetDrawableHandle (D))) #define UnlockDrawable(D) mem_unlock (GetDrawableHandle (D)) #define FreeDrawable(D) _ReleaseCelData (GetDrawableHandle (D)) #define GetDrawableHandle(D) ((MEM_HANDLE)LOWORD (D)) #define GetDrawableIndex(D) ((COUNT)HIWORD (D)) #define GetFrameParentDrawable(F) (F)->parent #define NULL_DRAWABLE (DRAWABLE)NULL_PTR #define TYPE_GET(f) ((f) & FTYPE_MASK) #define INDEX_GET(f) ((f) & FINDEX_MASK) #define TYPE_SET(f,t) ((f)|=t) #define INDEX_SET(f,i) ((f)|=i) typedef struct { RECT Box; FRAMEPTR FramePtr; } IMAGE_BOX; typedef IMAGE_BOX *PIMAGE_BOX; extern DRAWABLE _request_drawable (COUNT NumFrames, DRAWABLE_TYPE DrawableType, CREATE_FLAGS flags, SIZE width, SIZE height); extern INTERSECT_CODE _clip_line (PRECT pClipRect, PBRESENHAM_LINE pLine); extern MEM_HANDLE _GetCelData (uio_Stream *fp, DWORD length); extern BOOLEAN _ReleaseCelData (MEM_HANDLE handle); typedef PPRIMITIVE PRIMITIVEPTR; typedef PPOINT POINTPTR; typedef PRECT RECTPTR; typedef PSTAMP STAMPPTR; typedef PTEXT TEXTPTR; extern STAMP _save_stamp; extern FRAMEPTR _CurFramePtr; extern void _rect_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr); extern void _text_blt (PRECT pClipRect, PRIMITIVEPTR PrimPtr); #endif /* _DRAWABLE_H */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/tfb_draw.c0000600000175000017500000002340410543202054020272 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "gfx_common.h" #include "tfb_draw.h" #include "drawcmd.h" #include "units.h" #include "libs/log.h" static const HOT_SPOT NullHs = {0, 0}; void TFB_DrawScreen_Line (int x1, int y1, int x2, int y2, int r, int g, int b, SCREEN dest) { TFB_DrawCommand DC; DC.Type = TFB_DRAWCOMMANDTYPE_LINE; DC.data.line.x1 = x1; DC.data.line.y1 = y1; DC.data.line.x2 = x2; DC.data.line.y2 = y2; DC.data.line.r = r; DC.data.line.g = g; DC.data.line.b = b; DC.data.line.destBuffer = dest; TFB_EnqueueDrawCommand (&DC); } void TFB_DrawScreen_Rect (PRECT rect, int r, int g, int b, SCREEN dest) { RECT locRect; TFB_DrawCommand DC; if (!rect) { locRect.corner.x = locRect.corner.y = 0; locRect.extent.width = SCREEN_WIDTH; locRect.extent.height = SCREEN_HEIGHT; rect = &locRect; } DC.Type = TFB_DRAWCOMMANDTYPE_RECTANGLE; DC.data.rect.rect = *rect; DC.data.rect.r = r; DC.data.rect.g = g; DC.data.rect.b = b; DC.data.rect.destBuffer = dest; TFB_EnqueueDrawCommand (&DC); } void TFB_DrawScreen_SetPalette (int paletteIndex, int r, int g, int b) { TFB_DrawCommand DC; DC.Type = TFB_DRAWCOMMANDTYPE_SETPALETTE; DC.data.setpalette.r = r; DC.data.setpalette.g = g; DC.data.setpalette.b = b; DC.data.setpalette.index = paletteIndex; TFB_EnqueueDrawCommand (&DC); } void TFB_DrawScreen_Image (TFB_Image *img, int x, int y, int scale, TFB_ColorMap *cmap, SCREEN dest) { TFB_DrawCommand DC; DC.Type = TFB_DRAWCOMMANDTYPE_IMAGE; DC.data.image.image = img; DC.data.image.colormap = cmap; DC.data.image.x = x; DC.data.image.y = y; DC.data.image.scale = (scale == GSCALE_IDENTITY) ? 0 : scale; DC.data.image.destBuffer = dest; TFB_EnqueueDrawCommand (&DC); } void TFB_DrawScreen_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int g, int b, SCREEN dest) { TFB_DrawCommand DC; DC.Type = TFB_DRAWCOMMANDTYPE_FILLEDIMAGE; DC.data.filledimage.image = img; DC.data.filledimage.x = x; DC.data.filledimage.y = y; DC.data.filledimage.scale = (scale == GSCALE_IDENTITY) ? 0 : scale; DC.data.filledimage.r = r; DC.data.filledimage.g = g; DC.data.filledimage.b = b; DC.data.filledimage.destBuffer = dest; TFB_EnqueueDrawCommand (&DC); } void TFB_DrawScreen_FontChar (TFB_Char *fontChar, TFB_Image *backing, int x, int y, SCREEN dest) { TFB_DrawCommand DC; DC.Type = TFB_DRAWCOMMANDTYPE_FONTCHAR; DC.data.fontchar.fontchar = fontChar; DC.data.fontchar.backing = backing; DC.data.fontchar.x = x; DC.data.fontchar.y = y; DC.data.fontchar.destBuffer = dest; TFB_EnqueueDrawCommand (&DC); } void TFB_DrawScreen_CopyToImage (TFB_Image *img, PRECT lpRect, SCREEN src) { TFB_DrawCommand DC; DC.Type = TFB_DRAWCOMMANDTYPE_COPYTOIMAGE; DC.data.copytoimage.x = lpRect->corner.x; DC.data.copytoimage.y = lpRect->corner.y; DC.data.copytoimage.w = lpRect->extent.width; DC.data.copytoimage.h = lpRect->extent.height; DC.data.copytoimage.image = img; DC.data.copytoimage.srcBuffer = src; TFB_EnqueueDrawCommand (&DC); } void TFB_DrawScreen_Copy (PRECT r, SCREEN src, SCREEN dest) { RECT locRect; TFB_DrawCommand DC; if (!r) { locRect.corner.x = locRect.corner.y = 0; locRect.extent.width = SCREEN_WIDTH; locRect.extent.height = SCREEN_HEIGHT; r = &locRect; } DC.Type = TFB_DRAWCOMMANDTYPE_COPY; DC.data.copy.x = r->corner.x; DC.data.copy.y = r->corner.y; DC.data.copy.w = r->extent.width; DC.data.copy.h = r->extent.height; DC.data.copy.srcBuffer = src; DC.data.copy.destBuffer = dest; TFB_EnqueueDrawCommand (&DC); } void TFB_DrawScreen_DeleteImage (TFB_Image *img) { if (img) { TFB_DrawCommand DC; DC.Type = TFB_DRAWCOMMANDTYPE_DELETEIMAGE; DC.data.deleteimage.image = img; TFB_EnqueueDrawCommand (&DC); } } void TFB_DrawScreen_DeleteData (void *data) // data must be a result of HXalloc() call { if (data) { TFB_DrawCommand DC; DC.Type = TFB_DRAWCOMMANDTYPE_DELETEDATA; DC.data.deletedata.data = data; TFB_EnqueueDrawCommand (&DC); } } void TFB_DrawScreen_WaitForSignal (void) { TFB_DrawCommand DrawCommand; Semaphore s; s = GetMyThreadLocal ()->flushSem; DrawCommand.Type = TFB_DRAWCOMMANDTYPE_SENDSIGNAL; DrawCommand.data.sendsignal.sem = s; Lock_DCQ (1); TFB_BatchReset (); TFB_EnqueueDrawCommand(&DrawCommand); Unlock_DCQ(); SetSemaphore (s); } void TFB_DrawScreen_ReinitVideo (int driver, int flags, int width, int height) { TFB_DrawCommand DrawCommand; DrawCommand.Type = TFB_DRAWCOMMANDTYPE_REINITVIDEO; DrawCommand.data.reinitvideo.driver = driver; DrawCommand.data.reinitvideo.flags = flags; DrawCommand.data.reinitvideo.width = width; DrawCommand.data.reinitvideo.height = height; TFB_EnqueueDrawCommand(&DrawCommand); } void TFB_DrawImage_Line (int x1, int y1, int x2, int y2, int r, int g, int b, TFB_Image *dest) { LockMutex (dest->mutex); TFB_DrawCanvas_Line (x1, y1, x2, y2, r, g, b, dest->NormalImg); dest->dirty = TRUE; UnlockMutex (dest->mutex); } void TFB_DrawImage_Rect (PRECT rect, int r, int g, int b, TFB_Image *image) { LockMutex (image->mutex); TFB_DrawCanvas_Rect (rect, r, g, b, image->NormalImg); image->dirty = TRUE; UnlockMutex (image->mutex); } void TFB_DrawImage_Image (TFB_Image *img, int x, int y, int scale, TFB_ColorMap *cmap, TFB_Image *target) { LockMutex (target->mutex); TFB_DrawCanvas_Image (img, x, y, scale, cmap, target->NormalImg); target->dirty = TRUE; UnlockMutex (target->mutex); } void TFB_DrawImage_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int g, int b, TFB_Image *target) { LockMutex (target->mutex); TFB_DrawCanvas_FilledImage (img, x, y, scale, r, g, b, target->NormalImg); target->dirty = TRUE; UnlockMutex (target->mutex); } void TFB_DrawImage_FontChar (TFB_Char *fontChar, TFB_Image *backing, int x, int y, TFB_Image *target) { LockMutex (target->mutex); TFB_DrawCanvas_FontChar (fontChar, backing, x, y, target->NormalImg); target->dirty = TRUE; UnlockMutex (target->mutex); } TFB_Image * TFB_DrawImage_New (TFB_Canvas canvas) { TFB_Image *img = HMalloc (sizeof (TFB_Image)); img->mutex = CreateMutex ("image lock", SYNC_CLASS_VIDEO); img->ScaledImg = NULL; img->MipmapImg = NULL; img->FilledImg = NULL; img->colormap_index = -1; img->colormap_version = 0; img->NormalHs = NullHs; img->MipmapHs = NullHs; img->last_scale_hs = NullHs; img->last_scale_type = -1; TFB_DrawCanvas_GetExtent (canvas, &img->extent); img->Palette = TFB_DrawCanvas_ExtractPalette (canvas); if (img->Palette) { img->NormalImg = canvas; } else { img->NormalImg = TFB_DrawCanvas_ToScreenFormat (canvas); } return img; } TFB_Image* TFB_DrawImage_CreateForScreen (int w, int h, BOOLEAN withalpha) { TFB_Image* img = HMalloc (sizeof (TFB_Image)); img->mutex = CreateMutex ("image lock", SYNC_CLASS_VIDEO); img->ScaledImg = NULL; img->MipmapImg = NULL; img->FilledImg = NULL; img->colormap_index = -1; img->colormap_version = 0; img->NormalHs = NullHs; img->MipmapHs = NullHs; img->last_scale_hs = NullHs; img->last_scale_type = -1; img->Palette = NULL; img->extent.width = w; img->extent.height = h; img->NormalImg = TFB_DrawCanvas_New_ForScreen (w, h, withalpha); return img; } TFB_Image * TFB_DrawImage_New_Rotated (TFB_Image *img, int angle) { TFB_Canvas dst; EXTENT size; TFB_Image* newimg; /* sanity check */ if (!img->NormalImg) { log_add (log_Warning, "TFB_DrawImage_New_Rotated: " "source canvas is NULL! Failing."); return NULL; } TFB_DrawCanvas_GetRotatedExtent (img->NormalImg, angle, &size); dst = TFB_DrawCanvas_New_RotationTarget (img->NormalImg, angle); if (!dst) { log_add (log_Warning, "TFB_DrawImage_New_Rotated: " "rotation target canvas not created! Failing."); return NULL; } TFB_DrawCanvas_Rotate (img->NormalImg, dst, angle, size); newimg = TFB_DrawImage_New (dst); return newimg; } void TFB_DrawImage_Delete (TFB_Image *image) { if (image == 0) { log_add (log_Warning, "INTERNAL ERROR: Tried to delete a null image!"); /* Should we die here? */ return; } LockMutex (image->mutex); TFB_DrawCanvas_Delete (image->NormalImg); if (image->ScaledImg) { TFB_DrawCanvas_Delete (image->ScaledImg); } if (image->Palette) HFree (image->Palette); UnlockMutex (image->mutex); DestroyMutex (image->mutex); HFree (image); } void TFB_DrawImage_FixScaling (TFB_Image *image, int target, int type) { EXTENT old = image->extent; HOT_SPOT oldhs = image->last_scale_hs; TFB_DrawCanvas_GetScaledExtent (image->NormalImg, image->NormalHs, image->MipmapImg, image->MipmapHs, target, &image->extent, &image->last_scale_hs); if ((old.width != image->extent.width) || (old.height != image->extent.height) || image->dirty || !image->ScaledImg || type != image->last_scale_type || (oldhs.x != image->last_scale_hs.x) || (oldhs.y != image->last_scale_hs.y)) { image->dirty = FALSE; image->ScaledImg = TFB_DrawCanvas_New_ScaleTarget (image->NormalImg, image->ScaledImg, type, image->last_scale_type); image->last_scale_type = type; if (type == TFB_SCALE_NEAREST) TFB_DrawCanvas_Rescale_Nearest (image->NormalImg, image->ScaledImg, image->extent); else TFB_DrawCanvas_Rescale_Trilinear (image->NormalImg, image->ScaledImg, image->MipmapImg, image->extent); } } uqm-0.6.2/sc2/src/sc2code/libs/graphics/pixmap.c0000600000175000017500000000666110543202053020005 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" FRAME CaptureDrawable (DRAWABLE Drawable) { DRAWABLEPTR DrawablePtr; DrawablePtr = LockDrawable (Drawable); if (DrawablePtr) { COUNT FrameIndex; FrameIndex = GetDrawableIndex (Drawable); return ((FRAME)&DrawablePtr->Frame[FrameIndex]); } return (0); } DRAWABLE ReleaseDrawable (FRAMEPTR FramePtr) { if (FramePtr != 0) { DRAWABLE Drawable; DRAWABLEPTR DrawablePtr; DrawablePtr = GetFrameParentDrawable (FramePtr); Drawable = BUILD_DRAWABLE (DrawablePtr->hDrawable, FramePtr->Index); UnlockDrawable (Drawable); return (Drawable); } return (0); } MEM_HANDLE GetFrameHandle (FRAMEPTR FramePtr) { DRAWABLEPTR DrawablePtr; if (FramePtr == 0) return (0); DrawablePtr = GetFrameParentDrawable (FramePtr); return (DrawablePtr->hDrawable); } COUNT GetFrameCount (FRAMEPTR FramePtr) { DRAWABLEPTR DrawablePtr; if (FramePtr == 0) return (0); DrawablePtr = GetFrameParentDrawable (FramePtr); return DrawablePtr->MaxIndex + 1; } COUNT GetFrameIndex (FRAMEPTR FramePtr) { if (FramePtr == 0) return (0); return FramePtr->Index; } FRAME SetAbsFrameIndex (FRAMEPTR FramePtr, COUNT FrameIndex) { if (FramePtr != 0) { DRAWABLEPTR DrawablePtr; DrawablePtr = GetFrameParentDrawable (FramePtr); FrameIndex = FrameIndex % (DrawablePtr->MaxIndex + 1); FramePtr = (FRAMEPTR)&DrawablePtr->Frame[FrameIndex]; } return ((FRAME)FramePtr); } FRAME SetRelFrameIndex (FRAMEPTR FramePtr, SIZE FrameOffs) { if (FramePtr != 0) { COUNT num_frames; DRAWABLEPTR DrawablePtr; DrawablePtr = GetFrameParentDrawable (FramePtr); num_frames = DrawablePtr->MaxIndex + 1; if (FrameOffs < 0) { while ((FrameOffs += num_frames) < 0) ; } FrameOffs = ((SWORD)FramePtr->Index + FrameOffs) % num_frames; FramePtr = (FRAMEPTR)&DrawablePtr->Frame[FrameOffs]; } return ((FRAME)FramePtr); } FRAME SetEquFrameIndex (FRAMEPTR DstFramePtr, FRAMEPTR SrcFramePtr) { if (DstFramePtr && SrcFramePtr) return ((FRAME)( (PBYTE)((GetFrameParentDrawable (DstFramePtr))->Frame) + ((PBYTE)SrcFramePtr - (PBYTE)((GetFrameParentDrawable (SrcFramePtr))->Frame)) )); return (0); } FRAME IncFrameIndex (FRAMEPTR FramePtr) { DRAWABLEPTR DrawablePtr; if (FramePtr == 0) return (0); DrawablePtr = GetFrameParentDrawable (FramePtr); if (FramePtr->Index < DrawablePtr->MaxIndex) return ((FRAME)++FramePtr); else return ((FRAME)DrawablePtr->Frame); } FRAME DecFrameIndex (FRAMEPTR FramePtr) { if (FramePtr == 0) return (0); if (FramePtr->Index > 0) return ((FRAME)--FramePtr); else { DRAWABLEPTR DrawablePtr; DrawablePtr = GetFrameParentDrawable (FramePtr); return ((FRAME)&DrawablePtr->Frame[DrawablePtr->MaxIndex]); } } uqm-0.6.2/sc2/src/sc2code/libs/graphics/drawable.c0000600000175000017500000001226110543202054020262 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" #include "misc.h" #include "tfb_draw.h" #include "units.h" #include "libs/mathlib.h" #include "gfxother.h" FRAMEPTR _CurFramePtr; FRAME SetContextFGFrame (FRAME Frame) { FRAME LastFrame; if (Frame != (LastFrame = (FRAME)_CurFramePtr)) { if (LastFrame) DeactivateDrawable (); _CurFramePtr = (FRAMEPTR)Frame; if (_CurFramePtr) ActivateDrawable (); if (ContextActive ()) { SwitchContextFGFrame (Frame); } } return (LastFrame); } DRAWABLE CreateDisplay (CREATE_FLAGS CreateFlags, PSIZE pwidth, PSIZE pheight) { DRAWABLE Drawable; if (!DisplayActive ()) return (0); Drawable = _request_drawable (1, SCREEN_DRAWABLE, (CreateFlags & (WANT_PIXMAP | (GetDisplayFlags () & WANT_MASK))), GetDisplayWidth (), GetDisplayHeight ()); if (Drawable) { FRAMEPTR F; if ((F = CaptureDrawable (Drawable)) == 0) DestroyDrawable (Drawable); else { *pwidth = GetFrameWidth (F); *pheight = GetFrameHeight (F); ReleaseDrawable (F); return (Drawable); } } *pwidth = *pheight = 0; return (0); } DRAWABLE AllocDrawable (COUNT n) { DRAWABLE Drawable; Drawable = (DRAWABLE)mem_allocate ((MEM_SIZE)(sizeof (DRAWABLE_DESC)), MEM_ZEROINIT | MEM_GRAPHICS, DRAWABLE_PRIORITY, MEM_SIMPLE); if (Drawable) { DRAWABLEPTR DrawablePtr; int i; DrawablePtr = LockDrawable (Drawable); DrawablePtr->Frame = (FRAMEPTR)HMalloc ((MEM_SIZE)(sizeof (FRAME_DESC) * n)); /* Zero out the newly allocated frames, since HMalloc doesn't have MEM_ZEROINIT. */ for (i = 0; i < n; i++) { FRAMEPTR F; F = &DrawablePtr->Frame[i]; F->parent = DrawablePtr; F->Type = 0; F->Index = 0; F->image = 0; F->Bounds.width = F->Bounds.height = 0; F->HotSpot.x = F->HotSpot.y = 0; } UnlockDrawable (Drawable); } return Drawable; } DRAWABLE CreateDrawable (CREATE_FLAGS CreateFlags, SIZE width, SIZE height, COUNT num_frames) { DRAWABLE Drawable; if (!DisplayActive ()) return (0); Drawable = _request_drawable (num_frames, RAM_DRAWABLE, (CreateFlags & (WANT_MASK | WANT_PIXMAP | WANT_ALPHA | MAPPED_TO_DISPLAY)), width, height); if (Drawable) { FRAMEPTR F; F = CaptureDrawable (Drawable); if (F) { ReleaseDrawable (F); return (Drawable); } } return (0); } BOOLEAN DestroyDrawable (DRAWABLE Drawable) { DRAWABLEPTR DrawablePtr; if (LOWORD (Drawable) == GetFrameHandle (_CurFramePtr)) SetContextFGFrame ((FRAME)0); DrawablePtr = LockDrawable (Drawable); if (DrawablePtr) { UnlockDrawable (Drawable); FreeDrawable (Drawable); return (TRUE); } return (FALSE); } BOOLEAN GetFrameRect (FRAMEPTR FramePtr, PRECT pRect) { if (FramePtr) { pRect->corner.x = -FramePtr->HotSpot.x; pRect->corner.y = -FramePtr->HotSpot.y; pRect->extent.width = GetFrameWidth (FramePtr); pRect->extent.height = GetFrameHeight (FramePtr); return (TRUE); } return (FALSE); } HOT_SPOT SetFrameHot (FRAMEPTR FramePtr, HOT_SPOT HotSpot) { if (FramePtr) { HOT_SPOT OldHot; OldHot = FramePtr->HotSpot; FramePtr->HotSpot = HotSpot; return (OldHot); } return (MAKE_HOT_SPOT (0, 0)); } HOT_SPOT GetFrameHot (FRAMEPTR FramePtr) { if (FramePtr) { return FramePtr->HotSpot; } return (MAKE_HOT_SPOT (0, 0)); } DRAWABLE RotateFrame (FRAMEPTR Frame, COUNT angle) { DRAWABLE Drawable; FRAMEPTR RotFramePtr; SIZE dx, dy; SIZE d; COUNT organg; Drawable = _request_drawable (1, RAM_DRAWABLE, WANT_PIXMAP, 0, 0); if (!Drawable) return 0; RotFramePtr = CaptureDrawable (Drawable); if (!RotFramePtr) { FreeDrawable (Drawable); return 0; } RotFramePtr->image = TFB_DrawImage_New_Rotated ( Frame->image, -ANGLE_TO_DEGREES (angle)); SetFrameBounds (RotFramePtr, RotFramePtr->image->extent.width, RotFramePtr->image->extent.height); /* now we need to rotate the hot-spot, eww */ dx = Frame->HotSpot.x - (GetFrameWidth (Frame) / 2); dy = Frame->HotSpot.y - (GetFrameHeight (Frame) / 2); d = square_root ((long)dx*dx + (long)dy*dy); if (d != 0) { organg = ARCTAN (dx, dy); dx = COSINE (organg + angle, d); dy = SINE (organg + angle, d); } RotFramePtr->HotSpot.x = (GetFrameWidth (RotFramePtr) / 2) + dx; RotFramePtr->HotSpot.y = (GetFrameHeight (RotFramePtr) / 2) + dy; ReleaseDrawable (RotFramePtr); return Drawable; } void SetFrameTransparentColor (FRAMEPTR Frame, COLOR c32k) { TFB_Palette color; COLORtoPalette (c32k, &color); TFB_DrawCanvas_SetTransparentColor (Frame->image->NormalImg, color.r, color.g, color.b, FALSE); } uqm-0.6.2/sc2/src/sc2code/libs/graphics/drawcmd.h0000600000175000017500000001006310543202054020125 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef DRAWCMD_H #define DRAWCMD_H #include "graphics/tfb_draw.h" enum { TFB_DRAWCOMMANDTYPE_LINE, TFB_DRAWCOMMANDTYPE_RECTANGLE, TFB_DRAWCOMMANDTYPE_IMAGE, TFB_DRAWCOMMANDTYPE_FILLEDIMAGE, TFB_DRAWCOMMANDTYPE_FONTCHAR, TFB_DRAWCOMMANDTYPE_COPY, TFB_DRAWCOMMANDTYPE_COPYTOIMAGE, TFB_DRAWCOMMANDTYPE_SCISSORENABLE, TFB_DRAWCOMMANDTYPE_SCISSORDISABLE, TFB_DRAWCOMMANDTYPE_SETPALETTE, TFB_DRAWCOMMANDTYPE_SETMIPMAP, TFB_DRAWCOMMANDTYPE_DELETEIMAGE, TFB_DRAWCOMMANDTYPE_DELETEDATA, TFB_DRAWCOMMANDTYPE_SENDSIGNAL, TFB_DRAWCOMMANDTYPE_REINITVIDEO, }; typedef struct tfb_dc_line { int x1, y1, x2, y2; int r, g, b; SCREEN destBuffer; } TFB_DrawCommand_Line; typedef struct tfb_dc_rect { RECT rect; int r, g, b; SCREEN destBuffer; } TFB_DrawCommand_Rect; typedef struct tfb_dc_img { TFB_Image *image; int x, y; SCREEN destBuffer; TFB_ColorMap *colormap; int scale; } TFB_DrawCommand_Image; typedef struct tfb_dc_filledimg { TFB_Image *image; int x, y; int r, g, b; SCREEN destBuffer; int scale; } TFB_DrawCommand_FilledImage; typedef struct tfb_dc_fontchar { TFB_Char *fontchar; TFB_Image *backing; int x, y; SCREEN destBuffer; } TFB_DrawCommand_FontChar; typedef struct tfb_dc_copy { int x, y, w, h; SCREEN srcBuffer, destBuffer; } TFB_DrawCommand_Copy; typedef struct tfb_dc_copyimg { TFB_Image *image; int x, y, w, h; SCREEN srcBuffer; } TFB_DrawCommand_CopyToImage; typedef struct tfb_dc_scissor { int x, y, w, h; } TFB_DrawCommand_Scissor; typedef struct tfb_dc_setpal { int index; int r, g, b; } TFB_DrawCommand_SetPalette; typedef struct tfb_dc_setmip { TFB_Image *image; TFB_Canvas mipmap; int hotx, hoty; } TFB_DrawCommand_SetMipmap; typedef struct tfb_dc_delimg { TFB_Image *image; } TFB_DrawCommand_DeleteImage; typedef struct tfb_dc_deldata { void *data; // data must be a result of HXalloc() call } TFB_DrawCommand_DeleteData; typedef struct tfb_dc_signal { Semaphore sem; } TFB_DrawCommand_SendSignal; typedef struct tfb_dc_reinit_video { int driver, flags, width, height; } TFB_DrawCommand_ReinitVideo; typedef struct tfb_drawcommand { int Type; union { TFB_DrawCommand_Line line; TFB_DrawCommand_Rect rect; TFB_DrawCommand_Image image; TFB_DrawCommand_FilledImage filledimage; TFB_DrawCommand_FontChar fontchar; TFB_DrawCommand_Copy copy; TFB_DrawCommand_CopyToImage copytoimage; TFB_DrawCommand_Scissor scissor; TFB_DrawCommand_SetPalette setpalette; TFB_DrawCommand_SetMipmap setmipmap; TFB_DrawCommand_DeleteImage deleteimage; TFB_DrawCommand_DeleteData deletedata; TFB_DrawCommand_SendSignal sendsignal; TFB_DrawCommand_ReinitVideo reinitvideo; } data; } TFB_DrawCommand; // Queue Stuff typedef struct tfb_drawcommandqueue { int Front; int Back; int InsertionPoint; int Batching; volatile int FullSize; volatile int Size; } TFB_DrawCommandQueue; void Init_DrawCommandQueue (void); void Uninit_DrawCommandQueue (void); void TFB_BatchGraphics (void); void TFB_UnbatchGraphics (void); void TFB_BatchReset (void); void TFB_DrawCommandQueue_Push (TFB_DrawCommand* Command); int TFB_DrawCommandQueue_Pop (TFB_DrawCommand* Command); void TFB_DrawCommandQueue_Clear (void); extern TFB_DrawCommandQueue DrawCommandQueue; void TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand); void Lock_DCQ (int slots); void Unlock_DCQ (void); #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/widgets.h0000600000175000017500000001540210543202053020153 0ustar joeyjoey// Copyright Michael Martin, 2004. /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _WIDGETS_H #define _WIDGETS_H #include "libs/gfxlib.h" enum { WIDGET_EVENT_UP, WIDGET_EVENT_DOWN, WIDGET_EVENT_LEFT, WIDGET_EVENT_RIGHT, WIDGET_EVENT_SELECT, WIDGET_EVENT_CANCEL, WIDGET_EVENT_DELETE, NUM_WIDGET_EVENTS }; typedef enum { WIDGET_TYPE_MENU_SCREEN, WIDGET_TYPE_CHOICE, WIDGET_TYPE_BUTTON, WIDGET_TYPE_LABEL, WIDGET_TYPE_SLIDER, WIDGET_TYPE_TEXTENTRY, WIDGET_TYPE_CONTROLENTRY, NUM_WIDGET_TYPES } WIDGET_TYPE; #define WIDGET_TEXTENTRY_WIDTH 50 #define WIDGET_CONTROLENTRY_WIDTH 16 typedef struct _widget { WIDGET_TYPE tag; struct _widget *parent; int (*handleEvent)(struct _widget *self, int event); int (*receiveFocus)(struct _widget *self, int event); void (*draw)(struct _widget *self, int x, int y); int (*height)(struct _widget *self); int (*width)(struct _widget *self); } WIDGET; typedef struct _widget_menu_screen { WIDGET_TYPE tag; struct _widget *parent; int (*handleEvent)(struct _widget *self, int event); int (*receiveFocus)(struct _widget *self, int event); void (*draw)(struct _widget *self, int x, int y); int (*height)(struct _widget *self); int (*width)(struct _widget *self); const char *title; const char *subtitle; STAMP bgStamp; int num_children; struct _widget **child; int highlighted; } WIDGET_MENU_SCREEN; typedef struct { const char *optname; const char *tooltip[3]; } CHOICE_OPTION; typedef struct _widget_choice { WIDGET_TYPE tag; struct _widget *parent; int (*handleEvent)(struct _widget *self, int event); int (*receiveFocus)(struct _widget *self, int event); void (*draw)(struct _widget *self, int x, int y); int (*height)(struct _widget *self); int (*width)(struct _widget *self); const char *category; int numopts; int maxcolumns; CHOICE_OPTION *options; int selected, highlighted; void (*onChange)(struct _widget_choice *self, int oldval); } WIDGET_CHOICE; typedef struct _widget_button { WIDGET_TYPE tag; struct _widget *parent; int (*handleEvent)(struct _widget *self, int event); int (*receiveFocus)(struct _widget *self, int event); void (*draw)(struct _widget *self, int x, int y); int (*height)(struct _widget *self); int (*width)(struct _widget *self); const char *name; const char *tooltip[3]; } WIDGET_BUTTON; typedef struct _widget_label { WIDGET_TYPE tag; struct _widget *parent; int (*handleEvent)(struct _widget *self, int event); int (*receiveFocus)(struct _widget *self, int event); void (*draw)(struct _widget *self, int x, int y); int (*height)(struct _widget *self); int (*width)(struct _widget *self); int line_count; const char **lines; } WIDGET_LABEL; typedef struct _widget_slider { WIDGET_TYPE tag; struct _widget *parent; int (*handleEvent)(struct _widget *self, int event); int (*receiveFocus)(struct _widget *self, int event); void (*draw)(struct _widget *self, int x, int y); int (*height)(struct _widget *self); int (*width)(struct _widget *self); void (*draw_value)(struct _widget_slider *self, int x, int y); int min, max, step; int value; const char *category; const char *tooltip[3]; } WIDGET_SLIDER; typedef enum { WTE_NORMAL = 0, WTE_EDITING, WTE_BLOCKCUR, } WIDGET_TEXTENTRY_STATE; typedef struct _widget_textentry { WIDGET_TYPE tag; struct _widget *parent; int (*handleEvent)(struct _widget *self, int event); int (*receiveFocus)(struct _widget *self, int event); void (*draw)(struct _widget *self, int x, int y); int (*height)(struct _widget *self); int (*width)(struct _widget *self); int (*handleEventSelect)(struct _widget_textentry *self); // handleEventSelect is an overridable callback event // called by the default handleEvent implementation // can be NULL, in which case SELECT is ignored void (*onChange)(struct _widget_textentry *self); const char *category; char value[WIDGET_TEXTENTRY_WIDTH]; int maxlen; WIDGET_TEXTENTRY_STATE state; int cursor_pos; } WIDGET_TEXTENTRY; typedef struct _widget_controlentry { WIDGET_TYPE tag; struct _widget *parent; int (*handleEvent)(struct _widget *self, int event); int (*receiveFocus)(struct _widget *self, int event); void (*draw)(struct _widget *self, int x, int y); int (*height)(struct _widget *self); int (*width)(struct _widget *self); void (*onChange)(struct _widget_controlentry *self); void (*onDelete)(struct _widget_controlentry *self); const char *category; int controlindex; int highlighted; char controlname[2][WIDGET_CONTROLENTRY_WIDTH]; } WIDGET_CONTROLENTRY; void DrawShadowedBox (PRECT r, COLOR bg, COLOR dark, COLOR medium); void DrawLabelAsWindow(WIDGET_LABEL *label); int Widget_Event (int event); /* Methods for filling in widgets with */ int Widget_ReceiveFocusMenuScreen (WIDGET *_self, int event); int Widget_ReceiveFocusChoice (WIDGET *_self, int event); int Widget_ReceiveFocusSimple (WIDGET *_self, int event); int Widget_ReceiveFocusSlider (WIDGET *_self, int event); int Widget_ReceiveFocusControlEntry (WIDGET *_self, int event); int Widget_ReceiveFocusRefuseFocus (WIDGET *_self, int event); int Widget_HandleEventMenuScreen (WIDGET *_self, int event); int Widget_HandleEventChoice (WIDGET *_self, int event); int Widget_HandleEventSlider (WIDGET *_self, int event); int Widget_HandleEventTextEntry (WIDGET *_self, int event); int Widget_HandleEventControlEntry (WIDGET *_self, int event); int Widget_HandleEventIgnoreAll (WIDGET *_self, int event); int Widget_HeightChoice (WIDGET *_self); int Widget_HeightFullScreen (WIDGET *_self); int Widget_HeightOneLine (WIDGET *_self); int Widget_HeightLabel (WIDGET *_self); int Widget_WidthFullScreen (WIDGET *_self); void Widget_DrawMenuScreen (WIDGET *_self, int x, int y); void Widget_DrawChoice (WIDGET *_self, int x, int y); void Widget_DrawButton (WIDGET *_self, int x, int y); void Widget_DrawLabel (WIDGET *_self, int x, int y); void Widget_DrawSlider (WIDGET *_self, int x, int y); void Widget_DrawTextEntry (WIDGET *_self, int x, int y); void Widget_DrawControlEntry (WIDGET *_self, int x, int y); void Widget_Slider_DrawValue (WIDGET_SLIDER *self, int x, int y); /* Other implementations will need these values */ extern WIDGET *widget_focus; #endif /* _WIDGETS_H */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/cmap.c0000600000175000017500000003002510543202054017417 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfx_common.h" #include "libs/tasklib.h" #include "libs/log.h" #include static struct { COLORMAPPTR CMapPtr; SIZE Ticks; union { COUNT NumCycles; Task XFormTask; } tc; } FadeControl; typedef struct xform_control { int CMapIndex; // -1 means unused COLORMAPPTR CMapPtr; SIZE Ticks; DWORD StartTime; DWORD EndTime; TFB_Palette OldCMap[NUMBER_OF_PLUTVALS]; } XFORM_CONTROL; #define MAX_XFORMS 16 static struct { XFORM_CONTROL TaskControl[MAX_XFORMS]; volatile int Highest; // 'pending' is Highest >= 0 Mutex Lock; } XFormControl; volatile int FadeAmount = FADE_NORMAL_INTENSITY; static volatile int FadeEnd, XForming; #define SPARE_COLORMAPS 20 #define MAP_POOL_SIZE (MAX_COLORMAPS + SPARE_COLORMAPS) static TFB_ColorMap mappool[MAP_POOL_SIZE]; static TFB_ColorMap *poolhead; static TFB_ColorMap * colormaps[MAX_COLORMAPS]; static int mapcount; Mutex maplock; void InitColorMaps (void) { int i; // init colormaps maplock = CreateMutex ("Colormaps Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); // init static pool for (i = 0; i < MAP_POOL_SIZE - 1; ++i) mappool[i].next = mappool + i + 1; mappool[i].next = NULL; poolhead = mappool; // init xform control XFormControl.Highest = -1; XFormControl.Lock = CreateMutex ("Transform Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); for (i = 0; i < MAX_XFORMS; ++i) XFormControl.TaskControl[i].CMapIndex = -1; } void UninitColorMaps (void) { // uninit xform control DestroyMutex (XFormControl.Lock); // uninit colormaps DestroyMutex (maplock); } static inline TFB_ColorMap * alloc_colormap (void) // returns an addrefed object { TFB_ColorMap *map; if (!poolhead) return NULL; map = poolhead; poolhead = map->next; map->next = NULL; map->index = -1; map->refcount = 1; map->version = 0; return map; } static TFB_ColorMap * clone_colormap (TFB_ColorMap *from, int index) // returns an addrefed object { TFB_ColorMap *map; map = alloc_colormap (); if (!map) { static DWORD NextTime = 0; DWORD Now; if (!from) { log_add (log_Warning, "FATAL: clone_colormap(): " "no maps available"); exit (EXIT_FAILURE); } Now = GetTimeCounter (); if (Now >= NextTime) { log_add (log_Warning, "clone_colormap(): static pool exhausted"); NextTime = Now + ONE_SECOND; } // just overwrite the current one -- better than aborting map = from; from->refcount++; } else { // fresh new map map->index = index; if (from) map->version = from->version; } map->version++; return map; } static inline void free_colormap (TFB_ColorMap *map) { if (!map) { log_add (log_Warning, "free_colormap(): tried to free a NULL map"); return; } map->next = poolhead; poolhead = map; } static inline TFB_ColorMap * get_colormap (int index) { TFB_ColorMap *map; map = colormaps[index]; if (!map) { log_add (log_Fatal, "BUG: get_colormap(): map not present"); exit (EXIT_FAILURE); } map->refcount++; return map; } static inline void release_colormap (TFB_ColorMap *map) { if (!map) return; if (map->refcount <= 0) { log_add (log_Warning, "BUG: release_colormap(): refcount not >0"); return; } map->refcount--; if (map->refcount == 0) free_colormap (map); } void TFB_ReturnColorMap (TFB_ColorMap *map) { LockMutex (maplock); release_colormap (map); UnlockMutex (maplock); } TFB_ColorMap * TFB_GetColorMap (int index) { TFB_ColorMap *map; LockMutex (maplock); map = get_colormap (index); UnlockMutex (maplock); return map; } void TFB_ColorMapToRGB (TFB_Palette *pal, int index) { TFB_ColorMap *map = NULL; if (index < mapcount) map = colormaps[index]; if (!map) { log_add (log_Warning, "TFB_ColorMapToRGB(): " "requested non-present colormap %d", index); return; } memcpy (pal, map->colors, sizeof (map->colors)); } BOOLEAN SetColorMap (COLORMAPPTR map) { int start, end; int total_size; UBYTE *colors = (UBYTE*)map; TFB_ColorMap **mpp; if (!map) return TRUE; start = *colors++; end = *colors++; if (start > end) { log_add (log_Warning, "ERROR: SetColorMap(): " "starting map (%d) not less or eq ending (%d)", start, end); return FALSE; } if (start >= MAX_COLORMAPS) { log_add (log_Warning, "ERROR: SetColorMap(): " "starting map (%d) beyond range (0-%d)", start, (int)MAX_COLORMAPS - 1); return FALSE; } if (end >= MAX_COLORMAPS) { log_add (log_Warning, "SetColorMap(): " "ending map (%d) beyond range (0-%d)\n", end, (int)MAX_COLORMAPS - 1); end = MAX_COLORMAPS - 1; } total_size = end + 1; LockMutex (maplock); if (total_size > mapcount) mapcount = total_size; // parse the supplied PLUTs into our colormaps for (mpp = colormaps + start; start <= end; ++start, ++mpp) { int i; TFB_Palette *pal; TFB_ColorMap *newmap; TFB_ColorMap *oldmap; oldmap = *mpp; newmap = clone_colormap (oldmap, start); for (i = 0, pal = newmap->colors; i < NUMBER_OF_PLUTVALS; ++i, ++pal) { pal->r = *colors++; pal->g = *colors++; pal->b = *colors++; } *mpp = newmap; release_colormap (oldmap); } UnlockMutex (maplock); return TRUE; } /* Fade Transforms */ static int fade_xform_task (void *data) { SIZE TDelta, TTotal; DWORD CurTime; Task task = (Task)data; XForming = TRUE; while (FadeControl.tc.XFormTask == 0 && (!Task_ReadState (task, TASK_EXIT))) TaskSwitch (); TTotal = FadeControl.Ticks; FadeControl.tc.XFormTask = 0; { CurTime = GetTimeCounter (); do { DWORD StartTime; StartTime = CurTime; SleepThreadUntil (CurTime + ONE_SECOND / 60); CurTime = GetTimeCounter (); if (!XForming || (TDelta = (SIZE)(CurTime - StartTime)) > TTotal) TDelta = TTotal; FadeAmount += (FadeEnd - FadeAmount) * TDelta / TTotal; //log_add (log_Debug, "fade_xform_task FadeAmount %d\n", FadeAmount); } while ((TTotal -= TDelta) && (!Task_ReadState (task, TASK_EXIT))); } XForming = FALSE; FinishTask (task); return 0; } static void FlushFadeXForms (void) { if (XForming) { XForming = FALSE; TaskSwitch (); } } static DWORD XFormFade (COLORMAPPTR ColorMapPtr, SIZE TimeInterval) { BYTE what; DWORD TimeOut; FlushFadeXForms (); what = *ColorMapPtr; switch (what) { case FadeAllToBlack: case FadeSomeToBlack: FadeEnd = FADE_NO_INTENSITY; break; case FadeAllToColor: case FadeSomeToColor: FadeEnd = FADE_NORMAL_INTENSITY; break; case FadeAllToWhite: case FadeSomeToWhite: FadeEnd = FADE_FULL_INTENSITY; break; default: return (GetTimeCounter ()); } FadeControl.Ticks = TimeInterval; if (FadeControl.Ticks <= 0 || (FadeControl.tc.XFormTask = AssignTask (fade_xform_task, 1024, "fade transform")) == 0) { FadeAmount = FadeEnd; TimeOut = GetTimeCounter (); } else { do TaskSwitch (); while (FadeControl.tc.XFormTask); TimeOut = GetTimeCounter () + TimeInterval + 1; } return (TimeOut); } /* Colormap Transforms */ static void finish_colormap_xform (int which) { SetColorMap (XFormControl.TaskControl[which].CMapPtr); XFormControl.TaskControl[which].CMapIndex = -1; // check Highest ptr if (which == XFormControl.Highest) { do --which; while (which >= 0 && XFormControl.TaskControl[which].CMapIndex == -1); XFormControl.Highest = which; } } /* This gives the XFormColorMap task a timeslice to do its thing * Only one thread should ever be allowed to be calling this at any time */ BOOLEAN XFormColorMap_step (void) { BOOLEAN Changed = FALSE; int x; DWORD Now = GetTimeCounter (); LockMutex (XFormControl.Lock); for (x = 0; x <= XFormControl.Highest; ++x) { XFORM_CONTROL *control = &XFormControl.TaskControl[x]; int index = control->CMapIndex; int TicksLeft = control->EndTime - Now; TFB_ColorMap *curmap; if (index < 0) continue; // unused slot LockMutex (maplock); curmap = colormaps[index]; if (!curmap) { UnlockMutex (maplock); log_add (log_Error, "BUG: XFormColorMap_step(): no current map"); finish_colormap_xform (x); continue; } if (TicksLeft > 0) { #define XFORM_SCALE 0x10000 TFB_ColorMap *newmap = NULL; UBYTE *pNewCMap; TFB_Palette *pCurCMap, *pOldCMap; int frac; int i; newmap = clone_colormap (curmap, index); pCurCMap = newmap->colors; pOldCMap = control->OldCMap; pNewCMap = (UBYTE*)control->CMapPtr + 2; frac = (int)(control->Ticks - TicksLeft) * XFORM_SCALE / control->Ticks; for (i = 0; i < NUMBER_OF_PLUTVALS; i++, ++pCurCMap, ++pOldCMap) { pCurCMap->r = (UBYTE)(pOldCMap->r + ((int)*pNewCMap - pOldCMap->r) * frac / XFORM_SCALE); pNewCMap++; pCurCMap->g = (UBYTE)(pOldCMap->g + ((int)*pNewCMap - pOldCMap->g) * frac / XFORM_SCALE); pNewCMap++; pCurCMap->b = (UBYTE)(pOldCMap->b + ((int)*pNewCMap - pOldCMap->b) * frac / XFORM_SCALE); pNewCMap++; } colormaps[index] = newmap; release_colormap (curmap); } UnlockMutex (maplock); if (TicksLeft <= 0) { // asked for immediate xform or already done finish_colormap_xform (x); } Changed = TRUE; } UnlockMutex (XFormControl.Lock); return Changed; } static void FlushPLUTXForms (void) { int i; LockMutex (XFormControl.Lock); for (i = 0; i <= XFormControl.Highest; ++i) { if (XFormControl.TaskControl[i].CMapIndex >= 0) finish_colormap_xform (i); } XFormControl.Highest = -1; // all gone UnlockMutex (XFormControl.Lock); } static DWORD XFormPLUT (COLORMAPPTR ColorMapPtr, SIZE TimeInterval) { TFB_ColorMap *map; XFORM_CONTROL *control; int index; int x; int first_avail = -1; DWORD EndTime; DWORD Now; Now = GetTimeCounter (); index = *ColorMapPtr; LockMutex (XFormControl.Lock); // Find an available slot, or reuse if required for (x = 0; x <= XFormControl.Highest && index != XFormControl.TaskControl[x].CMapIndex; ++x) { if (first_avail == -1 && XFormControl.TaskControl[x].CMapIndex == -1) first_avail = x; } if (index == XFormControl.TaskControl[x].CMapIndex) { // already xforming this colormap -- cancel and reuse slot finish_colormap_xform (x); } else if (first_avail >= 0) { // picked up a slot along the way x = first_avail; } else if (x >= MAX_XFORMS) { // flush some xforms if the queue is full log_add (log_Debug, "WARNING: XFormPLUT(): no slots available"); x = XFormControl.Highest; finish_colormap_xform (x); } // take next unused one control = &XFormControl.TaskControl[x]; if (x > XFormControl.Highest) XFormControl.Highest = x; // make a copy of the current map LockMutex (maplock); map = colormaps[index]; if (!map) { UnlockMutex (maplock); UnlockMutex (XFormControl.Lock); log_add (log_Warning, "BUG: XFormPLUT(): no current map"); return (0); } memcpy (control->OldCMap, map->colors, sizeof (map->colors)); UnlockMutex (maplock); control->CMapIndex = index; control->CMapPtr = ColorMapPtr; control->Ticks = TimeInterval; if (control->Ticks < 0) control->Ticks = 0; /* prevent negative fade */ control->StartTime = Now; control->EndTime = EndTime = Now + control->Ticks; UnlockMutex (XFormControl.Lock); return (EndTime); } DWORD XFormColorMap (COLORMAPPTR ColorMapPtr, SIZE TimeInterval) { int what; if (!ColorMapPtr) return (0); what = *ColorMapPtr; if (what >= (int)FadeAllToWhite && what <= (int)FadeSomeToColor) return XFormFade (ColorMapPtr, TimeInterval); else return XFormPLUT (ColorMapPtr, TimeInterval); } void FlushColorXForms (void) { FlushFadeXForms (); FlushPLUTXForms (); } uqm-0.6.2/sc2/src/sc2code/libs/graphics/tfb_draw.h0000600000175000017500000001403010543202054020272 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TFB_DRAW_H #define TFB_DRAW_H #include "libs/threadlib.h" typedef void *TFB_Canvas; typedef enum { TFB_SCREEN_MAIN, TFB_SCREEN_EXTRA, TFB_SCREEN_TRANSITION, TFB_GFX_NUMSCREENS } SCREEN; typedef enum { TFB_SCALE_STEP, /* not really a scaler */ TFB_SCALE_NEAREST, TFB_SCALE_TRILINEAR } SCALE; typedef struct tfb_palette { UBYTE r; UBYTE g; UBYTE b; UBYTE unused; } TFB_Palette; #include "graphics/gfx_common.h" #include "cmap.h" typedef struct tfb_image { TFB_Canvas NormalImg; TFB_Canvas ScaledImg; TFB_Canvas MipmapImg; TFB_Canvas FilledImg; TFB_Palette *Palette; int colormap_index; int colormap_version; HOT_SPOT NormalHs; HOT_SPOT MipmapHs; HOT_SPOT last_scale_hs; int last_scale_type; TFB_Palette last_fill; EXTENT extent; Mutex mutex; BOOLEAN dirty; } TFB_Image; typedef struct tfb_char { EXTENT extent; EXTENT disp; // Display extent HOT_SPOT HotSpot; BYTE* data; DWORD pitch; // Pitch is for storing all chars of a page // in one rectangular pixel matrix } TFB_Char; // we do not support paletted format for now typedef struct tfb_pixelformat { int BitsPerPixel; int BytesPerPixel; DWORD Rmask, Gmask, Bmask, Amask; DWORD Rshift, Gshift, Bshift, Ashift; DWORD Rloss, Gloss, Bloss, Aloss; } TFB_PixelFormat; // Drawing commands void TFB_DrawScreen_Line (int x1, int y1, int x2, int y2, int r, int g, int b, SCREEN dest); void TFB_DrawScreen_Rect (PRECT rect, int r, int g, int b, SCREEN dest); void TFB_DrawScreen_Image (TFB_Image *img, int x, int y, int scale, TFB_ColorMap *cmap, SCREEN dest); void TFB_DrawScreen_Copy (PRECT r, SCREEN src, SCREEN dest); void TFB_DrawScreen_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int g, int b, SCREEN dest); void TFB_DrawScreen_FontChar (TFB_Char *, TFB_Image *backing, int x, int y, SCREEN dest); void TFB_DrawScreen_CopyToImage (TFB_Image *img, PRECT lpRect, SCREEN src); void TFB_DrawScreen_DeleteImage (TFB_Image *img); void TFB_DrawScreen_DeleteData (void *); void TFB_DrawScreen_WaitForSignal (void); void TFB_DrawScreen_ReinitVideo (int driver, int flags, int width, int height); void TFB_DrawScreen_SetPalette (int paletteIndex, int r, int g, int b); TFB_Image *TFB_DrawImage_New (TFB_Canvas canvas); TFB_Image *TFB_DrawImage_CreateForScreen (int w, int h, BOOLEAN withalpha); TFB_Image *TFB_DrawImage_New_Rotated (TFB_Image *img, int angle); void TFB_DrawImage_Delete (TFB_Image *image); void TFB_DrawImage_FixScaling (TFB_Image *image, int target, int type); 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, int scale, TFB_ColorMap *cmap, TFB_Image *target); void TFB_DrawImage_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int g, int b, TFB_Image *target); void TFB_DrawImage_FontChar (TFB_Char *, TFB_Image *backing, int x, int y, TFB_Image *target); TFB_Canvas TFB_DrawCanvas_New_TrueColor (int w, int h, BOOLEAN hasalpha); TFB_Canvas TFB_DrawCanvas_New_ForScreen (int w, int h, BOOLEAN withalpha); TFB_Canvas TFB_DrawCanvas_New_Paletted (int w, int h, TFB_Palette *palette, int transparent_index); TFB_Canvas TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas, TFB_Canvas oldcanvas, int type, int last_type); TFB_Canvas TFB_DrawCanvas_New_RotationTarget (TFB_Canvas src, int angle); TFB_Canvas TFB_DrawCanvas_ToScreenFormat (TFB_Canvas canvas); BOOLEAN TFB_DrawCanvas_IsPaletted (TFB_Canvas canvas); void TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src, TFB_Canvas dst, EXTENT size); void TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src, TFB_Canvas dst, TFB_Canvas mipmap, EXTENT size); void TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, HOT_SPOT src_hs, TFB_Canvas src_mipmap, HOT_SPOT mm_hs, int scale, PEXTENT size, HOT_SPOT *hs); void TFB_DrawCanvas_Rotate (TFB_Canvas src, TFB_Canvas dst, int angle, EXTENT size); void TFB_DrawCanvas_GetRotatedExtent (TFB_Canvas src, int angle, PEXTENT size); void TFB_DrawCanvas_GetExtent (TFB_Canvas canvas, PEXTENT size); void TFB_DrawCanvas_Delete (TFB_Canvas canvas); 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, int scale, TFB_ColorMap *cmap, TFB_Canvas target); void TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int g, int b, TFB_Canvas target); void TFB_DrawCanvas_FontChar (TFB_Char *, TFB_Image *backing, int x, int y, TFB_Canvas target); TFB_Palette *TFB_DrawCanvas_ExtractPalette (TFB_Canvas canvas); void TFB_DrawCanvas_SetPalette (TFB_Canvas target, TFB_Palette *palette); int TFB_DrawCanvas_GetTransparentIndex (TFB_Canvas canvas); void TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int i, BOOLEAN rleaccel); BOOLEAN TFB_DrawCanvas_GetTransparentColor (TFB_Canvas canvas, int *r, int *g, int *b); void TFB_DrawCanvas_SetTransparentColor (TFB_Canvas canvas, int r, int g, int b, BOOLEAN rleaccel); void TFB_DrawCanvas_Initialize (void); void TFB_DrawCanvas_GetScreenFormat (TFB_PixelFormat *fmt); void* TFB_DrawCanvas_GetLine (TFB_Canvas canvas, int line); void TFB_DrawCanvas_GetPixel (TFB_Canvas canvas, int x, int y, int *r, int *g, int *b); #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/tfb_prim.h0000600000175000017500000000224510543202053020310 0ustar joeyjoey// Copyright Michael Martin, 2003 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxlib.h" #include "tfb_draw.h" void TFB_Prim_Line (PLINE line, TFB_Palette *color); void TFB_Prim_Point (PPOINT p, TFB_Palette *color); void TFB_Prim_Rect (PRECT r, TFB_Palette *color); void TFB_Prim_FillRect (PRECT r, TFB_Palette *color); void TFB_Prim_Stamp (PSTAMP stamp); void TFB_Prim_StampFill (PSTAMP stamp, TFB_Palette *color); void TFB_Prim_FontChar (PPOINT origin, TFB_Char *, TFB_Image *backing); uqm-0.6.2/sc2/src/sc2code/libs/graphics/loaddisp.c0000600000175000017500000000264310543202053020302 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" /* LoadDisplay---Drawable Allocate a chunk of memory and read from the display into that chunk of memory. LoadDisplayPixmapDrawable() LoadDisplayMaskDrawable() LoadDisplayPixmapMaskDrawable() */ DRAWABLE LoadDisplayPixmap (PRECT area, FRAME frame) { DRAWABLE buffer; buffer = BUILD_DRAWABLE ( GetFrameHandle (frame), GetFrameIndex (frame) ); if (buffer || (buffer = CreateDrawable ( WANT_PIXMAP | MAPPED_TO_DISPLAY, area->extent.width, area->extent.height, 1)) ) { frame = CaptureDrawable (buffer); ReadDisplay (area, (FRAMEPTR)frame); ReleaseDrawable (frame); } return (buffer); } uqm-0.6.2/sc2/src/sc2code/libs/graphics/boxint.c0000600000175000017500000000776410543202053020017 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" #undef MIN #define MIN(a, b) (((a) <= (b)) ? (a) : (b)) #undef MAX #define MAX(a, b) (((a) >= (b)) ? (a) : (b)) INTERSECT_CODE BoxIntersect (PRECT pr1, PRECT pr2, PRECT pinter) { INTERSECT_CODE intersect_code; COORD x1; SIZE w1, w2, delta; intersect_code = INTERSECT_NOCLIP; x1 = pr1->corner.x - pr2->corner.x; w1 = pr1->extent.width; w2 = pr2->extent.width; if ((delta = w2 - x1) <= w1) { if (delta != w1) { w1 = delta; intersect_code &= ~INTERSECT_NOCLIP; } intersect_code |= INTERSECT_RIGHT; } if (x1 <= 0) { if (x1 < 0) { w1 += x1; x1 = 0; intersect_code &= ~INTERSECT_NOCLIP; } intersect_code |= INTERSECT_LEFT; } if (w1 > 0) { #define h2 w2 COORD y1; SIZE h1; y1 = pr1->corner.y - pr2->corner.y; h1 = pr1->extent.height; h2 = pr2->extent.height; if ((delta = h2 - y1) <= h1) { if (delta != h1) { h1 = delta; intersect_code &= ~INTERSECT_NOCLIP; } intersect_code |= INTERSECT_BOTTOM; } if (y1 <= 0) { if (y1 < 0) { h1 += y1; y1 = 0; intersect_code &= ~INTERSECT_NOCLIP; } intersect_code |= INTERSECT_TOP; } if (h1 > 0) { pinter->corner.x = x1 + pr2->corner.x; pinter->corner.y = y1 + pr2->corner.y; pinter->extent.width = w1; pinter->extent.height = h1; return (intersect_code); } #undef h2 } return ((INTERSECT_CODE)0); } void BoxUnion (PRECT pr1, PRECT pr2, PRECT punion) { #if NEVER // Part of lower FIXME. COORD x2, y2, w2, h2; #endif // NEVER // Union is A AND B, put together, correct? Returns a bigger box that // encompasses the two. punion->corner.x = MIN(pr1->corner.x, pr2->corner.x); punion->corner.y = MIN(pr1->corner.y, pr2->corner.y); punion->extent.width = MAX(pr1->corner.x + pr1->extent.width, pr2->corner.x + pr2->extent.width) - punion->corner.x; punion->extent.height = MAX(pr1->corner.y + pr1->extent.height, pr2->corner.y + pr2->extent.height) - punion->corner.y; #if NEVER // FIXME - I think this is broken, but keeping it around for reference // FIXME - just in case. #if 1 /* alter based on 0 widths */ x2 = (pr1->corner.x < pr2->corner.x)? pr1->corner.x : pr2->corner.x; y2 = (pr1->corner.y < pr2->corner.y)? pr1->corner.y : pr2->corner.y; w2 = ( ((pr1->corner.x + pr1->extent.width) > (pr2->corner.x + pr2->extent.width))? (pr1->corner.x + pr1->extent.width) : (pr2->corner.x + pr2->extent.width) ) - punion->corner.x; h2 = ( ((pr1->corner.y + pr1->extent.height) > (pr2->corner.y + pr2->extent.height))? (pr1->corner.y + pr1->extent.height) : (pr2->corner.y + pr2->extent.height) ) - punion->corner.y; #else SIZE delta; COORD x1, y1, w1, h1; x1 = pr1->corner.x; w1 = pr1->extent.width; x2 = pr2->corner.x; w2 = pr2->extent.width; if ((delta = x1 - x2) >= 0) w1 += delta; else { w2 -= delta; x2 += delta; } y1 = pr1->corner.y; h1 = pr1->extent.height; y2 = pr2->corner.y; h2 = pr2->extent.height; if ((delta = y1 - y2) >= 0) h1 += delta; else { h2 -= delta; y2 += delta; } if ((delta = w1 - w2) > 0) w2 += delta; if ((delta = h1 - h2) > 0) h2 += delta; #endif punion->corner.x = x2; punion->corner.y = y2; punion->extent.width = w2; punion->extent.height = h2; #endif // NEVER } uqm-0.6.2/sc2/src/sc2code/libs/graphics/display.h0000600000175000017500000000315610543202053020155 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _DISPLAY_H #define _DISPLAY_H typedef struct { CREATE_FLAGS DisplayFlags; BYTE DisplayDepth; COUNT DisplayWidth, DisplayHeight; DRAWABLE (*alloc_image) (COUNT NumFrames, DRAWABLE_TYPE DrawableType, CREATE_FLAGS flags, SIZE width, SIZE height); void (*read_display) (PRECT pRect, FRAMEPTR DstFramePtr); } DISPLAY_INTERFACE; typedef DISPLAY_INTERFACE *PDISPLAY_INTERFACE; extern PDISPLAY_INTERFACE _pCurDisplay; extern void (* mask_func_array[]) (PRECT pClipRect, PRIMITIVEPTR PrimPtr); #define AllocDrawableImage (*_pCurDisplay->alloc_image) #define ReadDisplay (*_pCurDisplay->read_display) #define GetDisplayFlags() (_pCurDisplay->DisplayFlags) #define GetDisplayDepth() (_pCurDisplay->DisplayDepth) #define GetDisplayWidth() (_pCurDisplay->DisplayWidth) #define GetDisplayHeight() (_pCurDisplay->DisplayHeight) #endif /* _DISPLAY_H */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/gfx_common.h0000600000175000017500000000520110543202053020635 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef GFX_COMMON_H #define GFX_COMMON_H #include #include #include "libs/gfxlib.h" #include "libs/vidlib.h" #include "libs/misc.h" // driver for TFB_InitGraphics enum { TFB_GFXDRIVER_SDL_OPENGL, TFB_GFXDRIVER_SDL_PURE, }; // flags for TFB_InitGraphics #define TFB_GFXFLAGS_FULLSCREEN (1<<0) #define TFB_GFXFLAGS_SHOWFPS (1<<1) #define TFB_GFXFLAGS_SCANLINES (1<<2) #define TFB_GFXFLAGS_SCALE_BILINEAR (1<<3) #define TFB_GFXFLAGS_SCALE_BIADAPT (1<<4) #define TFB_GFXFLAGS_SCALE_BIADAPTADV (1<<5) #define TFB_GFXFLAGS_SCALE_TRISCAN (1<<6) #define TFB_GFXFLAGS_SCALE_HQXX (1<<7) #define TFB_GFXFLAGS_SCALE_ANY \ ( TFB_GFXFLAGS_SCALE_BILINEAR | \ TFB_GFXFLAGS_SCALE_BIADAPT | \ TFB_GFXFLAGS_SCALE_BIADAPTADV | \ TFB_GFXFLAGS_SCALE_TRISCAN | \ TFB_GFXFLAGS_SCALE_HQXX ) #define TFB_GFXFLAGS_SCALE_SOFT_ONLY \ ( TFB_GFXFLAGS_SCALE_ANY & ~TFB_GFXFLAGS_SCALE_BILINEAR ) // The flag variable itself extern int GfxFlags; void TFB_PreInit (void); int TFB_InitGraphics (int driver, int flags, int width, int height); void TFB_UninitGraphics (void); void TFB_ProcessEvents (void); // 3DO Graphics Stuff #define GSCALE_IDENTITY 256 void LoadIntoExtraScreen (PRECT r); void DrawFromExtraScreen (PRECT r); void SetGraphicGrabOther (int grab_other); void SetGraphicScale (int scale); int GetGraphicScale (void); void SetGraphicUseOtherExtra (int other); void SetTransitionSource (PRECT pRect); void ScreenTransition (int transition, PRECT pRect); extern float FrameRate; extern int FrameRateTickBase; void TFB_FlushGraphics (void); // Only call from main thread!! void TFB_SetGamma (float gamma); // Unknown Stuff extern int ScreenWidth; extern int ScreenHeight; extern int ScreenWidthActual; extern int ScreenHeightActual; extern int ScreenColorDepth; extern int GraphicsDriver; #include "cmap.h" #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/cmap.h0000600000175000017500000000344510543202054017432 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "tfb_draw.h" #ifndef CMAP_H #define CMAP_H #define MAX_COLORMAPS 250 #define PLUTVAL_BYTE_SIZE 3 #define NUMBER_OF_PLUTVALS 256 #define PLUT_BYTE_SIZE (PLUTVAL_BYTE_SIZE * NUMBER_OF_PLUTVALS) #define BUILD_FRAME (1 << 0) #define FIND_PAGE (1 << 1) #define FIRST_BATCH (1 << 2) #define GRAB_OTHER (1 << 3) #define COLOR_CYCLE (1 << 4) #define CYCLE_PENDING (1 << 5) #define ENABLE_CYCLE (1 << 6) #define FADE_NO_INTENSITY 0 #define FADE_NORMAL_INTENSITY 255 #define FADE_FULL_INTENSITY 510 typedef struct tfb_colormap { TFB_Palette colors[NUMBER_OF_PLUTVALS]; int index; int version; int refcount; struct tfb_colormap *next; } TFB_ColorMap; extern volatile int FadeAmount; extern void InitColorMaps (void); extern void UninitColorMaps (void); extern void TFB_ColorMapToRGB (TFB_Palette *pal, int colormap_index); extern TFB_ColorMap * TFB_GetColorMap (int index); extern void TFB_ReturnColorMap (TFB_ColorMap *map); extern BOOLEAN XFormColorMap_step (void); #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/gfx_common.c0000600000175000017500000000345610543202054020643 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "libs/graphics/gfxintrn.h" #include "libs/input/inpintrn.h" #include "libs/graphics/gfx_common.h" #include "libs/graphics/drawcmd.h" PDISPLAY_INTERFACE _pCurDisplay; //Not a function. Probably has to be initialized... void (*mask_func_array[]) (PRECT pClipRect, PRIMITIVEPTR PrimPtr) = { 0 }; int ScreenWidth; int ScreenHeight; int ScreenWidthActual; int ScreenHeightActual; int ScreenColorDepth; int GraphicsDriver; int TFB_DEBUG_HALT = 0; // Status: Ignored (only used in fmv.c) void SetGraphicUseOtherExtra (int other) //Could this possibly be more cryptic?!? :) { //log_add (log_Debug, "SetGraphicUseOtherExtra %d", other); (void)other; /* lint */ } // Status: Ignored (only used in solarsys.c) void SetGraphicGrabOther (int grab_other) { //log_add (log_Debug, "SetGraphicGrabOther %d", grab_other); (void)grab_other; /* lint */ } void DrawFromExtraScreen (PRECT r) { TFB_DrawScreen_Copy(r, TFB_SCREEN_EXTRA, TFB_SCREEN_MAIN); } void LoadIntoExtraScreen (PRECT r) { TFB_DrawScreen_Copy(r, TFB_SCREEN_MAIN, TFB_SCREEN_EXTRA); } uqm-0.6.2/sc2/src/sc2code/libs/graphics/filegfx.c0000600000175000017500000000336410543202054020131 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" #include "options.h" #include "libs/reslib.h" DWORD LoadCelFile (PVOID pStr) { uio_Stream *fp; // FIXME: this theoretically needs a mechanism to prevent races if (_cur_resfile_name) // something else is loading resources atm return 0; fp = res_OpenResFile (contentDir, pStr, "rb"); if (fp != NULL) { MEM_HANDLE hData; _cur_resfile_name = pStr; hData = _GetCelData (fp, LengthResFile (fp)); _cur_resfile_name = 0; res_CloseResFile (fp); return ((DWORD)hData); } return (0); } DWORD LoadFontFile (PVOID pStr) { uio_Stream *fp; // FIXME: this theoretically needs a mechanism to prevent races if (_cur_resfile_name) // something else is loading resources atm return 0; fp = res_OpenResFile (contentDir, pStr, "rb"); if (fp == (uio_Stream *) ~0) { MEM_HANDLE hData; _cur_resfile_name = pStr; hData = _GetFontData (fp, LengthResFile (fp)); _cur_resfile_name = 0; res_CloseResFile (fp); return ((DWORD)hData); } return (0); } uqm-0.6.2/sc2/src/sc2code/libs/graphics/resgfx.c0000600000175000017500000000223710543202053020000 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" BOOLEAN InstallGraphicResTypes (COUNT cel_type, COUNT font_type) { InstallResTypeVectors (cel_type, _GetCelData, _ReleaseCelData); InstallResTypeVectors (font_type, _GetFontData, _ReleaseFontData); return (TRUE); } DWORD LoadGraphicInstance (DWORD res) { MEM_HANDLE hData; hData = res_GetResource (res); if (hData) res_DetachResource (res); return ((DWORD)hData); } uqm-0.6.2/sc2/src/sc2code/libs/graphics/font.h0000600000175000017500000000400610543202053017451 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _FONT_H #define _FONT_H #define MAX_DELTAS 100 typedef struct FontPage { struct FontPage *next; wchar_t pageStart; #define CHARACTER_PAGE_MASK 0xff800 wchar_t firstChar; size_t numChars; TFB_Char *charDesc; } FONT_PAGE; typedef FONT_PAGE *PFONT_PAGE; static inline FONT_PAGE * AllocFontPage (int numChars) { FONT_PAGE *result = HMalloc (sizeof (FONT_PAGE)); result->charDesc = HCalloc (numChars * sizeof *result->charDesc); return result; } static inline void FreeFontPage (FONT_PAGE *page) { HFree (page->charDesc); HFree (page); } typedef struct { FONT_REF FontRef; UWORD Leading; UWORD LeadingWidth; FONT_PAGE *fontPages; } FONT_DESC; typedef FONT_DESC *PFONT_DESC; #define FONTPTR PFONT_DESC #define CHAR_DESCPTR PCHAR_DESC #define FONT_PRIORITY DEFAULT_MEM_PRIORITY #define AllocFont(size) \ (FONT_REF)mem_allocate ((MEM_SIZE)(sizeof (FONT_DESC) + (size)), \ MEM_ZEROINIT | MEM_GRAPHICS, FONT_PRIORITY, MEM_SIMPLE) #define LockFont(h) (FONTPTR)mem_lock (h) #define UnlockFont(h) mem_unlock (h) #define FreeFont _ReleaseFontData #define NULL_FONT (FONTPTR)NULL_PTR extern FONTPTR _CurFontPtr; extern MEM_HANDLE _GetFontData (uio_Stream *fp, DWORD length); extern BOOLEAN _ReleaseFontData (MEM_HANDLE handle); #endif /* _FONT_H */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/tfb_prim.c0000600000175000017500000001372210543202053020305 0ustar joeyjoey// Copyright Michael Martin, 2003 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* The original Primitive routines do various elaborate checks to * ensure we're within bounds for the clipping. Since clipping is * handled by the underlying TFB_Canvas implementation, we need not * worry about this. */ #include "gfxintrn.h" #include "gfx_common.h" #include "tfb_draw.h" #include "tfb_prim.h" #include "cmap.h" #include "libs/log.h" void TFB_Prim_Point (PPOINT p, TFB_Palette *color) { RECT r; r.corner.x = p->x - _CurFramePtr->HotSpot.x; r.corner.y = p->y - _CurFramePtr->HotSpot.y; r.extent.width = r.extent.height = 1; if (_CurFramePtr->Type == SCREEN_DRAWABLE) TFB_DrawScreen_Rect (&r, color->r, color->g, color->b, TFB_SCREEN_MAIN); else TFB_DrawImage_Rect (&r, color->r, color->g, color->b, _CurFramePtr->image); } void TFB_Prim_Rect (PRECT r, TFB_Palette *color) { RECT arm; int gscale; gscale = GetGraphicScale (); arm = *r; arm.extent.width = r->extent.width; arm.extent.height = 1; TFB_Prim_FillRect (&arm, color); arm.extent.height = r->extent.height; arm.extent.width = 1; TFB_Prim_FillRect (&arm, color); // rounding error correction here arm.corner.x += ((r->extent.width * gscale + (GSCALE_IDENTITY >> 1)) / GSCALE_IDENTITY) - 1; TFB_Prim_FillRect (&arm, color); arm.corner.x = r->corner.x; arm.corner.y += ((r->extent.height * gscale + (GSCALE_IDENTITY >> 1)) / GSCALE_IDENTITY) - 1; arm.extent.width = r->extent.width; arm.extent.height = 1; TFB_Prim_FillRect (&arm, color); } void TFB_Prim_FillRect (PRECT r, TFB_Palette *color) { RECT rect; int gscale; rect.corner.x = r->corner.x - _CurFramePtr->HotSpot.x; rect.corner.y = r->corner.y - _CurFramePtr->HotSpot.y; rect.extent.width = r->extent.width; rect.extent.height = r->extent.height; gscale = GetGraphicScale (); if (gscale != GSCALE_IDENTITY) { // rounding error correction here rect.extent.width = (rect.extent.width * gscale + (GSCALE_IDENTITY >> 1)) / GSCALE_IDENTITY; rect.extent.height = (rect.extent.height * gscale + (GSCALE_IDENTITY >> 1)) / GSCALE_IDENTITY; rect.corner.x += (r->extent.width - rect.extent.width) >> 1; rect.corner.y += (r->extent.height - rect.extent.height) >> 1; } if (_CurFramePtr->Type == SCREEN_DRAWABLE) TFB_DrawScreen_Rect (&rect, color->r, color->g, color->b, TFB_SCREEN_MAIN); else TFB_DrawImage_Rect (&rect, color->r, color->g, color->b, _CurFramePtr->image); } void TFB_Prim_Line (PLINE line, TFB_Palette *color) { int x1, y1, x2, y2; x1=line->first.x - _CurFramePtr->HotSpot.x; y1=line->first.y - _CurFramePtr->HotSpot.y; x2=line->second.x - _CurFramePtr->HotSpot.x; y2=line->second.y - _CurFramePtr->HotSpot.y; if (_CurFramePtr->Type == SCREEN_DRAWABLE) TFB_DrawScreen_Line (x1, y1, x2, y2, color->r, color->g, color->b, TFB_SCREEN_MAIN); else TFB_DrawImage_Line (x1, y1, x2, y2, color->r, color->g, color->b, _CurFramePtr->image); } void TFB_Prim_Stamp (PSTAMP stmp) { int x, y; PFRAME_DESC SrcFramePtr; TFB_Image *img; TFB_ColorMap *cmap = NULL; int gscale; SrcFramePtr = (PFRAME_DESC)stmp->frame; if (!SrcFramePtr) { log_add (log_Warning, "TFB_Prim_Stamp: Tried to draw a NULL frame" " (Stamp address = %p)", stmp); return; } img = SrcFramePtr->image; gscale = GetGraphicScale (); if (!img) { log_add (log_Warning, "Non-existent image to TFB_Prim_Stamp()"); return; } LockMutex (img->mutex); img->NormalHs = SrcFramePtr->HotSpot; x = stmp->origin.x - _CurFramePtr->HotSpot.x; y = stmp->origin.y - _CurFramePtr->HotSpot.y; if (TFB_DrawCanvas_IsPaletted(img->NormalImg) && img->colormap_index != -1) { // returned cmap is addrefed, must release later cmap = TFB_GetColorMap (img->colormap_index); } UnlockMutex (img->mutex); if (_CurFramePtr->Type == SCREEN_DRAWABLE) { TFB_DrawScreen_Image (img, x, y, gscale, cmap, TFB_SCREEN_MAIN); } else { TFB_DrawImage_Image (img, x, y, gscale, cmap, _CurFramePtr->image); } } void TFB_Prim_StampFill (PSTAMP stmp, TFB_Palette *color) { int x, y; PFRAME_DESC SrcFramePtr; TFB_Image *img; int r, g, b; int gscale; SrcFramePtr = (PFRAME_DESC)stmp->frame; if (!SrcFramePtr) { log_add (log_Warning, "TFB_Prim_StampFill: Tried to draw a NULL frame" " (Stamp address = %p)", stmp); return; } img = SrcFramePtr->image; gscale = GetGraphicScale (); if (!img) { log_add (log_Warning, "Non-existent image to TFB_Prim_StampFill()"); return; } LockMutex (img->mutex); img->NormalHs = SrcFramePtr->HotSpot; x = stmp->origin.x - _CurFramePtr->HotSpot.x; y = stmp->origin.y - _CurFramePtr->HotSpot.y; r = color->r; g = color->g; b = color->b; UnlockMutex (img->mutex); if (_CurFramePtr->Type == SCREEN_DRAWABLE) { TFB_DrawScreen_FilledImage (img, x, y, gscale, r, g, b, TFB_SCREEN_MAIN); } else { TFB_DrawImage_FilledImage (img, x, y, gscale, r, g, b, _CurFramePtr->image); } } void TFB_Prim_FontChar (PPOINT origin, TFB_Char *fontChar, TFB_Image *backing) { int x, y; x = origin->x - _CurFramePtr->HotSpot.x; y = origin->y - _CurFramePtr->HotSpot.y; if (_CurFramePtr->Type == SCREEN_DRAWABLE) { TFB_DrawScreen_FontChar (fontChar, backing, x, y, TFB_SCREEN_MAIN); } else { TFB_DrawImage_FontChar (fontChar, backing, x, y, _CurFramePtr->image); } } // Text rendering is in font.c, under the name _text_blt uqm-0.6.2/sc2/src/sc2code/libs/graphics/intersec.c0000600000175000017500000002350510543202054020320 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" #include "libs/log.h" //#define DEBUG_INTERSEC static TIME_VALUE frame_intersect (PINTERSECT_CONTROL pControl0, PRECT pr0, PINTERSECT_CONTROL pControl1, PRECT pr1, TIME_VALUE t0, TIME_VALUE t1) { SIZE time_error0, time_error1; SIZE cycle0, cycle1; SIZE dx_0, dy_0, dx_1, dy_1; SIZE xincr0, yincr0, xincr1, yincr1; SIZE xerror0, xerror1, yerror0, yerror1; RECT r_intersect; IMAGE_BOX IB0, IB1; BOOLEAN check0, check1; IB0.FramePtr = pControl0->IntersectStamp.frame; IB0.Box.corner = pr0->corner; IB0.Box.extent.width = GetFrameWidth (IB0.FramePtr); IB0.Box.extent.height = GetFrameHeight (IB0.FramePtr); IB1.FramePtr = pControl1->IntersectStamp.frame; IB1.Box.corner = pr1->corner; IB1.Box.extent.width = GetFrameWidth (IB1.FramePtr); IB1.Box.extent.height = GetFrameHeight (IB1.FramePtr); dx_0 = pr0->extent.width; dy_0 = pr0->extent.height; if (dx_0 >= 0) xincr0 = 1; else { xincr0 = -1; dx_0 = -dx_0; } if (dy_0 >= 0) yincr0 = 1; else { yincr0 = -1; dy_0 = -dy_0; } if (dx_0 >= dy_0) cycle0 = dx_0; else cycle0 = dy_0; xerror0 = yerror0 = cycle0; dx_1 = pr1->extent.width; dy_1 = pr1->extent.height; if (dx_1 >= 0) xincr1 = 1; else { xincr1 = -1; dx_1 = -dx_1; } if (dy_1 >= 0) yincr1 = 1; else { yincr1 = -1; dy_1 = -dy_1; } if (dx_1 >= dy_1) cycle1 = dx_1; else cycle1 = dy_1; xerror1 = yerror1 = cycle1; check0 = check1 = FALSE; if (t0 <= 1) { time_error0 = time_error1 = 0; if (t0 == 0) { ++t0; goto CheckFirstIntersection; } } else { SIZE delta; COUNT start; long error; start = (COUNT)cycle0 * (COUNT)(t0 - 1); time_error0 = start & ((1 << TIME_SHIFT) - 1); if ((start >>= (COUNT)TIME_SHIFT) > 0) { if ((error = (long)xerror0 - (long)dx_0 * (long)start) > 0) xerror0 = (SIZE)error; else { delta = -(SIZE)(error / (long)cycle0) + 1; IB0.Box.corner.x += xincr0 * delta; xerror0 = (SIZE)(error + (long)cycle0 * (long)delta); } if ((error = (long)yerror0 - (long)dy_0 * (long)start) > 0) yerror0 = (SIZE)error; else { delta = -(SIZE)(error / (long)cycle0) + 1; IB0.Box.corner.y += yincr0 * delta; yerror0 = (SIZE)(error + (long)cycle0 * (long)delta); } pr0->corner = IB0.Box.corner; } start = (COUNT)cycle1 * (COUNT)(t0 - 1); time_error1 = start & ((1 << TIME_SHIFT) - 1); if ((start >>= (COUNT)TIME_SHIFT) > 0) { if ((error = (long)xerror1 - (long)dx_1 * (long)start) > 0) xerror1 = (SIZE)error; else { delta = -(SIZE)(error / (long)cycle1) + 1; IB1.Box.corner.x += xincr1 * delta; xerror1 = (SIZE)(error + (long)cycle1 * (long)delta); } if ((error = (long)yerror1 - (long)dy_1 * (long)start) > 0) yerror1 = (SIZE)error; else { delta = -(SIZE)(error / (long)cycle1) + 1; IB1.Box.corner.y += yincr1 * delta; yerror1 = (SIZE)(error + (long)cycle1 * (long)delta); } pr1->corner = IB1.Box.corner; } } pControl0->last_time_val = pControl1->last_time_val = t0; do { ++t0; if ((time_error0 += cycle0) >= (1 << TIME_SHIFT)) { if ((xerror0 -= dx_0) <= 0) { IB0.Box.corner.x += xincr0; xerror0 += cycle0; } if ((yerror0 -= dy_0) <= 0) { IB0.Box.corner.y += yincr0; yerror0 += cycle0; } check0 = TRUE; time_error0 -= (1 << TIME_SHIFT); } if ((time_error1 += cycle1) >= (1 << TIME_SHIFT)) { if ((xerror1 -= dx_1) <= 0) { IB1.Box.corner.x += xincr1; xerror1 += cycle1; } if ((yerror1 -= dy_1) <= 0) { IB1.Box.corner.y += yincr1; yerror1 += cycle1; } check1 = TRUE; time_error1 -= (1 << TIME_SHIFT); } if (check0 || check1) { /* if check0 && check1, this may not be quite right -- * if shapes had a pixel's separation to begin with * and both moved toward each other, you would actually * get a pixel overlap but since the last positions were * separated by a pixel, the shapes wouldn't be touching * each other. */ BOOLEAN _image_intersect (PIMAGE_BOX pImageBox0, PIMAGE_BOX pImageBox1, PRECT pIRect); CheckFirstIntersection: if (BoxIntersect (&IB0.Box, &IB1.Box, &r_intersect) && _image_intersect (&IB0, &IB1, &r_intersect)) return (t0); if (check0) { pr0->corner = IB0.Box.corner; pControl0->last_time_val = t0; check0 = FALSE; } if (check1) { pr1->corner = IB1.Box.corner; pControl1->last_time_val = t0; check1 = FALSE; } } } while (t0 <= t1); return ((TIME_VALUE)0); } TIME_VALUE DrawablesIntersect (PINTERSECT_CONTROL pControl0, PINTERSECT_CONTROL pControl1, TIME_VALUE max_time_val) { SIZE dy; SIZE time_y_0, time_y_1; RECT r0, r1; FRAMEPTR FramePtr0, FramePtr1; if (!ContextActive () || max_time_val == 0) return ((TIME_VALUE)0); else if (max_time_val > MAX_TIME_VALUE) max_time_val = MAX_TIME_VALUE; pControl0->last_time_val = pControl1->last_time_val = 0; r0.corner = pControl0->IntersectStamp.origin; r1.corner = pControl1->IntersectStamp.origin; r0.extent.width = pControl0->EndPoint.x - r0.corner.x; r0.extent.height = pControl0->EndPoint.y - r0.corner.y; r1.extent.width = pControl1->EndPoint.x - r1.corner.x; r1.extent.height = pControl1->EndPoint.y - r1.corner.y; FramePtr0 = (FRAMEPTR)pControl0->IntersectStamp.frame; if (FramePtr0 == 0) return(0); r0.corner.x -= FramePtr0->HotSpot.x; r0.corner.y -= FramePtr0->HotSpot.y; FramePtr1 = (FRAMEPTR)pControl1->IntersectStamp.frame; if (FramePtr1 == 0) return(0); r1.corner.x -= FramePtr1->HotSpot.x; r1.corner.y -= FramePtr1->HotSpot.y; dy = r1.corner.y - r0.corner.y; time_y_0 = dy - GetFrameHeight (FramePtr0) + 1; time_y_1 = dy + GetFrameHeight (FramePtr1) - 1; dy = r0.extent.height - r1.extent.height; if ((time_y_0 <= 0 && time_y_1 >= 0) || (time_y_0 > 0 && dy >= time_y_0) || (time_y_1 < 0 && dy <= time_y_1)) { SIZE dx; SIZE time_x_0, time_x_1; dx = r1.corner.x - r0.corner.x; time_x_0 = dx - GetFrameWidth (FramePtr0) + 1; time_x_1 = dx + GetFrameWidth (FramePtr1) - 1; dx = r0.extent.width - r1.extent.width; if ((time_x_0 <= 0 && time_x_1 >= 0) || (time_x_0 > 0 && dx >= time_x_0) || (time_x_1 < 0 && dx <= time_x_1)) { TIME_VALUE intersect_time; if (dx == 0 && dy == 0) time_y_0 = time_y_1 = 0; else { SIZE t; long time_beg, time_end, fract; if (time_y_1 < 0) { t = time_y_0; time_y_0 = -time_y_1; time_y_1 = -t; } else if (time_y_0 <= 0) { if (dy < 0) time_y_1 = -time_y_0; time_y_0 = 0; } if (dy < 0) dy = -dy; if (dy < time_y_1) time_y_1 = dy; /* just to be safe, widen search area */ --time_y_0; ++time_y_1; if (time_x_1 < 0) { t = time_x_0; time_x_0 = -time_x_1; time_x_1 = -t; } else if (time_x_0 <= 0) { if (dx < 0) time_x_1 = -time_x_0; time_x_0 = 0; } if (dx < 0) dx = -dx; if (dx < time_x_1) time_x_1 = dx; /* just to be safe, widen search area */ --time_x_0; ++time_x_1; #ifdef DEBUG_INTERSEC log_add (log_Debug, "FramePtr0<%d, %d> --> <%d, %d>", GetFrameWidth (FramePtr0), GetFrameHeight (FramePtr0), r0.corner.x, r0.corner.y); log_add (log_Debug, "FramePtr1<%d, %d> --> <%d, %d>", GetFrameWidth (FramePtr1), GetFrameHeight (FramePtr1), r1.corner.x, r1.corner.y); log_add (log_Debug, "time_x(%d, %d)-%d, time_y(%d, %d)-%d", time_x_0, time_x_1, dx, time_y_0, time_y_1, dy); #endif /* DEBUG_INTERSEC */ if (dx == 0) { time_beg = time_y_0; time_end = time_y_1; fract = dy; } else if (dy == 0) { time_beg = time_x_0; time_end = time_x_1; fract = dx; } else { long time_x, time_y; time_x = (long)time_x_0 * (long)dy; time_y = (long)time_y_0 * (long)dx; time_beg = time_x < time_y ? time_y : time_x; time_x = (long)time_x_1 * (long)dy; time_y = (long)time_y_1 * (long)dx; time_end = time_x > time_y ? time_y : time_x; fract = (long)dx * (long)dy; } if ((time_beg <<= TIME_SHIFT) < fract) time_y_0 = 0; else time_y_0 = (SIZE)(time_beg / fract); if (time_end >= fract /* just in case of overflow */ || (time_end <<= TIME_SHIFT) >= fract * (long)max_time_val) time_y_1 = max_time_val - 1; else time_y_1 = (SIZE)((time_end + fract - 1) / fract) - 1; } #ifdef DEBUG_INTERSEC log_add (log_Debug, "start_time = %d, end_time = %d", time_y_0, time_y_1); #endif /* DEBUG_INTERSEC */ if (time_y_0 <= time_y_1 && (intersect_time = frame_intersect ( pControl0, &r0, pControl1, &r1, (TIME_VALUE)time_y_0, (TIME_VALUE)time_y_1))) { FramePtr0 = (FRAMEPTR)pControl0->IntersectStamp.frame; pControl0->EndPoint.x = r0.corner.x + FramePtr0->HotSpot.x; pControl0->EndPoint.y = r0.corner.y + FramePtr0->HotSpot.y; FramePtr1 = (FRAMEPTR)pControl1->IntersectStamp.frame; pControl1->EndPoint.x = r1.corner.x + FramePtr1->HotSpot.x; pControl1->EndPoint.y = r1.corner.y + FramePtr1->HotSpot.y; return (intersect_time); } } } return ((TIME_VALUE)0); } uqm-0.6.2/sc2/src/sc2code/libs/graphics/Makeinfo0000600000175000017500000000030110543202053020000 0ustar joeyjoeyuqm_SUBDIRS="sdl" uqm_CFILES="boxint.c clipline.c cmap.c context.c drawable.c filegfx.c font.c frame.c gfx_common.c intersec.c loaddisp.c pixmap.c resgfx.c tfb_draw.c tfb_prim.c widgets.c" uqm-0.6.2/sc2/src/sc2code/libs/graphics/frame.c0000600000175000017500000001477410543202054017606 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" #include "declib.h" #include "gfx_common.h" #include "tfb_draw.h" #include "tfb_prim.h" #include "gfxother.h" HOT_SPOT MAKE_HOT_SPOT (COORD x, COORD y) { HOT_SPOT hs; hs.x = x; hs.y = y; return hs; } typedef union { POINT Point; STAMP Stamp; BRESENHAM_LINE Line; TEXT Text; RECT Rect; } INTERNAL_PRIM_DESC; typedef INTERNAL_PRIM_DESC *PINTERNAL_PRIM_DESC; typedef PINTERNAL_PRIM_DESC INTERNAL_PRIM_DESCPTR; typedef struct { PRIM_LINKS Links; GRAPHICS_PRIM Type; COLOR Color; INTERNAL_PRIM_DESC Object; } INTERNAL_PRIMITIVE; typedef INTERNAL_PRIMITIVE *PINTERNAL_PRIMITIVE; STAMP _save_stamp; static BOOLEAN GetFrameValidRect (PRECT pValidRect, HOT_SPOT *pOldHot) { COORD hx, hy; HOT_SPOT OldHot; OldHot = _CurFramePtr->HotSpot; hx = OldHot.x; hy = OldHot.y; pValidRect->corner.x = hx; pValidRect->corner.y = hy; pValidRect->extent.width = GetFrameWidth (_CurFramePtr); pValidRect->extent.height = GetFrameHeight (_CurFramePtr); if (_pCurContext->ClipRect.extent.width) { if (!BoxIntersect (&_pCurContext->ClipRect, pValidRect, pValidRect)) return (FALSE); hx -= _pCurContext->ClipRect.corner.x; hy -= _pCurContext->ClipRect.corner.y; pValidRect->corner.x += hx; pValidRect->corner.y += hy; _CurFramePtr->HotSpot = MAKE_HOT_SPOT (hx, hy); } *pOldHot = OldHot; return (TRUE); } void ClearBackGround (PRECT pClipRect) { TFB_Palette color; COLORtoPalette (_get_context_bg_color (), &color); TFB_Prim_FillRect (pClipRect, &color); } void DrawBatch (PPRIMITIVE lpBasePrim, PRIM_LINKS PrimLinks, BATCH_FLAGS BatchFlags) { RECT ValidRect; HOT_SPOT OldHot; if (GraphicsSystemActive () && GetFrameValidRect (&ValidRect, &OldHot)) { COUNT CurIndex; PRIM_LINKS OldLinks; PPRIMITIVE lpPrim; BatchFlags &= BATCH_SINGLE | BATCH_BUILD_PAGE | BATCH_XFORM; BatchFlags |= _get_context_flags () & BATCH_CLIP_GRAPHICS; BatchGraphics (); if (BatchFlags & BATCH_BUILD_PAGE) { ClearBackGround (&ValidRect); } CurIndex = GetPredLink (PrimLinks); if (BatchFlags & BATCH_SINGLE) { if (CurIndex == END_OF_LIST) BatchFlags &= ~BATCH_SINGLE; else { lpBasePrim += CurIndex; OldLinks = GetPrimLinks (lpBasePrim); SetPrimLinks (lpBasePrim, END_OF_LIST, END_OF_LIST); CurIndex = 0; } } for (; CurIndex != END_OF_LIST; CurIndex = GetSuccLink (GetPrimLinks (lpPrim))) { GRAPHICS_PRIM PrimType; PPRIMITIVE lpWorkPrim; RECT ClipRect; TFB_Palette color; lpPrim = &lpBasePrim[CurIndex]; PrimType = GetPrimType (lpPrim); if (!ValidPrimType (PrimType)) continue; lpWorkPrim = lpPrim; switch (PrimType) { case POINT_PRIM: COLORtoPalette (GetPrimColor (lpWorkPrim), &color); TFB_Prim_Point (&lpWorkPrim->Object.Point, &color); break; case STAMP_PRIM: TFB_Prim_Stamp (&lpWorkPrim->Object.Stamp); break; case STAMPFILL_PRIM: COLORtoPalette (GetPrimColor (lpWorkPrim), &color); TFB_Prim_StampFill (&lpWorkPrim->Object.Stamp, &color); break; case LINE_PRIM: COLORtoPalette (GetPrimColor (lpWorkPrim), &color); TFB_Prim_Line (&lpWorkPrim->Object.Line, &color); break; case TEXT_PRIM: if (!TextRect (&lpWorkPrim->Object.Text, &ClipRect, NULL_PTR)) continue; _save_stamp.origin = ClipRect.corner; _text_blt (&ClipRect, lpWorkPrim); break; case RECT_PRIM: COLORtoPalette (GetPrimColor (lpWorkPrim), &color); TFB_Prim_Rect (&lpWorkPrim->Object.Rect, &color); break; case RECTFILL_PRIM: COLORtoPalette (GetPrimColor (lpWorkPrim), &color); TFB_Prim_FillRect (&lpWorkPrim->Object.Rect, &color); break; } } UnbatchGraphics (); _CurFramePtr->HotSpot = OldHot; if (BatchFlags & BATCH_SINGLE) SetPrimLinks (lpBasePrim, GetPredLink (OldLinks), GetSuccLink (OldLinks)); } } void ClearDrawable (void) { RECT ValidRect; HOT_SPOT OldHot; if (GraphicsSystemActive () && GetFrameValidRect (&ValidRect, &OldHot)) { BatchGraphics (); ClearBackGround (&ValidRect); UnbatchGraphics (); _CurFramePtr->HotSpot = OldHot; } } void DrawPoint (PPOINT lpPoint) { RECT ValidRect; HOT_SPOT OldHot; if (GraphicsSystemActive () && GetFrameValidRect (&ValidRect, &OldHot)) { TFB_Palette color; COLORtoPalette (GetPrimColor (&_locPrim), &color); TFB_Prim_Point (lpPoint, &color); _CurFramePtr->HotSpot = OldHot; } } void DrawRectangle (PRECT lpRect) { RECT ValidRect; HOT_SPOT OldHot; if (GraphicsSystemActive () && GetFrameValidRect (&ValidRect, &OldHot)) { TFB_Palette color; COLORtoPalette (GetPrimColor (&_locPrim), &color); TFB_Prim_Rect (lpRect, &color); _CurFramePtr->HotSpot = OldHot; } } void DrawFilledRectangle (PRECT lpRect) { RECT ValidRect; HOT_SPOT OldHot; if (GraphicsSystemActive () && GetFrameValidRect (&ValidRect, &OldHot)) { TFB_Palette color; COLORtoPalette (GetPrimColor (&_locPrim), &color); TFB_Prim_FillRect (lpRect, &color); _CurFramePtr->HotSpot = OldHot; } } void DrawLine (PLINE lpLine) { RECT ValidRect; HOT_SPOT OldHot; if (GraphicsSystemActive () && GetFrameValidRect (&ValidRect, &OldHot)) { TFB_Palette color; COLORtoPalette (GetPrimColor (&_locPrim), &color); TFB_Prim_Line (lpLine, &color); _CurFramePtr->HotSpot = OldHot; } } void DrawStamp (PSTAMP stmp) { RECT ValidRect; HOT_SPOT OldHot; if (GraphicsSystemActive () && GetFrameValidRect (&ValidRect, &OldHot)) { TFB_Prim_Stamp (stmp); _CurFramePtr->HotSpot = OldHot; } } void DrawFilledStamp (PSTAMP stmp) { RECT ValidRect; HOT_SPOT OldHot; if (GraphicsSystemActive () && GetFrameValidRect (&ValidRect, &OldHot)) { TFB_Palette color; COLORtoPalette (GetPrimColor (&_locPrim), &color); TFB_Prim_StampFill (stmp, &color); _CurFramePtr->HotSpot = OldHot; } } uqm-0.6.2/sc2/src/sc2code/libs/graphics/gfxintrn.h0000600000175000017500000000223510543202053020344 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GFXINTRN_H #define _GFXINTRN_H #include #include #define _GFX_PROTOS #include "gfxlib.h" #include "reslib.h" #include "context.h" #include "drawable.h" #include "font.h" #include "display.h" #undef CONTEXT #define CONTEXT CONTEXTPTR #undef FRAME #define FRAME FRAMEPTR #undef FONT #define FONT FONTPTR #undef _GFX_PROTOS #include "gfxlib.h" #endif /* _GFXINTRN_H */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/context.c0000600000175000017500000001272310543202054020170 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" #include "gfxother.h" GRAPHICS_STATUS _GraphicsStatusFlags; CONTEXTPTR _pCurContext; PRIMITIVE _locPrim; FONTPTR _CurFontPtr; CONTEXT SetContext (CONTEXT Context) { CONTEXT LastContext; LastContext = (CONTEXT)_pCurContext; if (Context != LastContext) { if (LastContext) { UnsetContextFlags ( MAKE_WORD (0, GRAPHICS_ACTIVE | DRAWABLE_ACTIVE) ); SetContextFlags ( MAKE_WORD (0, _GraphicsStatusFlags & (GRAPHICS_ACTIVE | DRAWABLE_ACTIVE)) ); DeactivateContext (); } _pCurContext = (CONTEXTPTR)Context; if (_pCurContext) { ActivateContext (); _GraphicsStatusFlags &= ~(GRAPHICS_ACTIVE | DRAWABLE_ACTIVE); _GraphicsStatusFlags |= HIBYTE (_get_context_flags ()); SetPrimColor (&_locPrim, _get_context_fg_color ()); _CurFramePtr = (FRAMEPTR)_get_context_fg_frame (); _CurFontPtr = (FONTPTR)_get_context_font (); } } return (LastContext); } CONTEXT_REF CreateContext (void) { CONTEXT_REF ContextRef; ContextRef = AllocContext (); if (ContextRef) { CONTEXT OldContext; /* initialize context */ OldContext = SetContext (CaptureContext (ContextRef)); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); SetContextClipping (TRUE); ReleaseContext (SetContext (OldContext)); } return (ContextRef); } BOOLEAN DestroyContext (CONTEXT_REF ContextRef) { if (ContextRef == 0) return (FALSE); if (_pCurContext && _pCurContext->ContextRef == ContextRef) SetContext ((CONTEXT)0); return (FreeContext (ContextRef)); } CONTEXT CaptureContext (CONTEXT_REF ContextRef) { CONTEXTPTR ContextPtr; ContextPtr = LockContext (ContextRef); if (ContextPtr) ContextPtr->ContextRef = ContextRef; return ((CONTEXT)ContextPtr); } CONTEXT_REF ReleaseContext (CONTEXT Context) { CONTEXTPTR ContextPtr; ContextPtr = (CONTEXTPTR)Context; if (ContextPtr) { CONTEXT_REF ContextRef; ContextRef = ContextPtr->ContextRef; UnlockContext (ContextRef); return (ContextRef); } return (0); } COLOR SetContextForeGroundColor (COLOR Color) { COLOR oldColor; if (!ContextActive ()) return (BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F)); if ((oldColor = _get_context_fg_color ()) != Color) { SwitchContextForeGroundColor (Color); if (!(_get_context_fbk_flags () & FBK_IMAGE)) { SetContextFBkFlags (FBK_DIRTY); } } SetPrimColor (&_locPrim, Color); return (oldColor); } COLOR SetContextBackGroundColor (COLOR Color) { COLOR oldColor; if (!ContextActive ()) return (BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); if ((oldColor = _get_context_bg_color ()) != Color) { SwitchContextBackGroundColor (Color); } return (oldColor); } BOOLEAN SetContextClipping (BOOLEAN ClipStatus) { BOOLEAN oldClipStatus; if (!ContextActive ()) return (TRUE); oldClipStatus = (_get_context_flags () & BATCH_CLIP_GRAPHICS) != 0; if (ClipStatus) { SetContextFlags (BATCH_CLIP_GRAPHICS); } else { UnsetContextFlags (BATCH_CLIP_GRAPHICS); } return (oldClipStatus); } BOOLEAN SetContextClipRect (PRECT lpRect) { if (!ContextActive ()) return (FALSE); if (lpRect) _pCurContext->ClipRect = *lpRect; else _pCurContext->ClipRect.extent.width = 0; return (TRUE); } BOOLEAN GetContextClipRect (PRECT lpRect) { if (!ContextActive ()) return (FALSE); *lpRect = _pCurContext->ClipRect; return (lpRect->extent.width != 0); } FRAME SetContextFontEffect (FRAME EffectFrame) { FRAME LastEffect; if (!ContextActive ()) return (NULL); LastEffect = _get_context_fonteff (); if (EffectFrame != LastEffect) { SwitchContextFontEffect (EffectFrame); if (EffectFrame != 0) { SetContextFBkFlags (FBK_IMAGE); } else { UnsetContextFBkFlags (FBK_IMAGE); } } return LastEffect; } void FixContextFontEffect (void) { SIZE w, h; TFB_Image* img; if (!ContextActive () || (_get_context_font_backing () != 0 && !(_get_context_fbk_flags () & FBK_DIRTY))) return; if (!GetContextFontLeading (&h) || !GetContextFontLeadingWidth (&w)) return; img = _pCurContext->FontBacking; if (img) TFB_DrawScreen_DeleteImage (img); img = TFB_DrawImage_CreateForScreen (w, h, TRUE); if (_get_context_fbk_flags () & FBK_IMAGE) { // image pattern backing FRAMEPTR EffectFrame = (FRAMEPTR)_get_context_fonteff (); TFB_DrawImage_Image (EffectFrame->image, -EffectFrame->HotSpot.x, -EffectFrame->HotSpot.y, 0, NULL, img); } else { // solid color backing TFB_Palette color; RECT r = { {0, 0}, {w, h} }; COLORtoPalette (_get_context_fg_color (), &color); TFB_DrawImage_Rect (&r, color.r, color.g, color.b, img); } _pCurContext->FontBacking = img; UnsetContextFBkFlags (FBK_DIRTY); } uqm-0.6.2/sc2/src/sc2code/libs/graphics/clipline.c0000600000175000017500000001353010543202053020277 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxintrn.h" INTERSECT_CODE _clip_line (PRECT pClipRect, PBRESENHAM_LINE pLine) { COORD p; COORD x0, y0, xmin, ymin, xmax, ymax; SIZE abs_delta_x, abs_delta_y; INTERSECT_CODE intersect_code; xmin = pClipRect->corner.x; ymin = pClipRect->corner.y; xmax = pClipRect->corner.x + pClipRect->extent.width - 1; ymax = pClipRect->corner.y + pClipRect->extent.height - 1; if (pLine->first.x <= pLine->second.x) pLine->end_points_exchanged = FALSE; else { p = pLine->first.x; pLine->first.x = pLine->second.x; pLine->second.x = p; p = pLine->first.y; pLine->first.y = pLine->second.y; pLine->second.y = p; pLine->end_points_exchanged = TRUE; } if (pLine->first.x > xmax || pLine->second.x < xmin || (pLine->first.y > ymax && pLine->second.y > ymax) || (pLine->first.y < ymin && pLine->second.y < ymin)) return ((INTERSECT_CODE)0); intersect_code = INTERSECT_NOCLIP; x0 = y0 = 0; abs_delta_x = (pLine->second.x - pLine->first.x) << 1; abs_delta_y = (pLine->second.y - pLine->first.y) << 1; pLine->abs_delta_x = abs_delta_x; pLine->abs_delta_y = abs_delta_y; if (abs_delta_y == 0) { if (pLine->first.x < xmin) { pLine->first.x = xmin; intersect_code |= INTERSECT_LEFT; } if (pLine->second.x > xmax) { pLine->second.x = xmax; intersect_code |= INTERSECT_RIGHT; } } else if (abs_delta_x == 0) { if (abs_delta_y < 0) { p = pLine->first.y; pLine->first.y = pLine->second.y; pLine->second.y = p; pLine->abs_delta_y = abs_delta_y = -abs_delta_y; } if (pLine->first.y < ymin) { pLine->first.y = ymin; intersect_code |= INTERSECT_TOP; } if (pLine->second.y > ymax) { pLine->second.y = ymax; intersect_code |= INTERSECT_BOTTOM; } } else { COORD x1, y1; p = pLine->first.x; x1 = pLine->second.x - p; xmin = xmin - p; xmax = xmax - p; p = pLine->first.y; if (abs_delta_y > 0) { y1 = pLine->second.y - p; ymin = ymin - p; ymax = ymax - p; } else { y1 = p - pLine->second.y; ymin = p - ymin; ymax = p - ymax; p = ymin; ymin = ymax; ymax = p; abs_delta_y = -abs_delta_y; } if (abs_delta_x > abs_delta_y) { SIZE half_dx; half_dx = abs_delta_x >> 1; if (x0 < xmin) { if ((y0 = (COORD)(((long)abs_delta_y * (x0 = xmin) + half_dx) / abs_delta_x)) > ymax) return ((INTERSECT_CODE)0); intersect_code |= INTERSECT_LEFT; } if (x1 > xmax) { if ((y1 = (COORD)(((long)abs_delta_y * (x1 = xmax) + half_dx) / abs_delta_x)) < ymin) return ((INTERSECT_CODE)0); intersect_code |= INTERSECT_RIGHT; } if (y0 < ymin) { if ((x0 = (COORD)(((long)abs_delta_x * (y0 = ymin) - half_dx + (abs_delta_y - 1)) / abs_delta_y)) > xmax) return ((INTERSECT_CODE)0); intersect_code |= INTERSECT_TOP; intersect_code &= ~INTERSECT_LEFT; } if (y1 > ymax) { if ((x1 = (COORD)(((long)abs_delta_x * ((y1 = ymax) + 1) - half_dx + (abs_delta_y - 1)) / abs_delta_y) - 1) < xmin) return ((INTERSECT_CODE)0); intersect_code |= INTERSECT_BOTTOM; intersect_code &= ~INTERSECT_RIGHT; } } else { SIZE half_dy; half_dy = abs_delta_y >> 1; if (y0 < ymin) { if ((x0 = (COORD)(((long)abs_delta_x * (y0 = ymin) + half_dy) / abs_delta_y)) > xmax) return ((INTERSECT_CODE)0); intersect_code |= INTERSECT_TOP; } if (y1 > ymax) { if ((x1 = (COORD)(((long)abs_delta_x * (y1 = ymax) + half_dy) / abs_delta_y)) < xmin) return ((INTERSECT_CODE)0); intersect_code |= INTERSECT_BOTTOM; } if (x0 < xmin) { if ((y0 = (COORD)(((long)abs_delta_y * (x0 = xmin) - half_dy + (abs_delta_x - 1)) / abs_delta_x)) > ymax) return ((INTERSECT_CODE)0); intersect_code |= INTERSECT_LEFT; intersect_code &= ~INTERSECT_TOP; } if (x1 > xmax) { if ((y1 = (COORD)(((long)abs_delta_y * ((x1 = xmax) + 1) - half_dy + (abs_delta_x - 1)) / abs_delta_x) - 1) < ymin) return ((INTERSECT_CODE)0); intersect_code |= INTERSECT_RIGHT; intersect_code &= ~INTERSECT_BOTTOM; } } pLine->second.x = pLine->first.x + x1; pLine->first.x += x0; if (pLine->abs_delta_y > 0) { pLine->second.y = pLine->first.y + y1; pLine->first.y += y0; } else { INTERSECT_CODE y_code; pLine->second.y = pLine->first.y - y1; pLine->first.y -= y0; y_code = (INTERSECT_CODE)(intersect_code & (INTERSECT_TOP | INTERSECT_BOTTOM)); if (y_code && y_code != (INTERSECT_TOP | INTERSECT_BOTTOM)) intersect_code ^= (INTERSECT_TOP | INTERSECT_BOTTOM); } } if (!(intersect_code & INTERSECT_ALL_SIDES)) { if (abs_delta_x > abs_delta_y) pLine->error_term = -(SIZE)(abs_delta_x >> 1); else pLine->error_term = -(SIZE)(abs_delta_y >> 1); } else { intersect_code &= ~INTERSECT_NOCLIP; if (abs_delta_x > abs_delta_y) pLine->error_term = (SIZE)((x0 * (long)abs_delta_y) - (y0 * (long)abs_delta_x)) - (abs_delta_x >> 1); else pLine->error_term = (SIZE)((y0 * (long)abs_delta_x) - (x0 * (long)abs_delta_y)) - (abs_delta_y >> 1); } return (pLine->intersect_code = intersect_code); } uqm-0.6.2/sc2/src/sc2code/libs/graphics/gfxother.h0000644000175000017500000000211710552135701020347 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef GFXOTHER_H #define GFXOTHER_H #include "gfxintrn.h" #include "tfb_draw.h" static inline void COLORtoPalette (DWORD c32k, TFB_Palette* color) { c32k >>= 8; // shift out color index color->r = (UBYTE)((c32k >> (10 - (8 - 5))) & 0xF8); color->g = (UBYTE)((c32k >> (5 - (8 - 5))) & 0xF8); color->b = (UBYTE)((c32k << (8 - 5)) & 0xF8); } #endif /* GFXOTHER */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/prim.h0000600000175000017500000000355210543202054017460 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _PRIM_H #define _PRIM_H enum gfx_object { POINT_PRIM = 0, STAMP_PRIM, STAMPFILL_PRIM, LINE_PRIM, TEXT_PRIM, RECT_PRIM, RECTFILL_PRIM, NUM_PRIMS }; typedef BYTE GRAPHICS_PRIM; typedef union { POINT Point; STAMP Stamp; LINE Line; TEXT Text; RECT Rect; } PRIM_DESC; typedef PRIM_DESC *PPRIM_DESC; typedef DWORD PRIM_LINKS; typedef struct { PRIM_LINKS Links; GRAPHICS_PRIM Type; COLOR Color; PRIM_DESC Object; } PRIMITIVE; typedef PRIMITIVE *PPRIMITIVE; #define END_OF_LIST ((COUNT)0xFFFF) #define GetPredLink(l) LOWORD(l) #define GetSuccLink(l) HIWORD(l) #define MakeLinks MAKE_DWORD #define SetPrimLinks(pPrim,p,s) ((pPrim)->Links = MakeLinks (p, s)) #define GetPrimLinks(pPrim) ((pPrim)->Links) #define SetPrimType(pPrim,t) ((pPrim)->Type = t) #define GetPrimType(pPrim) ((pPrim)->Type) #define SetPrimColor(pPrim,c) ((pPrim)->Color = c) #define GetPrimColor(pPrim) ((pPrim)->Color) static inline void SetPrimNextLink (PPRIMITIVE pPrim, COUNT Link) { SetPrimLinks (pPrim, END_OF_LIST, Link); } static inline COUNT GetPrimNextLink (PPRIMITIVE pPrim) { return GetSuccLink (GetPrimLinks (pPrim)); } #endif /* PRIM_H */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/context.h0000600000175000017500000001154210543202054020173 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _CONTEXT_H #define _CONTEXT_H #include "tfb_draw.h" typedef UWORD FBK_FLAGS; #define FBK_DIRTY (1 << 0) #define FBK_IMAGE (1 << 1) typedef struct { CONTEXT_REF ContextRef; UWORD Flags; COLOR ForeGroundColor, BackGroundColor; FRAME ForeGroundFrame; FONT Font; RECT ClipRect; FRAME FontEffect; TFB_Image *FontBacking; FBK_FLAGS BackingFlags; } CONTEXT_DESC; typedef CONTEXT_DESC *PCONTEXT_DESC; #define CONTEXT_PRIORITY DEFAULT_MEM_PRIORITY #define CONTEXTPTR PCONTEXT_DESC #define AllocContext() \ (CONTEXT_REF)mem_allocate ((MEM_SIZE)sizeof (CONTEXT_DESC), \ MEM_ZEROINIT | MEM_PRIMARY, CONTEXT_PRIORITY, MEM_SIMPLE) #define LockContext (CONTEXTPTR)mem_lock #define UnlockContext mem_unlock #define FreeContext mem_release extern CONTEXTPTR _pCurContext; extern PRIMITIVE _locPrim; #define _get_context_fg_color() (_pCurContext->ForeGroundColor) #define _get_context_bg_color() (_pCurContext->BackGroundColor) #define _get_context_flags() (_pCurContext->Flags) #define _get_context_fg_frame() (_pCurContext->ForeGroundFrame) #define _get_context_font() (_pCurContext->Font) #define _get_context_fbk_flags() (_pCurContext->BackingFlags) #define _get_context_fonteff() (_pCurContext->FontEffect) #define _get_context_font_backing() (_pCurContext->FontBacking) #define SwitchContextDrawState(s) \ { \ _pCurContext->DrawState = (s); \ } #define SwitchContextForeGroundColor(c) \ { \ _pCurContext->ForeGroundColor = (c); \ } #define SwitchContextBackGroundColor(c) \ { \ _pCurContext->BackGroundColor = (c); \ } #define SetContextFlags(f) \ { \ _pCurContext->Flags |= (f); \ } #define UnsetContextFlags(f) \ { \ _pCurContext->Flags &= ~(f); \ } #define SwitchContextFGFrame(f) \ { \ _pCurContext->ForeGroundFrame = (f); \ } #define SwitchContextFont(f) \ { \ _pCurContext->Font = (f); \ SetContextFBkFlags (FBK_DIRTY); \ } #define SwitchContextBGFunc(f) \ { \ _pCurContext->BackGroundFunc = (f); \ } #define SetContextFBkFlags(f) \ { \ _pCurContext->BackingFlags |= (f); \ } #define UnsetContextFBkFlags(f) \ { \ _pCurContext->BackingFlags &= ~(f); \ } #define SwitchContextFontEffect(f) \ { \ _pCurContext->FontEffect = (f); \ SetContextFBkFlags (FBK_DIRTY); \ } /* These seem to have been moved to gfxlib.h, but not in their entirety. That's rather unpleasant. -- Michael #define BATCH_BUILD_PAGE (BATCH_FLAGS)(1 << 0) #define BATCH_SINGLE (BATCH_FLAGS)(1 << 1) #define BATCH_UPDATE_DRAWABLE (BATCH_FLAGS)(1 << 2) */ #define BATCH_CLIP_GRAPHICS (BATCH_FLAGS)(1 << 3) #define BATCH_XFORM (BATCH_FLAGS)(1 << 4) typedef BYTE GRAPHICS_STATUS; extern GRAPHICS_STATUS _GraphicsStatusFlags; #define GRAPHICS_ACTIVE (GRAPHICS_STATUS)(1 << 0) #define GRAPHICS_VISIBLE (GRAPHICS_STATUS)(1 << 1) #define CONTEXT_ACTIVE (GRAPHICS_STATUS)(1 << 2) #define DRAWABLE_ACTIVE (GRAPHICS_STATUS)(1 << 3) #define DISPLAY_ACTIVE (GRAPHICS_STATUS)(1 << 5) #define DeactivateGraphics() (_GraphicsStatusFlags &= ~GRAPHICS_ACTIVE) #define ActivateGraphics() (_GraphicsStatusFlags |= GRAPHICS_ACTIVE) #define GraphicsActive() (_GraphicsStatusFlags & GRAPHICS_ACTIVE) #define DeactivateVisible() (_GraphicsStatusFlags &= ~GRAPHICS_VISIBLE) #define ActivateVisible() (_GraphicsStatusFlags |= GRAPHICS_VISIBLE) #define DeactivateDisplay() (_GraphicsStatusFlags &= ~DISPLAY_ACTIVE) #define ActivateDisplay() (_GraphicsStatusFlags |= DISPLAY_ACTIVE) #define DisplayActive() (_GraphicsStatusFlags & DISPLAY_ACTIVE) #define DeactivateContext() (_GraphicsStatusFlags &= ~CONTEXT_ACTIVE) #define ActivateContext() (_GraphicsStatusFlags |= CONTEXT_ACTIVE) #define ContextActive() (_GraphicsStatusFlags & CONTEXT_ACTIVE) #define DeactivateDrawable() (_GraphicsStatusFlags &= ~DRAWABLE_ACTIVE) #define ActivateDrawable() (_GraphicsStatusFlags |= DRAWABLE_ACTIVE) #define DrawableActive() (_GraphicsStatusFlags & DRAWABLE_ACTIVE) #define SYSTEM_ACTIVE (GRAPHICS_STATUS)( \ DISPLAY_ACTIVE | CONTEXT_ACTIVE | \ DRAWABLE_ACTIVE \ ) #define GraphicsSystemActive() \ ((_GraphicsStatusFlags & SYSTEM_ACTIVE) == SYSTEM_ACTIVE) #define GraphicsStatus() \ (_GraphicsStatusFlags & (GRAPHICS_STATUS)(GRAPHICS_ACTIVE \ | GRAPHICS_VISIBLE)) #endif /* _CONTEXT_H */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/0000755000175000017500000000000010552600274017133 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/scaleint.h0000644000175000017500000002733210552135701021113 0ustar joeyjoey/* * Copyright (C) 2005 Alex Volkov (codepro@usa.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Scalers Internals #ifndef SCALEINT_H_ #define SCALEINT_H_ #include "libs/graphics/sdl/sdl_common.h" #include "types.h" // Plain C names #define SCALE_(name) Scale ## _ ## name // These are defaults #define SCALE_GETPIX(p) ( *(Uint32 *)(p) ) #define SCALE_SETPIX(p, c) ( *(Uint32 *)(p) = (c) ) // Plain C defaults #define SCALE_CMPRGB(p1, p2) \ SCALE_(GetRGBDelta) (fmt, p1, p2) #define SCALE_TOYUV(p) \ SCALE_(RGBtoYUV) (fmt, p) #define SCALE_CMPYUV(p1, p2, toler) \ SCALE_(CmpYUV) (fmt, p1, p2, toler) #define SCALE_DIFFYUV(p1, p2) \ SCALE_(DiffYUV) (p1, p2) #define SCALE_DIFFYUV_TY 0x40 #define SCALE_DIFFYUV_TU 0x12 #define SCALE_DIFFYUV_TV 0x0c #define SCALE_GETY(p) \ SCALE_(GetPixY) (fmt, p) #define SCALE_BILINEAR_BLEND4(r0, r1, dst, dlen) \ SCALE_(Blend_bilinear) (r0, r1, dst, dlen) #define NO_PREFETCH 0 #define INTEL_PREFETCH 1 #define AMD_PREFETCH 2 typedef enum { YUV_XFORM_R = 0, YUV_XFORM_G = 1, YUV_XFORM_B = 2, YUV_XFORM_Y = 0, YUV_XFORM_U = 1, YUV_XFORM_V = 2 } RGB_YUV_INDEX; extern const int YUV_matrix[3][3]; // pre-computed transformations for 8 bits per channel extern int RGB_to_YUV[/*RGB*/ 3][/*YUV*/ 3][ /*mult-res*/ 256]; extern sint16 dRGB_to_dYUV[/*RGB*/ 3][/*YUV*/ 3][ /*mult-res*/ 512]; typedef Uint32 YUV_VECTOR; // pre-computed transformations for RGB555 extern YUV_VECTOR RGB15_to_YUV[0x8000]; // Platform+Scaler function lookups // typedef struct { int flag; TFB_ScaleFunc func; } Scale_FuncDef_t; // expands the given rectangle in all directions by 'expansion' // guarded by 'limits' extern void Scale_ExpandRect (SDL_Rect* rect, int expansion, const SDL_Rect* limits); // Standard plain C versions of support functions // Initialize various platform-specific features static inline void SCALE_(PlatInit) (void) { } // Finish with various platform-specific features static inline void SCALE_(PlatDone) (void) { } #if 0 static inline void SCALE_(Prefetch) (const void* p) { /* no-op in pure C */ (void)p; } #else # define Scale_Prefetch(p) #endif // compute the RGB distance squared between 2 pixels // Plain C version static inline int SCALE_(GetRGBDelta) (const SDL_PixelFormat* fmt, Uint32 pix1, Uint32 pix2) { int c; int delta; c = ((pix1 >> fmt->Rshift) & 0xff) - ((pix2 >> fmt->Rshift) & 0xff); delta = c * c; c = ((pix1 >> fmt->Gshift) & 0xff) - ((pix2 >> fmt->Gshift) & 0xff); delta += c * c; c = ((pix1 >> fmt->Bshift) & 0xff) - ((pix2 >> fmt->Bshift) & 0xff); delta += c * c; return delta; } // retrieve the Y (intensity) component of pixel's YUV // Plain C version static inline int SCALE_(GetPixY) (const SDL_PixelFormat* fmt, Uint32 pix) { Uint32 r, g, b; r = (pix >> fmt->Rshift) & 0xff; g = (pix >> fmt->Gshift) & 0xff; b = (pix >> fmt->Bshift) & 0xff; return RGB_to_YUV [YUV_XFORM_R][YUV_XFORM_Y][r] + RGB_to_YUV [YUV_XFORM_G][YUV_XFORM_Y][g] + RGB_to_YUV [YUV_XFORM_B][YUV_XFORM_Y][b]; } static inline YUV_VECTOR SCALE_(RGBtoYUV) (const SDL_PixelFormat* fmt, Uint32 pix) { return RGB15_to_YUV[ (((pix >> (fmt->Rshift + 3)) & 0x1f) << 10) | (((pix >> (fmt->Gshift + 3)) & 0x1f) << 5) | (((pix >> (fmt->Bshift + 3)) & 0x1f) ) ]; } // compare 2 pixels with respect to their YUV representations // tolerance set by toler arg // returns true: close; false: distant (-gt toler) // Plain C version static inline bool SCALE_(CmpYUV) (const SDL_PixelFormat* fmt, Uint32 pix1, Uint32 pix2, int toler) #if 1 { int dr, dg, db; int delta; dr = ((pix1 >> fmt->Rshift) & 0xff) - ((pix2 >> fmt->Rshift) & 0xff) + 255; dg = ((pix1 >> fmt->Gshift) & 0xff) - ((pix2 >> fmt->Gshift) & 0xff) + 255; db = ((pix1 >> fmt->Bshift) & 0xff) - ((pix2 >> fmt->Bshift) & 0xff) + 255; // compute Y delta delta = abs (dRGB_to_dYUV [YUV_XFORM_R][YUV_XFORM_Y][dr] + dRGB_to_dYUV [YUV_XFORM_G][YUV_XFORM_Y][dg] + dRGB_to_dYUV [YUV_XFORM_B][YUV_XFORM_Y][db]); if (delta > toler) return false; // compute U delta delta += abs (dRGB_to_dYUV [YUV_XFORM_R][YUV_XFORM_U][dr] + dRGB_to_dYUV [YUV_XFORM_G][YUV_XFORM_U][dg] + dRGB_to_dYUV [YUV_XFORM_B][YUV_XFORM_U][db]); if (delta > toler) return false; // compute V delta delta += abs (dRGB_to_dYUV [YUV_XFORM_R][YUV_XFORM_V][dr] + dRGB_to_dYUV [YUV_XFORM_G][YUV_XFORM_V][dg] + dRGB_to_dYUV [YUV_XFORM_B][YUV_XFORM_V][db]); return delta <= toler; } #else { int delta; Uint32 yuv1, yuv2; yuv1 = RGB15_to_YUV[ (((pix1 >> (fmt->Rshift + 3)) & 0x1f) << 10) | (((pix1 >> (fmt->Gshift + 3)) & 0x1f) << 5) | (((pix1 >> (fmt->Bshift + 3)) & 0x1f) ) ]; yuv2 = RGB15_to_YUV[ (((pix2 >> (fmt->Rshift + 3)) & 0x1f) << 10) | (((pix2 >> (fmt->Gshift + 3)) & 0x1f) << 5) | (((pix2 >> (fmt->Bshift + 3)) & 0x1f) ) ]; // compute Y delta delta = abs ((yuv1 & 0xff0000) - (yuv2 & 0xff0000)) >> 16; if (delta > toler) return false; // compute U delta delta += abs ((yuv1 & 0x00ff00) - (yuv2 & 0x00ff00)) >> 8; if (delta > toler) return false; // compute V delta delta += abs ((yuv1 & 0x0000ff) - (yuv2 & 0x0000ff)); return delta <= toler; } #endif // Check if 2 pixels are different with respect to their // YUV representations // returns 0: close; ~0: distant static inline int SCALE_(DiffYUV) (Uint32 yuv1, Uint32 yuv2) { // non-branching version -- assumes 2's complement integers // delta math only needs 25 bits and we have 32 available; // only interested in the sign bits after subtraction sint32 delta, ret; if (yuv1 == yuv2) return 0; // compute Y delta delta = abs ((yuv1 & 0xff0000) - (yuv2 & 0xff0000)); ret = (SCALE_DIFFYUV_TY << 16) - delta; // save sign bit // compute U delta delta = abs ((yuv1 & 0x00ff00) - (yuv2 & 0x00ff00)); ret |= (SCALE_DIFFYUV_TU << 8) - delta; // save sign bit // compute V delta delta = abs ((yuv1 & 0x0000ff) - (yuv2 & 0x0000ff)); ret |= SCALE_DIFFYUV_TV - delta; // save sign bit return (ret >> 31); } // blends two pixels with 1:1 ratio static inline Uint32 SCALE_(Blend_11) (Uint32 pix1, Uint32 pix2) { /* (pix1 + pix2) >> 1 */ return /* lower bits can be safely ignored - the error is minimal expression that calcs them is left for posterity (pix1 & pix2 & low_mask) + */ ((pix1 & 0xfefefefe) >> 1) + ((pix2 & 0xfefefefe) >> 1); } // blends four pixels with 1:1:1:1 ratio static inline Uint32 SCALE_(Blend_1111) (Uint32 pix1, Uint32 pix2, Uint32 pix3, Uint32 pix4) { /* (pix1 + pix2 + pix3 + pix4) >> 2 */ return /* lower bits can be safely ignored - the error is minimal expression that calcs them is left for posterity ((((pix1 & low_mask) + (pix2 & low_mask) + (pix3 & low_mask) + (pix4 & low_mask) ) >> 2) & low_mask) + */ ((pix1 & 0xfcfcfcfc) >> 2) + ((pix2 & 0xfcfcfcfc) >> 2) + ((pix3 & 0xfcfcfcfc) >> 2) + ((pix4 & 0xfcfcfcfc) >> 2); } // blends pixels with 3:1 ratio static inline Uint32 Scale_Blend_31 (Uint32 pix1, Uint32 pix2) { /* (pix1 * 3 + pix2) / 4 */ /* lower bits can be safely ignored - the error is minimal */ return ((pix1 & 0xfefefefe) >> 1) + ((pix1 & 0xfcfcfcfc) >> 2) + ((pix2 & 0xfcfcfcfc) >> 2); } // blends pixels with 2:1:1 ratio static inline Uint32 Scale_Blend_211 (Uint32 pix1, Uint32 pix2, Uint32 pix3) { /* (pix1 * 2 + pix2 + pix3) / 4 */ /* lower bits can be safely ignored - the error is minimal */ return ((pix1 & 0xfefefefe) >> 1) + ((pix2 & 0xfcfcfcfc) >> 2) + ((pix3 & 0xfcfcfcfc) >> 2); } // blends pixels with 5:2:1 ratio static inline Uint32 Scale_Blend_521 (Uint32 pix1, Uint32 pix2, Uint32 pix3) { /* (pix1 * 5 + pix2 * 2 + pix3) / 8 */ /* lower bits can be safely ignored - the error is minimal */ return ((pix1 & 0xfefefefe) >> 1) + ((pix1 & 0xf8f8f8f8) >> 3) + ((pix2 & 0xfcfcfcfc) >> 2) + ((pix3 & 0xf8f8f8f8) >> 3) + 0x02020202 /* half-error */; } // blends pixels with 6:1:1 ratio static inline Uint32 Scale_Blend_611 (Uint32 pix1, Uint32 pix2, Uint32 pix3) { /* (pix1 * 6 + pix2 + pix3) / 8 */ /* lower bits can be safely ignored - the error is minimal */ return ((pix1 & 0xfefefefe) >> 1) + ((pix1 & 0xfcfcfcfc) >> 2) + ((pix2 & 0xf8f8f8f8) >> 3) + ((pix3 & 0xf8f8f8f8) >> 3) + 0x02020202 /* half-error */; } // blends pixels with 2:3:3 ratio static inline Uint32 Scale_Blend_233 (Uint32 pix1, Uint32 pix2, Uint32 pix3) { /* (pix1 * 2 + pix2 * 3 + pix3 * 3) / 8 */ /* lower bits can be safely ignored - the error is minimal */ return ((pix1 & 0xfcfcfcfc) >> 2) + ((pix2 & 0xfcfcfcfc) >> 2) + ((pix2 & 0xf8f8f8f8) >> 3) + ((pix3 & 0xfcfcfcfc) >> 2) + ((pix3 & 0xf8f8f8f8) >> 3) + 0x02020202 /* half-error */; } // blends pixels with 14:1:1 ratio static inline Uint32 Scale_Blend_e11 (Uint32 pix1, Uint32 pix2, Uint32 pix3) { /* (pix1 * 14 + pix2 + pix3) >> 4 */ /* lower bits can be safely ignored - the error is minimal */ return ((pix1 & 0xfefefefe) >> 1) + ((pix1 & 0xfcfcfcfc) >> 2) + ((pix1 & 0xf8f8f8f8) >> 3) + ((pix2 & 0xf0f0f0f0) >> 4) + ((pix3 & 0xf0f0f0f0) >> 4) + 0x03030303 /* half-error */; } // Halfs the pixel's intensity static inline Uint32 SCALE_(HalfPixel) (Uint32 pix) { return ((pix & 0xfefefefe) >> 1); } // Bilinear weighted blend of four pixels // Function produces 4 blended pixels and writes them // out to the surface (in 2x2 matrix) // Pixels are computed using expanded weight matrix like so: // ('sp' - source pixel, 'dp' - destination pixel) // dp[0] = (9*sp[0] + 3*sp[1] + 3*sp[2] + 1*sp[3]) / 16 // dp[1] = (3*sp[0] + 9*sp[1] + 1*sp[2] + 3*sp[3]) / 16 // dp[2] = (3*sp[0] + 1*sp[1] + 9*sp[2] + 3*sp[3]) / 16 // dp[3] = (1*sp[0] + 3*sp[1] + 3*sp[2] + 9*sp[3]) / 16 static inline void SCALE_(Blend_bilinear) (const Uint32* row0, const Uint32* row1, Uint32* dst_p, Uint32 dlen) { // We loose some lower bits here and try to compensate for // that by adding half-error values. // In general, the error is minimal (+-7) // The >>4 reduction is achieved gradually # define BL_PACKED_HALF(p) \ (((p) & 0xfefefefe) >> 1) # define BL_SUM(p1, p2) \ (BL_PACKED_HALF(p1) + BL_PACKED_HALF(p2)) # define BL_HALF_ERR 0x01010101 # define BL_SUM_WERR(p1, p2) \ (BL_PACKED_HALF(p1) + BL_PACKED_HALF(p2) + BL_HALF_ERR) Uint32 sum1111, sum1331, sum3113; // cache p[0] + 3*(p[1] + p[2]) + p[3] in sum1331 // cache p[1] + 3*(p[0] + p[3]) + p[2] in sum3113 sum1331 = BL_SUM (row0[1], row1[0]); sum3113 = BL_SUM (row0[0], row1[1]); // cache p[0] + p[1] + p[2] + p[3] in sum1111 sum1111 = BL_SUM_WERR (sum1331, sum3113); sum1331 = BL_SUM_WERR (sum1331, sum1111); sum1331 = BL_PACKED_HALF (sum1331); sum3113 = BL_SUM_WERR (sum3113, sum1111); sum3113 = BL_PACKED_HALF (sum3113); // pixel 0 math -- (9*p[0] + 3*(p[1] + p[2]) + p[3]) / 16 dst_p[0] = BL_PACKED_HALF (row0[0]) + sum1331; // pixel 1 math -- (9*p[1] + 3*(p[0] + p[3]) + p[2]) / 16 dst_p[1] = BL_PACKED_HALF (row0[1]) + sum3113; // pixel 2 math -- (9*p[2] + 3*(p[0] + p[3]) + p[1]) / 16 dst_p[dlen] = BL_PACKED_HALF (row1[0]) + sum3113; // pixel 3 math -- (9*p[3] + 3*(p[1] + p[2]) + p[0]) / 16 dst_p[dlen + 1] = BL_PACKED_HALF (row1[1]) + sum1331; # undef BL_PACKED_HALF # undef BL_SUM # undef BL_HALF_ERR # undef BL_SUM_WERR } #endif /* SCALEINT_H_ */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/primitives.h0000600000175000017500000000235110543202053021461 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PRIMITIVES_H #define PRIMITIVES_H /* Function types for the pixel functions */ typedef Uint32 (*GetPixelFn)(SDL_Surface *, int, int); typedef void (*PutPixelFn)(SDL_Surface *, int, int, Uint32); GetPixelFn getpixel_for(SDL_Surface *surface); PutPixelFn putpixel_for(SDL_Surface *surface); void line(int x1, int y1, int x2, int y2, Uint32 color, PutPixelFn plot, SDL_Surface *surface); int clip_line(int *lx1, int *ly1, int *lx2, int *ly2, SDL_Rect *r); #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/2xscalers.c0000600000175000017500000001435010543202052021170 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "libs/graphics/sdl/sdl_common.h" #include "types.h" #include "scalers.h" #include "scaleint.h" #include "2xscalers.h" // Scaler function lookup table // const Scale_FuncDef_t Scale_C_Functions[] = { {TFB_GFXFLAGS_SCALE_BILINEAR, Scale_BilinearFilter}, {TFB_GFXFLAGS_SCALE_BIADAPT, Scale_BiAdaptFilter}, {TFB_GFXFLAGS_SCALE_BIADAPTADV, Scale_BiAdaptAdvFilter}, {TFB_GFXFLAGS_SCALE_TRISCAN, Scale_TriScanFilter}, {TFB_GFXFLAGS_SCALE_HQXX, Scale_HqFilter}, // Default {0, Scale_Nearest} }; // See // nearest2x.c -- Nearest Neighboor scaling // bilinear2x.c -- Bilinear scaling // biadv2x.c -- Advanced Biadapt scaling // triscan2x.c -- Triscan scaling // Biadapt scaling to 2x void SCALE_(BiAdaptFilter) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) { int x, y; const int w = src->w, h = src->h; int xend, yend; int dsrc, ddst; SDL_Rect *region = r; SDL_Rect limits; SDL_PixelFormat *fmt = dst->format; const int sp = src->pitch, dp = dst->pitch; const int bpp = fmt->BytesPerPixel; const int slen = sp / bpp, dlen = dp / bpp; Uint32 *src_p = (Uint32 *)src->pixels; Uint32 *dst_p = (Uint32 *)dst->pixels; Uint32 pixval_tl, pixval_tr, pixval_bl, pixval_br; // these macros are for clarity; they make the current pixel (0,0) // and allow to access pixels in all directions #define SRC(x, y) (src_p + (x) + ((y) * slen)) SCALE_(PlatInit) (); // expand updated region if necessary // pixels neighbooring the updated region may // change as a result of updates limits.x = 0; limits.y = 0; limits.w = src->w; limits.h = src->h; Scale_ExpandRect (region, 2, &limits); xend = region->x + region->w; yend = region->y + region->h; dsrc = slen - region->w; ddst = (dlen - region->w) * 2; // move ptrs to the first updated pixel src_p += slen * region->y + region->x; dst_p += (dlen * region->y + region->x) * 2; for (y = region->y; y < yend; ++y, dst_p += ddst, src_p += dsrc) { for (x = region->x; x < xend; ++x, ++src_p, ++dst_p) { pixval_tl = SCALE_GETPIX (SRC (0, 0)); SCALE_SETPIX (dst_p, pixval_tl); if (y + 1 < h) { // check pixel below the current one pixval_bl = SCALE_GETPIX (SRC (0, 1)); if (pixval_tl == pixval_bl) SCALE_SETPIX (dst_p + dlen, pixval_tl); else SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 ( pixval_tl, pixval_bl) ); } else { // last pixel in column - propagate SCALE_SETPIX (dst_p + dlen, pixval_tl); pixval_bl = pixval_tl; } ++dst_p; if (x + 1 >= w) { // last pixel in row - propagate SCALE_SETPIX (dst_p, pixval_tl); if (pixval_tl == pixval_bl) SCALE_SETPIX (dst_p + dlen, pixval_tl); else SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 ( pixval_tl, pixval_bl) ); continue; } // check pixel to the right from the current one pixval_tr = SCALE_GETPIX (SRC (1, 0)); if (pixval_tl == pixval_tr) SCALE_SETPIX (dst_p, pixval_tr); else SCALE_SETPIX (dst_p, Scale_Blend_11 ( pixval_tl, pixval_tr) ); if (y + 1 >= h) { // last pixel in column - propagate SCALE_SETPIX (dst_p + dlen, pixval_tl); continue; } // check pixel to the bottom-right pixval_br = SCALE_GETPIX (SRC (1, 1)); if (pixval_tl == pixval_br && pixval_tr == pixval_bl) { int cl, cr; Uint32 clr; if (pixval_tl == pixval_tr) { // all 4 are equal - propagate SCALE_SETPIX (dst_p + dlen, pixval_tl); continue; } // both pairs are equal, have to resolve the pixel // race; we try detecting which color is // the background by looking for a line or an edge // examine 8 pixels surrounding the current quad cl = cr = 1; if (x > 0) { clr = SCALE_GETPIX (SRC (-1, 0)); if (clr == pixval_tl) cl++; else if (clr == pixval_tr) cr++; clr = SCALE_GETPIX (SRC (-1, 1)); if (clr == pixval_tl) cl++; else if (clr == pixval_tr) cr++; } if (y > 0) { clr = SCALE_GETPIX (SRC (0, -1)); if (clr == pixval_tl) cl++; else if (clr == pixval_tr) cr++; clr = SCALE_GETPIX (SRC (1, -1)); if (clr == pixval_tl) cl++; else if (clr == pixval_tr) cr++; } if (x + 2 < w) { clr = SCALE_GETPIX (SRC (2, 0)); if (clr == pixval_tl) cl++; else if (clr == pixval_tr) cr++; clr = SCALE_GETPIX (SRC (2, 1)); if (clr == pixval_tl) cl++; else if (clr == pixval_tr) cr++; } if (y + 2 < h) { clr = SCALE_GETPIX (SRC (0, 2)); if (clr == pixval_tl) cl++; else if (clr == pixval_tr) cr++; clr = SCALE_GETPIX (SRC (1, 2)); if (clr == pixval_tl) cl++; else if (clr == pixval_tr) cr++; } // least count wins if (cl > cr) SCALE_SETPIX (dst_p + dlen, pixval_tr); else if (cr > cl) SCALE_SETPIX (dst_p + dlen, pixval_tl); else SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 (pixval_tl, pixval_tr)); } else if (pixval_tl == pixval_br) { // main diagonal is same color // use its value SCALE_SETPIX (dst_p + dlen, pixval_tl); } else if (pixval_tr == pixval_bl) { // 2nd diagonal is same color // use its value SCALE_SETPIX (dst_p + dlen, pixval_tr); } else { // blend all 4 SCALE_SETPIX (dst_p + dlen, Scale_Blend_1111 ( pixval_tl, pixval_bl, pixval_tr, pixval_br )); } } } SCALE_(PlatDone) (); } #endif /* GFXMODULE_SDL */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/opengl.h0000644000175000017500000000437410551324106020574 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OPENGL_H #define OPENGL_H #include "libs/graphics/sdl/sdl_common.h" int TFB_GL_InitGraphics (int driver, int flags, int width, int height); int TFB_GL_ConfigureVideo (int driver, int flags, int width, int height); void TFB_GL_UploadTransitionScreen (void); #ifdef HAVE_OPENGL #ifdef WIN32 #ifdef _MSC_VER #pragma comment (lib, "opengl32.lib") #pragma comment (lib, "glu32.lib") #endif /* To avoid including windows.h, Win32's needs APIENTRY and WINGDIAPI defined properly. */ #ifndef APIENTRY #define GLUT_APIENTRY_DEFINED #if __MINGW32__ || (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) #define APIENTRY __stdcall #else #define APIENTRY #endif #endif #ifndef WINAPI #define GLUT_WINAPI_DEFINED #if __MINGW32__ || (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) #define WINAPI __stdcall #else #define WINAPI #endif #endif /* This is from Win32's */ #ifndef CALLBACK #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) #define CALLBACK __stdcall #else #define CALLBACK #endif #endif /* This is from Win32's and */ #ifndef WINGDIAPI #define GLUT_WINGDIAPI_DEFINED #define WINGDIAPI __declspec(dllimport) #endif /* This is from Win32's */ #ifndef _WCHAR_T_DEFINED typedef unsigned short wchar_t; #define _WCHAR_T_DEFINED #endif #include "GL/glu.h" #else /* !defined(WIN32) */ #include "port.h" #include SDL_INCLUDE(SDL_opengl.h) #endif /* WIN32 */ #endif /* HAVE_OPENGL */ #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/biadv2x.c0000644000175000017500000003446410552135701020647 0ustar joeyjoey/* * Portions Copyright (C) 2003-2005 Alex Volkov (codepro@usa.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Core algorithm of the Advanced BiAdaptive screen scaler // Template // When this file is built standalone is produces a plain C version // Also #included by 2xscalers_mmx.c for an MMX version #ifdef GFXMODULE_SDL #include "libs/graphics/sdl/sdl_common.h" #include "types.h" #include "scalers.h" #include "scaleint.h" #include "2xscalers.h" // Advanced biadapt scaling to 2x // The name expands to either // Scale_BiAdaptAdvFilter (for plain C) or // Scale_MMX_BiAdaptAdvFilter (for MMX) // [others when platforms are added] void SCALE_(BiAdaptAdvFilter) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) { int x, y; const int w = src->w, h = src->h; int xend, yend; int dsrc, ddst; SDL_Rect *region = r; SDL_Rect limits; SDL_PixelFormat *fmt = dst->format; const int sp = src->pitch, dp = dst->pitch; const int bpp = fmt->BytesPerPixel; const int slen = sp / bpp, dlen = dp / bpp; // for clarity purposes, the 'pixels' array here is transposed Uint32 pixels[4][4]; static int resolve_coord[][2] = { {0, -1}, {1, -1}, { 2, 0}, { 2, 1}, {1, 2}, {0, 2}, {-1, 1}, {-1, 0}, {100, 100} // term }; Uint32 *src_p = (Uint32 *)src->pixels; Uint32 *dst_p = (Uint32 *)dst->pixels; // these macros are for clarity; they make the current pixel (0,0) // and allow to access pixels in all directions #define PIX(x, y) (pixels[1 + (x)][1 + (y)]) #define SRC(x, y) (src_p + (x) + ((y) * slen)) // commonly used operations, for clarity also // others are defined at their respective bpp levels #define BIADAPT_RGBHIGH 8000 #define BIADAPT_YUVLOW 30 #define BIADAPT_YUVMED 70 #define BIADAPT_YUVHIGH 130 // high tolerance pixel comparison #define BIADAPT_CMPRGB_HIGH(p1, p2) \ (p1 == p2 || SCALE_CMPRGB (p1, p2) <= BIADAPT_RGBHIGH) // low tolerance pixel comparison #define BIADAPT_CMPYUV_LOW(p1, p2) \ (p1 == p2 || SCALE_CMPYUV (p1, p2, BIADAPT_YUVLOW)) // medium tolerance pixel comparison #define BIADAPT_CMPYUV_MED(p1, p2) \ (p1 == p2 || SCALE_CMPYUV (p1, p2, BIADAPT_YUVMED)) // high tolerance pixel comparison #define BIADAPT_CMPYUV_HIGH(p1, p2) \ (p1 == p2 || SCALE_CMPYUV (p1, p2, BIADAPT_YUVHIGH)) SCALE_(PlatInit) (); // expand updated region if necessary // pixels neighbooring the updated region may // change as a result of updates limits.x = 0; limits.y = 0; limits.w = src->w; limits.h = src->h; Scale_ExpandRect (region, 2, &limits); xend = region->x + region->w; yend = region->y + region->h; dsrc = slen - region->w; ddst = (dlen - region->w) * 2; #define SCALE_GETPIX(p) ( *(Uint32 *)(p) ) #define SCALE_SETPIX(p, c) ( *(Uint32 *)(p) = (c) ) // move ptrs to the first updated pixel src_p += slen * region->y + region->x; dst_p += (dlen * region->y + region->x) * 2; for (y = region->y; y < yend; ++y, dst_p += ddst, src_p += dsrc) { for (x = region->x; x < xend; ++x, ++src_p, ++dst_p) { // pixel equality counter int cmatch; // most pixels will fall into 'all 4 equal' // pattern, so we check it first cmatch = 0; PIX (0, 0) = SCALE_GETPIX (SRC (0, 0)); SCALE_SETPIX (dst_p, PIX (0, 0)); if (y + 1 < h) { // check pixel below the current one PIX (0, 1) = SCALE_GETPIX (SRC (0, 1)); if (PIX (0, 0) == PIX (0, 1)) { SCALE_SETPIX (dst_p + dlen, PIX (0, 0)); cmatch |= 1; } } else { // last pixel in column - propagate PIX (0, 1) = PIX (0, 0); SCALE_SETPIX (dst_p + dlen, PIX (0, 0)); cmatch |= 1; } if (x + 1 < w) { // check pixel to the right from the current one PIX (1, 0) = SCALE_GETPIX (SRC (1, 0)); if (PIX (0, 0) == PIX (1, 0)) { SCALE_SETPIX (dst_p + 1, PIX (0, 0)); cmatch |= 2; } } else { // last pixel in row - propagate PIX (1, 0) = PIX (0, 0); SCALE_SETPIX (dst_p + 1, PIX (0, 0)); cmatch |= 2; } if (cmatch == 3) { if (y + 1 >= h || x + 1 >= w) { // last pixel in row/column and nearest // neighboor is identical dst_p++; SCALE_SETPIX (dst_p + dlen, PIX (0, 0)); continue; } // check pixel to the bottom-right PIX (1, 1) = SCALE_GETPIX (SRC (1, 1)); if (PIX (0, 0) == PIX (1, 1)) { // all 4 are equal - propagate dst_p++; SCALE_SETPIX (dst_p + dlen, PIX (0, 0)); continue; } } // some neighboors are different, lets check them if (x > 0) PIX (-1, 0) = SCALE_GETPIX (SRC (-1, 0)); else PIX (-1, 0) = PIX (0, 0); if (x + 2 < w) PIX (2, 0) = SCALE_GETPIX (SRC (2, 0)); else PIX (2, 0) = PIX (1, 0); if (y + 1 < h) { if (x > 0) PIX (-1, 1) = SCALE_GETPIX (SRC (-1, 1)); else PIX (-1, 1) = PIX (0, 1); if (x + 2 < w) { PIX (1, 1) = SCALE_GETPIX (SRC (1, 1)); PIX (2, 1) = SCALE_GETPIX (SRC (2, 1)); } else if (x + 1 < w) { PIX (1, 1) = SCALE_GETPIX (SRC (1, 1)); PIX (2, 1) = PIX (1, 1); } else { PIX (1, 1) = PIX (0, 1); PIX (2, 1) = PIX (0, 1); } } else { // last pixel in column PIX (-1, 1) = PIX (-1, 0); PIX (1, 1) = PIX (1, 0); PIX (2, 1) = PIX (2, 0); } if (y + 2 < h) { PIX (0, 2) = SCALE_GETPIX (SRC (0, 2)); if (x > 0) PIX (-1, 2) = SCALE_GETPIX (SRC (-1, 2)); else PIX (-1, 2) = PIX (0, 2); if (x + 2 < w) { PIX (1, 2) = SCALE_GETPIX (SRC (1, 2)); PIX (2, 2) = SCALE_GETPIX (SRC (2, 2)); } else if (x + 1 < w) { PIX (1, 2) = SCALE_GETPIX (SRC (1, 2)); PIX (2, 2) = PIX (1, 2); } else { PIX (1, 2) = PIX (0, 2); PIX (2, 2) = PIX (0, 2); } } else { // last pixel in column PIX (-1, 2) = PIX (-1, 1); PIX (0, 2) = PIX (0, 1); PIX (1, 2) = PIX (1, 1); PIX (2, 2) = PIX (2, 1); } if (y > 0) { PIX (0, -1) = SCALE_GETPIX (SRC (0, -1)); if (x > 0) PIX (-1, -1) = SCALE_GETPIX (SRC (-1, -1)); else PIX (-1, -1) = PIX (0, -1); if (x + 2 < w) { PIX (1, -1) = SCALE_GETPIX (SRC (1, -1)); PIX (2, -1) = SCALE_GETPIX (SRC (2, -1)); } else if (x + 1 < w) { PIX (1, -1) = SCALE_GETPIX (SRC (1, -1)); PIX (2, -1) = PIX (1, -1); } else { PIX (1, -1) = PIX (0, -1); PIX (2, -1) = PIX (0, -1); } } else { PIX (-1, -1) = PIX (-1, 0); PIX (0, -1) = PIX (0, 0); PIX (1, -1) = PIX (1, 0); PIX (2, -1) = PIX (2, 0); } // check pixel below the current one if (!(cmatch & 1)) { if (SCALE_CMPYUV (PIX (0, 0), PIX (0, 1), BIADAPT_YUVLOW)) { SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 ( PIX (0, 0), PIX (0, 1)) ); cmatch |= 1; } // detect a 2:1 line going across the current pixel else if ( (PIX (0, 0) == PIX (-1, 0) && PIX (0, 0) == PIX (1, 1) && PIX (0, 0) == PIX (2, 1) && ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 0)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))) || (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 2)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) || (PIX (0, 0) == PIX (1, 0) && PIX (0, 0) == PIX (-1, 1) && PIX (0, 0) == PIX (2, -1) && ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1))) || (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 2)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 0))))) ) { SCALE_SETPIX (dst_p + dlen, PIX (0, 0)); } // detect a 2:1 line going across the pixel below current else if ( (PIX (0, 1) == PIX (-1, 0) && PIX (0, 1) == PIX (1, 1) && PIX (0, 1) == PIX (2, 2) && ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 0)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))) || (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 2))))) || (PIX (0, 1) == PIX (1, 0) && PIX (0, 1) == PIX (-1, 1) && PIX (0, 1) == PIX (2, 0) && ((!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 0)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, -1))) || (!BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (-1, 2)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (0, 2)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (1, 1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 1), PIX (2, 1))))) ) { SCALE_SETPIX (dst_p + dlen, PIX (0, 1)); } else SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 ( PIX (0, 0), PIX (0, 1)) ); } dst_p++; // check pixel to the right from the current one if (!(cmatch & 2)) { if (SCALE_CMPYUV (PIX (0, 0), PIX (1, 0), BIADAPT_YUVLOW)) { SCALE_SETPIX (dst_p, Scale_Blend_11 ( PIX (0, 0), PIX (1, 0)) ); cmatch |= 2; } // detect a 1:2 line going across the current pixel else if ( (PIX (0, 0) == PIX (1, -1) && PIX (0, 0) == PIX (0, 1) && PIX (0, 0) == PIX (-1, 2) && ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 1))) || (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, 1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))))) || (PIX (0, 0) == PIX (0, -1) && PIX (0, 0) == PIX (1, 1) && PIX (0, 0) == PIX (1, 2) && ((!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (-1, 0)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (0, 2))) || (!BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (1, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 1)) && !BIADAPT_CMPRGB_HIGH (PIX (0, 0), PIX (2, 2))))) ) { SCALE_SETPIX (dst_p, PIX (0, 0)); } // detect a 1:2 line going across the pixel to the right else if ( (PIX (1, 0) == PIX (1, -1) && PIX (1, 0) == PIX (0, 1) && PIX (1, 0) == PIX (0, 2) && ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 1)) && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, 2))) || (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 1)) && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))))) || (PIX (1, 0) == PIX (0, -1) && PIX (1, 0) == PIX (1, 1) && PIX (1, 0) == PIX (2, 2) && ((!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (-1, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (0, 1)) && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, 2))) || (!BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (1, -1)) && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 0)) && !BIADAPT_CMPRGB_HIGH (PIX (1, 0), PIX (2, 1))))) ) { SCALE_SETPIX (dst_p, PIX (1, 0)); } else SCALE_SETPIX (dst_p, Scale_Blend_11 ( PIX (0, 0), PIX (1, 0)) ); } if (PIX (0, 0) == PIX (1, 1) && PIX (1, 0) == PIX (0, 1)) { // diagonals are equal int *coord; int cl, cr; Uint32 clr; // both pairs are equal, have to resolve the pixel // race; we try detecting which color is // the background by looking for a line or an edge // examine 8 pixels surrounding the current quad cl = cr = 2; for (coord = resolve_coord[0]; *coord < 100; coord += 2) { clr = PIX (coord[0], coord[1]); if (BIADAPT_CMPYUV_MED (clr, PIX (0, 0))) cl++; else if (BIADAPT_CMPYUV_MED (clr, PIX (1, 0))) cr++; } // least count wins if (cl > cr) clr = PIX (1, 0); else if (cr > cl) clr = PIX (0, 0); else clr = Scale_Blend_11 (PIX (0, 0), PIX (1, 0)); SCALE_SETPIX (dst_p + dlen, clr); continue; } if (cmatch == 3 || (BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (0, 1)) && BIADAPT_CMPYUV_LOW (PIX (1, 0), PIX (1, 1)))) { SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 ( PIX (0, 1), PIX (1, 0)) ); continue; } else if (cmatch && BIADAPT_CMPYUV_LOW (PIX (0, 0), PIX (1, 1))) { SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 ( PIX (0, 0), PIX (1, 1)) ); continue; } // check pixel to the bottom-right if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1)) && BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) { if (SCALE_GETY (PIX (0, 0)) > SCALE_GETY (PIX (1, 0))) { SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 ( PIX (0, 0), PIX (1, 1)) ); } else { SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 ( PIX (1, 0), PIX (0, 1)) ); } } else if (BIADAPT_CMPYUV_HIGH (PIX (0, 0), PIX (1, 1))) { // main diagonal is same color // use its value SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 ( PIX (0, 0), PIX (1, 1)) ); } else if (BIADAPT_CMPYUV_HIGH (PIX (1, 0), PIX (0, 1))) { // 2nd diagonal is same color // use its value SCALE_SETPIX (dst_p + dlen, Scale_Blend_11 ( PIX (1, 0), PIX (0, 1)) ); } else { // blend all 4 SCALE_SETPIX (dst_p + dlen, Scale_Blend_1111 ( PIX (0, 0), PIX (0, 1), PIX (1, 0), PIX (1, 1) )); } } } SCALE_(PlatDone) (); } #endif /* GFXMODULE_SDL */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/bilinear2x.c0000644000175000017500000000611510552135701021337 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Core algorithm of the BiLinear screen scaler // Template // When this file is built standalone is produces a plain C version // Also #included by 2xscalers_mmx.c for an MMX version #ifdef GFXMODULE_SDL #include "libs/graphics/sdl/sdl_common.h" #include "types.h" #include "scalers.h" #include "scaleint.h" #include "2xscalers.h" // Bilinear scaling to 2x // The name expands to either // Scale_BilinearFilter (for plain C) or // Scale_MMX_BilinearFilter (for MMX) // Scale_SSE_BilinearFilter (for SSE) // [others when platforms are added] void SCALE_(BilinearFilter) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) { int x, y; const int w = src->w, h = src->h; int xend, yend; int dsrc, ddst; SDL_Rect *region = r; SDL_Rect limits; SDL_PixelFormat *fmt = dst->format; const int pitch = src->pitch, dp = dst->pitch; const int bpp = fmt->BytesPerPixel; const int len = pitch / bpp, dlen = dp / bpp; Uint32 p[4]; // influential pixels array Uint32 *srow0 = (Uint32 *) src->pixels; Uint32 *dst_p = (Uint32 *) dst->pixels; SCALE_(PlatInit) (); // expand updated region if necessary // pixels neighbooring the updated region may // change as a result of updates limits.x = 0; limits.y = 0; limits.w = w; limits.h = h; Scale_ExpandRect (region, 1, &limits); xend = region->x + region->w; yend = region->y + region->h; dsrc = len - region->w; ddst = (dlen - region->w) * 2; // move ptrs to the first updated pixel srow0 += len * region->y + region->x; dst_p += (dlen * region->y + region->x) * 2; for (y = region->y; y < yend; ++y, dst_p += ddst, srow0 += dsrc) { Uint32 *srow1; SCALE_(Prefetch) (srow0 + 16); SCALE_(Prefetch) (srow0 + 32); if (y < h - 1) srow1 = srow0 + len; else srow1 = srow0; SCALE_(Prefetch) (srow1 + 16); SCALE_(Prefetch) (srow1 + 32); for (x = region->x; x < xend; ++x, ++srow0, ++srow1, dst_p += 2) { if (x < w - 1) { // can blend directly from pixels SCALE_BILINEAR_BLEND4 (srow0, srow1, dst_p, dlen); } else { // need to make temp pixel rows p[0] = srow0[0]; p[1] = p[0]; p[2] = srow1[0]; p[3] = p[2]; SCALE_BILINEAR_BLEND4 (&p[0], &p[2], dst_p, dlen); } } SCALE_(Prefetch) (srow0 + dsrc); SCALE_(Prefetch) (srow0 + dsrc + 16); SCALE_(Prefetch) (srow1 + dsrc); SCALE_(Prefetch) (srow1 + dsrc + 16); } SCALE_(PlatDone) (); } #endif /* GFXMODULE_SDL */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/dcqueue.h0000600000175000017500000000435110543202053020723 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef DCQUEUE_H #define DCQUEUE_H // Maximum size of the DCQ. The larger the DCQ, the larger frameskips // become tolerable before initiating livelock deterrence and game // slowdown. Other constants for controlling the frameskip/slowdown // balance may be found in sdl_common.c near TFB_FlushGraphics. // Livelock deterrance constants. Because the entire screen is rarely // refreshed, we may not drop draw commands on the floor with abandon. // Furthermore, if the main program is queuing commands at a speed // comparable to our processing of the commands, we never finish and // the game freezes. Thus, if the queue starts out larger than // DCQ_FORCE_SLOWDOWN_SIZE, or DCQ_LIVELOCK_MAX commands find // themselves being processed in one go, livelock deterrence is // enabled, and TFB_FlushGraphics locks the DCQ until it has processed // all entries. If batched but pending commands exceed DCQ_FORCE_BREAK_SIZE, // a continuity break is performed. This will effectively slow down the // game logic, a fate we seek to avoid - however, it seems to be unavoidable // on slower machines. Even there, it's seems nonexistent outside of // communications screens. --Michael #ifdef DCQ_OF_DOOM #define DCQ_MAX 512 #define DCQ_FORCE_SLOWDOWN_SIZE 128 #define DCQ_FORCE_BREAK_SIZE 512 #define DCQ_LIVELOCK_MAX 256 #else #define DCQ_MAX 16384 #define DCQ_FORCE_SLOWDOWN_SIZE 4096 #define DCQ_FORCE_BREAK_SIZE 16384 #define DCQ_LIVELOCK_MAX 4096 #endif extern CondVar RenderingCond; #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/2xscalers_mmx.c0000644000175000017500000000775010552135701022075 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "port.h" #include "libs/platform.h" #if defined(MMX_ASM) #include "libs/graphics/sdl/sdl_common.h" #include "types.h" #include "scalers.h" #include "scaleint.h" #include "2xscalers.h" #include "2xscalers_mmx.h" // MMX name for all functions #undef SCALE_ #define SCALE_(name) Scale ## _MMX_ ## name // Tell them which opcodes we want to support #undef USE_MOVNTQ #undef USE_PREFETCH #undef USE_PSADBW // And Bring in inline asm functions #include "scalemmx.h" // Scaler function lookup table // const Scale_FuncDef_t Scale_MMX_Functions[] = { {TFB_GFXFLAGS_SCALE_BILINEAR, Scale_MMX_BilinearFilter}, {TFB_GFXFLAGS_SCALE_BIADAPT, Scale_BiAdaptFilter}, {TFB_GFXFLAGS_SCALE_BIADAPTADV, Scale_MMX_BiAdaptAdvFilter}, {TFB_GFXFLAGS_SCALE_TRISCAN, Scale_MMX_TriScanFilter}, {TFB_GFXFLAGS_SCALE_HQXX, Scale_MMX_HqFilter}, // Default {0, Scale_MMX_Nearest} }; // MMX transformation multipliers Uint64 mmx_888to555_mult; Uint64 mmx_Y_mult; Uint64 mmx_U_mult; Uint64 mmx_V_mult; // Uint64 mmx_YUV_threshold = 0x00300706; original hq2x threshold //Uint64 mmx_YUV_threshold = 0x0030100e; Uint64 mmx_YUV_threshold = 0x0040120c; void Scale_MMX_PrepPlatform (const SDL_PixelFormat* fmt) { // prepare the channel-shuffle multiplier mmx_888to555_mult = ((Uint64)0x0400) << (fmt->Rshift * 2) | ((Uint64)0x0020) << (fmt->Gshift * 2) | ((Uint64)0x0001) << (fmt->Bshift * 2); // prepare the RGB->YUV multipliers mmx_Y_mult = ((Uint64)(uint16)YUV_matrix[YUV_XFORM_R][YUV_XFORM_Y]) << (fmt->Rshift * 2) | ((Uint64)(uint16)YUV_matrix[YUV_XFORM_G][YUV_XFORM_Y]) << (fmt->Gshift * 2) | ((Uint64)(uint16)YUV_matrix[YUV_XFORM_B][YUV_XFORM_Y]) << (fmt->Bshift * 2); mmx_U_mult = ((Uint64)(uint16)YUV_matrix[YUV_XFORM_R][YUV_XFORM_U]) << (fmt->Rshift * 2) | ((Uint64)(uint16)YUV_matrix[YUV_XFORM_G][YUV_XFORM_U]) << (fmt->Gshift * 2) | ((Uint64)(uint16)YUV_matrix[YUV_XFORM_B][YUV_XFORM_U]) << (fmt->Bshift * 2); mmx_V_mult = ((Uint64)(uint16)YUV_matrix[YUV_XFORM_R][YUV_XFORM_V]) << (fmt->Rshift * 2) | ((Uint64)(uint16)YUV_matrix[YUV_XFORM_G][YUV_XFORM_V]) << (fmt->Gshift * 2) | ((Uint64)(uint16)YUV_matrix[YUV_XFORM_B][YUV_XFORM_V]) << (fmt->Bshift * 2); mmx_YUV_threshold = (SCALE_DIFFYUV_TY << 16) | (SCALE_DIFFYUV_TU << 8) | SCALE_DIFFYUV_TV; } // Nearest Neighbor scaling to 2x // void Scale_MMX_Nearest (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "nearest2x.c" // Bilinear scaling to 2x // void Scale_MMX_BilinearFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "bilinear2x.c" // Advanced Biadapt scaling to 2x // void Scale_MMX_BiAdaptAdvFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "biadv2x.c" // Triscan scaling to 2x // derivative of 'scale2x' -- scale2x.sf.net // void Scale_MMX_TriScanFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "triscan2x.c" // Hq2x scaling // (adapted from 'hq2x' by Maxim Stepin -- www.hiend3d.com/hq2x.html) // void Scale_MMX_HqFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "hq2x.c" #endif /* MMX_ASM */ #endif /* GFXMODULE_SDL */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/pure.h0000644000175000017500000000176410551324106020263 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PURE_H #define PURE_H #include "libs/graphics/sdl/sdl_common.h" int TFB_Pure_InitGraphics (int driver, int flags, int width, int height); int TFB_Pure_ConfigureVideo (int driver, int flags, int width, int height); #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/2xscalers.h0000600000175000017500000000243310543202052021174 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _2XSCALERS_H_ #define _2XSCALERS_H_ void Scale_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_BiAdaptFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_TriScanFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_HqFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); extern const Scale_FuncDef_t Scale_C_Functions[]; #endif /* _2XSCALERS_H_ */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/3do_funcs.c0000600000175000017500000001332110543202053021143 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "sdl_common.h" #include "pure.h" #include "opengl.h" #include "primitives.h" #include "units.h" #include "graphics/drawcmd.h" #include "graphics/tfb_draw.h" int batch_depth = 0; //Status: Not entirely unimplemented! BOOLEAN InitGraphics (int argc, char* argv[], COUNT KbytesRequired) // Kbytes should only matter if we wanted to port Starcon2 to the // hand-helds... { BOOLEAN ret; LoadDisplay (&_pCurDisplay); ActivateDisplay (); (void) argc; /* lint */ (void) argv; /* lint */ (void) KbytesRequired; /* lint */ ret = TRUE; return (ret); } // Status: Unimplemented void UninitGraphics () // Also probably empty { // HFree (DrawCommandQueue); This is static now! //mem_uninit (); } /* Batching and Unbatching functions. A "Batch" is a collection of DrawCommands that will never be flipped to the screen half-rendered. BatchGraphics and UnbatchGraphics function vaguely like a non-blocking recursive lock to do this respect. */ void BatchGraphics (void) { TFB_BatchGraphics (); } void UnbatchGraphics (void) { TFB_UnbatchGraphics (); } /* Sleeps this thread until all Draw Commands queued by that thread have been processed. */ void FlushGraphics () { TFB_DrawScreen_WaitForSignal (); } static void ExpandRect (PRECT rect, int expansion) { if (rect->corner.x - expansion >= 0) { rect->extent.width += expansion; rect->corner.x -= expansion; } else { rect->extent.width += rect->corner.x; rect->corner.x = 0; } if (rect->corner.y - expansion >= 0) { rect->extent.height += expansion; rect->corner.y -= expansion; } else { rect->extent.height += rect->corner.y; rect->corner.y = 0; } if (rect->corner.x + rect->extent.width + expansion <= SCREEN_WIDTH) rect->extent.width += expansion; else rect->extent.width = SCREEN_WIDTH - rect->corner.x; if (rect->corner.y + rect->extent.height + expansion <= SCREEN_HEIGHT) rect->extent.height += expansion; else rect->extent.height = SCREEN_HEIGHT - rect->corner.y; } void SetTransitionSource (PRECT pRect) { RECT ActualRect; if (pRect) { /* expand the rect to accomodate scalers in OpenGL mode */ ActualRect = *pRect; pRect = &ActualRect; ExpandRect (&ActualRect, 2); } TFB_DrawScreen_Copy(pRect, TFB_SCREEN_MAIN, TFB_SCREEN_TRANSITION); } // Status: Implemented void ScreenTransition (int TransType, PRECT pRect) { const float DURATION = (31.0f / 60.0f); // in seconds Uint32 last_time = 0, current_time, delta_time, add_amount; (void) TransType; /* dodge compiler warning */ if (pRect) { TransitionClipRect.x = pRect->corner.x; TransitionClipRect.y = pRect->corner.y; TransitionClipRect.w = pRect->extent.width; TransitionClipRect.h = pRect->extent.height; } else { TransitionClipRect.x = TransitionClipRect.y = 0; TransitionClipRect.w = ScreenWidth; TransitionClipRect.h = ScreenHeight; } #ifdef HAVE_OPENGL if (GraphicsDriver == TFB_GFXDRIVER_SDL_OPENGL) { TFB_GL_UploadTransitionScreen (); } #endif TransitionAmount = 0; FlushGraphics (); last_time = SDL_GetTicks (); for (;;) { SDL_Delay (10); current_time = SDL_GetTicks (); delta_time = current_time - last_time; last_time = current_time; add_amount = (Uint32) ((delta_time / 1000.0f / DURATION) * 255); if (TransitionAmount + add_amount >= 255) break; TransitionAmount += add_amount; } TransitionAmount = 255; } BOOLEAN _image_intersect (PIMAGE_BOX box1, PIMAGE_BOX box2, PRECT rect) { BOOLEAN ret; SDL_Surface *img1, *img2; int img1w, img1xpos, img1ypos, img2w, img2xpos, img2ypos; int x,y; Uint32 img1key, img2key; Uint32 img1mask, img2mask; GetPixelFn getpixel1, getpixel2; img1 = (SDL_Surface *)box1->FramePtr->image->NormalImg; img2 = (SDL_Surface *)box2->FramePtr->image->NormalImg; getpixel1 = getpixel_for(img1); getpixel2 = getpixel_for(img2); img1w = img1->w; img1xpos = box1->Box.corner.x; img1ypos = box1->Box.corner.y; if (img1->format->Amask) { // use alpha transparency info img1mask = img1->format->Amask; // consider any not fully transparent pixel collidable img1key = 0; } else { // colorkey transparency img1mask = ~img1->format->Amask; img1key = img1->format->colorkey & img1mask; } img2w = img2->w; img2xpos = box2->Box.corner.x; img2ypos = box2->Box.corner.y; if (img2->format->Amask) { // use alpha transparency info img2mask = img2->format->Amask; // consider any not fully transparent pixel collidable img2key = 0; } else { // colorkey transparency img2mask = ~img2->format->Amask; img2key = img2->format->colorkey & img2mask; } for (y = rect->corner.y; y < rect->corner.y + rect->extent.height; ++y) { for (x = rect->corner.x; x < rect->corner.x + rect->extent.width; ++x) { Uint32 p1 = getpixel1(img1, x - img1xpos, y - img1ypos) & img1mask; Uint32 p2 = getpixel2(img2, x - img2xpos, y - img2ypos) & img2mask; if ((p1 != img1key) && (p2 != img2key)) { return TRUE; } } } ret = FALSE; return (ret); } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/bbox.h0000600000175000017500000000325010543202052020216 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gfxlib.h" #include "graphics/tfb_draw.h" #include "graphics/gfx_common.h" #ifndef _BBOX_H_ #define _BBOX_H_ /* Bounding Box operations. These operations are NOT synchronized. * However, they should only be accessed by TFB_FlushGraphics and * TFB_SwapBuffers, or the routines that they exclusively call -- all * of which are only callable by the thread that is permitted to touch * the screen. No explicit locks should therefore be required. */ typedef struct { int valid; // If zero, the next point registered becomes the region RECT region; // The actual modified rectangle RECT clip; // Points outside of this rectangle are pushed to // the closest border point } TFB_BoundingBox; extern TFB_BoundingBox TFB_BBox; void TFB_BBox_RegisterPoint (int x, int y); void TFB_BBox_RegisterRect (PRECT r); void TFB_BBox_RegisterCanvas (TFB_Canvas c, int x, int y); void TFB_BBox_Reset (void); void TFB_BBox_GetClipRect (TFB_Canvas c); #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/primitives.c0000600000175000017500000001505710543202052021462 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "sdl_common.h" #include "primitives.h" // Pixel drawing routines Uint32 getpixel_8(SDL_Surface *surface, int x, int y) { /* Here p is the address to the pixel we want to retrieve */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x; return *p; } void putpixel_8(SDL_Surface *surface, int x, int y, Uint32 pixel) { /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 1; *p = pixel; } Uint32 getpixel_16(SDL_Surface *surface, int x, int y) { /* Here p is the address to the pixel we want to retrieve */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 2; return *(Uint16 *)p; } void putpixel_16(SDL_Surface *surface, int x, int y, Uint32 pixel) { /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 2; *(Uint16 *)p = pixel; } Uint32 getpixel_24_be(SDL_Surface *surface, int x, int y) { /* Here p is the address to the pixel we want to retrieve */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 3; return p[0] << 16 | p[1] << 8 | p[2]; } void putpixel_24_be(SDL_Surface *surface, int x, int y, Uint32 pixel) { /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 3; p[0] = (pixel >> 16) & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = pixel & 0xff; } Uint32 getpixel_24_le(SDL_Surface *surface, int x, int y) { /* Here p is the address to the pixel we want to retrieve */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 3; return p[0] | p[1] << 8 | p[2] << 16; } void putpixel_24_le(SDL_Surface *surface, int x, int y, Uint32 pixel) { /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 3; p[0] = pixel & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = (pixel >> 16) & 0xff; } Uint32 getpixel_32(SDL_Surface *surface, int x, int y) { /* Here p is the address to the pixel we want to retrieve */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 4; return *(Uint32 *)p; } void putpixel_32(SDL_Surface *surface, int x, int y, Uint32 pixel) { /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 4; *(Uint32 *)p = pixel; } GetPixelFn getpixel_for(SDL_Surface *surface) { int bpp = surface->format->BytesPerPixel; switch (bpp) { case 1: return &getpixel_8; break; case 2: return &getpixel_16; break; case 3: if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { return &getpixel_24_be; } else { return &getpixel_24_le; } break; case 4: return &getpixel_32; break; } return NULL; } PutPixelFn putpixel_for(SDL_Surface *surface) { int bpp = surface->format->BytesPerPixel; switch (bpp) { case 1: return &putpixel_8; break; case 2: return &putpixel_16; break; case 3: if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { return &putpixel_24_be; } else { return &putpixel_24_le; } break; case 4: return &putpixel_32; break; } return NULL; } /* Line drawing routine * Adapted from Paul Heckbert's implementation of Bresenham's algorithm, * 3 Sep 85; taken from Graphics Gems I */ void line(int x1, int y1, int x2, int y2, Uint32 color, PutPixelFn plot, SDL_Surface *surface) { int d, x, y, ax, ay, sx, sy, dx, dy; SDL_Rect r; SDL_GetClipRect (surface, &r); if (!clip_line (&x1, &y1, &x2, &y2, &r)) return; // line is completely outside clipping rectangle dx = x2-x1; ax = ((dx < 0) ? -dx : dx) << 1; sx = (dx < 0) ? -1 : 1; dy = y2-y1; ay = ((dy < 0) ? -dy : dy) << 1; sy = (dy < 0) ? -1 : 1; x = x1; y = y1; if (ax > ay) { d = ay - (ax >> 1); for (;;) { (*plot)(surface, x, y, color); if (x == x2) return; if (d >= 0) { y += sy; d -= ax; } x += sx; d += ay; } } else { d = ax - (ay >> 1); for (;;) { (*plot)(surface, x, y, color); if (y == y2) return; if (d >= 0) { x += sx; d -= ay; } y += sy; d += ax; } } } // Clips line against rectangle using Cohen-Sutherland algorithm enum {C_TOP = 0x1, C_BOTTOM = 0x2, C_RIGHT = 0x4, C_LEFT = 0x8}; static int compute_code (float x, float y, float xmin, float ymin, float xmax, float ymax) { int c = 0; if (y > ymax) c |= C_TOP; else if (y < ymin) c |= C_BOTTOM; if (x > xmax) c |= C_RIGHT; else if (x < xmin) c |= C_LEFT; return c; } int clip_line (int *lx1, int *ly1, int *lx2, int *ly2, SDL_Rect *r) { int C0, C1, C; float x, y, x0, y0, x1, y1, xmin, ymin, xmax, ymax; x0 = (float)*lx1; y0 = (float)*ly1; x1 = (float)*lx2; y1 = (float)*ly2; xmin = (float)r->x; ymin = (float)r->y; xmax = (float)r->x + r->w - 1; ymax = (float)r->y + r->h - 1; C0 = compute_code (x0, y0, xmin, ymin, xmax, ymax); C1 = compute_code (x1, y1, xmin, ymin, xmax, ymax); for (;;) { /* trivial accept: both ends in rectangle */ if ((C0 | C1) == 0) { *lx1 = (int)x0; *ly1 = (int)y0; *lx2 = (int)x1; *ly2 = (int)y1; return 1; } /* trivial reject: both ends on the external side of the rectangle */ if ((C0 & C1) != 0) return 0; /* normal case: clip end outside rectangle */ C = C0 ? C0 : C1; if (C & C_TOP) { x = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0); y = ymax; } else if (C & C_BOTTOM) { x = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0); y = ymin; } else if (C & C_RIGHT) { x = xmax; y = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0); } else { x = xmin; y = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0); } /* set new end point and iterate */ if (C == C0) { x0 = x; y0 = y; C0 = compute_code (x0, y0, xmin, ymin, xmax, ymax); } else { x1 = x; y1 = y; C1 = compute_code (x1, y1, xmin, ymin, xmax, ymax); } } } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/rotozoom.c0000600000175000017500000005617510543202053021166 0ustar joeyjoey/* rotozoom.c - rotozoomer for 32bit or 8bit surfaces LGPL (c) A. Schiffler Note by sc2 developers: Taken from SDL_gfx library and modified, original code can be downloaded from http://www.ferzkopp.net/Software/SDL_gfx-2.0/ */ #ifdef GFXMODULE_SDL #include #include #include "misc.h" #include "port.h" #include "rotozoom.h" #define MAX(a,b) (((a) > (b)) ? (a) : (b)) /* 32bit Zoomer with optional anti-aliasing by bilinear interpolation. Zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. */ int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int smooth) { int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep; tColorRGBA *c00, *c01, *c10, *c11; tColorRGBA *sp, *csp, *dp; int sgap, dgap; /* * Variable setup */ if (smooth) { /* * For interpolation: assume source dimension is one pixel */ /* * smaller to avoid overflow on right and bottom edge. */ sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w); sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h); } else { sx = (int) (65536.0 * (float) src->w / (float) dst->w); sy = (int) (65536.0 * (float) src->h / (float) dst->h); } /* * Allocate memory for row increments */ if ((sax = (int *) alloca((dst->w + 1) * sizeof(Uint32))) == NULL) { return (-1); } if ((say = (int *) alloca((dst->h + 1) * sizeof(Uint32))) == NULL) { return (-1); } /* * Precalculate row increments */ csx = 0; csax = sax; for (x = 0; x <= dst->w; x++) { *csax = csx; csax++; csx &= 0xffff; csx += sx; } csy = 0; csay = say; for (y = 0; y <= dst->h; y++) { *csay = csy; csay++; csy &= 0xffff; csy += sy; } /* * Pointer setup */ sp = csp = (tColorRGBA *) src->pixels; dp = (tColorRGBA *) dst->pixels; sgap = src->pitch - src->w * 4; dgap = dst->pitch - dst->w * 4; /* * Switch between interpolating and non-interpolating code */ if (smooth) { /* * Interpolating Zoom */ /* * Scan destination */ csay = say; for (y = 0; y < dst->h; y++) { /* * Setup color source pointers */ c00 = csp; c01 = csp; c01++; c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch); c11 = c10; c11++; csax = sax; for (x = 0; x < dst->w; x++) { /* * Interpolate colors */ ex = (*csax & 0xffff); ey = (*csay & 0xffff); t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; dp->r = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; dp->g = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; dp->b = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; dp->a = (((t2 - t1) * ey) >> 16) + t1; /* * Advance source pointers */ csax++; sstep = (*csax >> 16); c00 += sstep; c01 += sstep; c10 += sstep; c11 += sstep; /* * Advance destination pointer */ dp++; } /* * Advance source pointer */ csay++; csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch); /* * Advance destination pointers */ dp = (tColorRGBA *) ((Uint8 *) dp + dgap); } } else { /* * Non-Interpolating Zoom */ csay = say; for (y = 0; y < dst->h; y++) { sp = csp; csax = sax; for (x = 0; x < dst->w; x++) { /* * Draw */ *dp = *sp; /* * Advance source pointers */ csax++; sp += (*csax >> 16); /* * Advance destination pointer */ dp++; } /* * Advance source pointer */ csay++; csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch); /* * Advance destination pointers */ dp = (tColorRGBA *) ((Uint8 *) dp + dgap); } } return (0); } /* 8bit Zoomer without smoothing. Zoomes 8bit palette/Y 'src' surface to 'dst' surface. */ int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst) { Uint32 sx, sy, *sax, *say, *csax, *csay, csx, csy; int x, y; Uint8 *sp, *dp, *csp; int dgap; /* * Variable setup */ sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w); sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h); /* * Allocate memory for row increments */ if ((sax = (Uint32 *) alloca(dst->w * sizeof(Uint32))) == NULL) { return (-1); } if ((say = (Uint32 *) alloca(dst->h * sizeof(Uint32))) == NULL) { return (-1); } /* * Precalculate row increments */ csx = 0; csax = sax; for (x = 0; x < dst->w; x++) { csx += sx; *csax = (csx >> 16); csx &= 0xffff; csax++; } csy = 0; csay = say; for (y = 0; y < dst->h; y++) { csy += sy; *csay = (csy >> 16); csy &= 0xffff; csay++; } csx = 0; csax = sax; for (x = 0; x < dst->w; x++) { csx += (*csax); csax++; } csy = 0; csay = say; for (y = 0; y < dst->h; y++) { csy += (*csay); csay++; } /* * Pointer setup */ sp = csp = (Uint8 *) src->pixels; dp = (Uint8 *) dst->pixels; dgap = dst->pitch - dst->w; /* * Draw */ csay = say; for (y = 0; y < dst->h; y++) { csax = sax; sp = csp; for (x = 0; x < dst->w; x++) { /* * Draw */ *dp = *sp; /* * Advance source pointers */ sp += (*csax); csax++; /* * Advance destination pointer */ dp++; } /* * Advance source pointer (for row) */ csp += ((*csay) * src->pitch); csay++; /* * Advance destination pointers */ dp += dgap; } return (0); } /* 32bit Rotozoomer with optional anti-aliasing by bilinear interpolation. Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface. */ void transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int smooth) { int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh; tColorRGBA c00, c01, c10, c11; tColorRGBA *pc, *sp; int gap; /* * Variable setup */ xd = ((src->w - dst->w) << 15); yd = ((src->h - dst->h) << 15); ax = (cx << 16) - (icos * cx); ay = (cy << 16) - (isin * cx); sw = src->w - 1; sh = src->h - 1; pc = dst->pixels; gap = dst->pitch - dst->w * 4; /* * Switch between interpolating and non-interpolating code */ if (smooth) { for (y = 0; y < dst->h; y++) { dy = cy - y; sdx = (ax + (isin * dy)) + xd; sdy = (ay - (icos * dy)) + yd; for (x = 0; x < dst->w; x++) { dx = (sdx >> 16); dy = (sdy >> 16); if ((dx >= -1) && (dy >= -1) && (dx < src->w) && (dy < src->h)) { if ((dx >= 0) && (dy >= 0) && (dx < sw) && (dy < sh)) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; c00 = *sp; sp += 1; c01 = *sp; sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch); sp -= 1; c10 = *sp; sp += 1; c11 = *sp; } else if ((dx == sw) && (dy == sh)) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; c00 = *sp; c01 = *sp; c10 = *sp; c11 = *sp; } else if ((dx == -1) && (dy == -1)) { sp = (tColorRGBA *) (src->pixels); c00 = *sp; c01 = *sp; c10 = *sp; c11 = *sp; } else if ((dx == -1) && (dy == sh)) { sp = (tColorRGBA *) (src->pixels); sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); c00 = *sp; c01 = *sp; c10 = *sp; c11 = *sp; } else if ((dx == sw) && (dy == -1)) { sp = (tColorRGBA *) (src->pixels); sp += dx; c00 = *sp; c01 = *sp; c10 = *sp; c11 = *sp; } else if (dx == -1) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); c00 = *sp; c01 = *sp; c10 = *sp; sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch); c11 = *sp; } else if (dy == -1) { sp = (tColorRGBA *) (src->pixels); sp += dx; c00 = *sp; c01 = *sp; c10 = *sp; sp += 1; c11 = *sp; } else if (dx == sw) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; c00 = *sp; c01 = *sp; sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch); c10 = *sp; c11 = *sp; } else if (dy == sh) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; c00 = *sp; sp += 1; c01 = *sp; c10 = *sp; c11 = *sp; } /* * Interpolate colors */ ex = (sdx & 0xffff); ey = (sdy & 0xffff); t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; pc->r = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; pc->g = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; pc->b = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; pc->a = (((t2 - t1) * ey) >> 16) + t1; } sdx += icos; sdy += isin; pc++; } pc = (tColorRGBA *) ((Uint8 *) pc + gap); } } else { for (y = 0; y < dst->h; y++) { dy = cy - y; sdx = (ax + (isin * dy)) + xd; sdy = (ay - (icos * dy)) + yd; for (x = 0; x < dst->w; x++) { dx = (short) (sdx >> 16); dy = (short) (sdy >> 16); if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; *pc = *sp; } sdx += icos; sdy += isin; pc++; } pc = (tColorRGBA *) ((Uint8 *) pc + gap); } } } /* 8bit Rotozoomer without smoothing Rotates and zoomes 8bit palette/Y 'src' surface to 'dst' surface. */ void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos) { int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh; tColorY *pc, *sp; int gap; /* * Variable setup */ xd = ((src->w - dst->w) << 15); yd = ((src->h - dst->h) << 15); ax = (cx << 16) - (icos * cx); ay = (cy << 16) - (isin * cx); sw = src->w - 1; sh = src->h - 1; pc = dst->pixels; gap = dst->pitch - dst->w; /* * Clear surface to colorkey */ memset(pc, (unsigned char) (src->format->colorkey & 0xff), dst->pitch * dst->h); /* * Iterate through destination surface */ for (y = 0; y < dst->h; y++) { dy = cy - y; sdx = (ax + (isin * dy)) + xd; sdy = (ay - (icos * dy)) + yd; for (x = 0; x < dst->w; x++) { dx = (short) (sdx >> 16); dy = (short) (sdy >> 16); if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { sp = (tColorY *) (src->pixels); sp += (src->pitch * dy + dx); *pc = *sp; } sdx += icos; sdy += isin; pc++; } pc += gap; } } /* rotozoomSurface() Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. 'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1 then the destination 32bit surface is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. */ #define VALUE_LIMIT 0.001 /* Local rotozoom-size function with trig result return */ void rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight, double *canglezoom, double *sanglezoom) { double x, y, cx, cy, sx, sy; double radangle; int dstwidthhalf, dstheighthalf; /* * Determine destination width and height by rotating a centered source box */ radangle = angle * (M_PI / 180.0); *sanglezoom = sin(radangle); *canglezoom = cos(radangle); *sanglezoom *= zoom; *canglezoom *= zoom; x = width / 2; y = height / 2; cx = *canglezoom * x; cy = *canglezoom * y; sx = *sanglezoom * x; sy = *sanglezoom * y; dstwidthhalf = MAX((int) ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1); dstheighthalf = MAX((int) ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1); *dstwidth = 2 * dstwidthhalf; *dstheight = 2 * dstheighthalf; } /* Publically available rotozoom-size function */ void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight) { double dummy_sanglezoom, dummy_canglezoom; rotozoomSurfaceSizeTrig(width, height, angle, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); } /* Publically available rotozoom function */ SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth) { SDL_Surface *rz_src; SDL_Surface *rz_dst; double zoominv; double sanglezoom, canglezoom, sanglezoominv, canglezoominv; int dstwidthhalf, dstwidth, dstheighthalf, dstheight; int is32bit; int i, src_converted; /* * Sanity check */ if (src == NULL) return (NULL); /* * Determine if source surface is 32bit or 8bit */ is32bit = (src->format->BitsPerPixel == 32); if ((is32bit) || (src->format->BitsPerPixel == 8)) { /* * Use source surface 'as is' */ rz_src = src; src_converted = 0; } else { /* * New source surface is 32bit with a defined RGBA ordering */ rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); SDL_BlitSurface(src, NULL, rz_src, NULL); src_converted = 1; is32bit = 1; } /* * Sanity check zoom factor */ if (zoom < VALUE_LIMIT) { zoom = VALUE_LIMIT; } zoominv = 65536.0 / (zoom * zoom); /* * Check if we have a rotozoom or just a zoom */ if (fabs(angle) > VALUE_LIMIT) { /* * Angle!=0: full rotozoom */ /* * ----------------------- */ /* Determine target size */ rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoom, &dstwidth, &dstheight, &canglezoom, &sanglezoom); /* * Calculate target factors from sin/cos and zoom */ sanglezoominv = sanglezoom; canglezoominv = canglezoom; sanglezoominv *= zoominv; canglezoominv *= zoominv; /* Calculate half size */ dstwidthhalf = dstwidth / 2; dstheighthalf = dstheight / 2; /* * Alloc space to completely contain the rotated surface */ rz_dst = NULL; if (is32bit) { /* * Target surface is 32bit with source RGBA/ABGR ordering */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, rz_src->format->Rmask, rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask); } else { /* * Target surface is 8bit */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); } /* * Lock source surface */ SDL_LockSurface(rz_src); /* * Check which kind of surface we have */ if (is32bit) { /* * Call the 32bit transformation routine to do the rotation (using alpha) */ transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf, (int) (sanglezoominv), (int) (canglezoominv), smooth); /* * Turn on source-alpha support */ SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); } else { /* * Copy palette and colorkey info */ for (i = 0; i < rz_src->format->palette->ncolors; i++) { rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; } rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; /* * Call the 8bit transformation routine to do the rotation */ transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf, (int) (sanglezoominv), (int) (canglezoominv)); SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); } /* * Unlock source surface */ SDL_UnlockSurface(rz_src); } else { /* * Angle=0: Just a zoom */ /* * -------------------- */ /* * Calculate target size */ zoomSurfaceSize(rz_src->w, rz_src->h, zoom, zoom, &dstwidth, &dstheight); /* * Alloc space to completely contain the zoomed surface */ rz_dst = NULL; if (is32bit) { /* * Target surface is 32bit with source RGBA/ABGR ordering */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, rz_src->format->Rmask, rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask); } else { /* * Target surface is 8bit */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); } /* * Lock source surface */ SDL_LockSurface(rz_src); /* * Check which kind of surface we have */ if (is32bit) { /* * Call the 32bit transformation routine to do the zooming (using alpha) */ zoomSurfaceRGBA(rz_src, rz_dst, smooth); /* * Turn on source-alpha support */ SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); } else { /* * Copy palette and colorkey info */ for (i = 0; i < rz_src->format->palette->ncolors; i++) { rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; } rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; /* * Call the 8bit transformation routine to do the zooming */ zoomSurfaceY(rz_src, rz_dst); SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey); } /* * Unlock source surface */ SDL_UnlockSurface(rz_src); } /* * Cleanup temp surface */ if (src_converted) { SDL_FreeSurface(rz_src); } /* * Return destination surface */ return (rz_dst); } /* Publically available rotate function */ int rotateSurface(SDL_Surface *src, SDL_Surface *dst, double angle, int smooth) { double zoominv; double sanglezoom, canglezoom, sanglezoominv, canglezoominv; int dstwidthhalf, dstwidth, dstheighthalf, dstheight; int is32bit; int i; /* Sanity check */ if (!src || !dst) return -1; if (src->format->BitsPerPixel != dst->format->BitsPerPixel) return -1; /* Determine if source surface is 32bit or 8bit */ is32bit = (src->format->BitsPerPixel == 32); zoominv = 65536.0; /* Check if we have to rotate anything */ if (fabs(angle) <= VALUE_LIMIT) { SDL_BlitSurface(src, NULL, dst, NULL); return 0; } /* Determine target size */ rotozoomSurfaceSizeTrig(src->w, src->h, angle, 1, &dstwidth, &dstheight, &canglezoom, &sanglezoom); /* * Calculate target factors from sin/cos and zoom */ sanglezoominv = sanglezoom; canglezoominv = canglezoom; sanglezoominv *= zoominv; canglezoominv *= zoominv; /* Calculate half size */ dstwidthhalf = dstwidth / 2; dstheighthalf = dstheight / 2; /* Check if the rotated surface will fit destination */ if (dst->w < dstwidth || dst->h < dstheight) return -1; /* Lock source surface */ SDL_LockSurface(src); SDL_LockSurface(dst); /* Check which kind of surface we have */ if (is32bit) { /* Call the 32bit transformation routine to do the rotation (using alpha) */ transformSurfaceRGBA(src, dst, dstwidthhalf, dstheighthalf, (int) (sanglezoominv), (int) (canglezoominv), smooth); } else { /* Copy palette info */ for (i = 0; i < src->format->palette->ncolors; i++) dst->format->palette->colors[i] = src->format->palette->colors[i]; dst->format->palette->ncolors = src->format->palette->ncolors; /* Call the 8bit transformation routine to do the rotation */ transformSurfaceY(src, dst, dstwidthhalf, dstheighthalf, (int) (sanglezoominv), (int) (canglezoominv)); } /* Unlock source surface */ SDL_UnlockSurface(dst); SDL_UnlockSurface(src); return 0; } /* zoomSurface() Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1 then the destination 32bit surface is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. */ #define VALUE_LIMIT 0.001 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight) { /* * Sanity check zoom factors */ if (zoomx < VALUE_LIMIT) { zoomx = VALUE_LIMIT; } if (zoomy < VALUE_LIMIT) { zoomy = VALUE_LIMIT; } /* * Calculate target size */ *dstwidth = (int) ((double) width * zoomx); *dstheight = (int) ((double) height * zoomy); if (*dstwidth < 1) { *dstwidth = 1; } if (*dstheight < 1) { *dstheight = 1; } } SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth) { SDL_Surface *rz_src; SDL_Surface *rz_dst; int dstwidth, dstheight; int is32bit; int i, src_converted; /* * Sanity check */ if (src == NULL) return (NULL); /* * Determine if source surface is 32bit or 8bit */ is32bit = (src->format->BitsPerPixel == 32); if ((is32bit) || (src->format->BitsPerPixel == 8)) { /* * Use source surface 'as is' */ rz_src = src; src_converted = 0; } else { /* * New source surface is 32bit with a defined RGBA ordering */ rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); SDL_BlitSurface(src, NULL, rz_src, NULL); src_converted = 1; is32bit = 1; } /* Get size if target */ zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); /* * Alloc space to completely contain the zoomed surface */ rz_dst = NULL; if (is32bit) { /* * Target surface is 32bit with source RGBA/ABGR ordering */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, rz_src->format->Rmask, rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask); } else { /* * Target surface is 8bit */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0); } /* * Lock source surface */ SDL_LockSurface(rz_src); /* * Check which kind of surface we have */ if (is32bit) { /* * Call the 32bit transformation routine to do the zooming (using alpha) */ zoomSurfaceRGBA(rz_src, rz_dst, smooth); /* * Turn on source-alpha support */ SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255); } else { /* * Copy palette and colorkey info */ for (i = 0; i < rz_src->format->palette->ncolors; i++) { rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; } rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; /* * Call the 8bit transformation routine to do the zooming */ zoomSurfaceY(rz_src, rz_dst); SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY, rz_src->format->colorkey); } /* * Unlock source surface */ SDL_UnlockSurface(rz_src); /* * Cleanup temp surface */ if (src_converted) { SDL_FreeSurface(rz_src); } /* * Return destination surface */ return (rz_dst); } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/nearest2x.c0000644000175000017500000001163310552135701021214 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Core algorithm of the BiLinear screen scaler // Template // When this file is built standalone is produces a plain C version // Also #included by 2xscalers_mmx.c for an MMX version #ifdef GFXMODULE_SDL #include "libs/graphics/sdl/sdl_common.h" #include "types.h" #include "scalers.h" #include "scaleint.h" #include "2xscalers.h" // Nearest Neighbor scaling to 2x // The name expands to // Scale_Nearest (for plain C) // Scale_MMX_Nearest (for MMX) // Scale_SSE_Nearest (for SSE) // [others when platforms are added] void SCALE_(Nearest) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) { int y; const int rw = r->w, rh = r->h; const int sp = src->pitch, dp = dst->pitch; const int bpp = dst->format->BytesPerPixel; const int slen = sp / bpp, dlen = dp / bpp; const int dsrc = slen-rw, ddst = (dlen-rw) * 2; Uint32 *src_p = (Uint32 *)src->pixels; Uint32 *dst_p = (Uint32 *)dst->pixels; // guard asm code against such atrocities if (rw == 0 || rh == 0) return; SCALE_(PlatInit) (); // move ptrs to the first updated pixel src_p += slen * r->y + r->x; dst_p += (dlen * r->y + r->x) * 2; #if defined(MMX_ASM) && defined(MSVC_ASM) // Just about everything has to be done in asm for MSVC // to actually take advantage of asm here // MSVC does not support beautiful GCC-like asm templates y = rh; __asm { // setup vars mov esi, src_p mov edi, dst_p PREFETCH (esi + 0x40) PREFETCH (esi + 0x80) PREFETCH (esi + 0xc0) mov edx, dlen lea edx, [edx * 4] mov eax, dsrc lea eax, [eax * 4] mov ebx, ddst lea ebx, [ebx * 4] mov ecx, rw loop_y: test ecx, 1 jz even_x // one-pixel transfer movd mm1, [esi] punpckldq mm1, mm1 // pix1 | pix1 -> mm1 add esi, 4 MOVNTQ (edi, mm1) add edi, 8 MOVNTQ (edi - 8 + edx, mm1) even_x: shr ecx, 1 // x = rw / 2 jz end_x // rw was 1 loop_x: // two-pixel transfer movq mm1, [esi] movq mm2, mm1 PREFETCH (esi + 0x100) punpckldq mm1, mm1 // pix1 | pix1 -> mm1 add esi, 8 MOVNTQ (edi, mm1) punpckhdq mm2, mm2 // pix2 | pix2 -> mm2 MOVNTQ (edi + edx, mm1) add edi, 16 MOVNTQ (edi - 8, mm2) MOVNTQ (edi - 8 + edx, mm2) dec ecx jnz loop_x end_x: // try to prefetch as early as possible to have it on time PREFETCH (esi + eax) mov ecx, rw add esi, eax PREFETCH (esi + 0x40) PREFETCH (esi + 0x80) PREFETCH (esi + 0xc0) add edi, ebx dec y jnz loop_y } #elif defined(MMX_ASM) && defined(GCC_ASM) SCALE_(Prefetch) (src_p + 16); SCALE_(Prefetch) (src_p + 32); SCALE_(Prefetch) (src_p + 48); for (y = rh; y; --y) { int x = rw; if (x & 1) { // one-pixel transfer __asm__ ( "movd (%0), %%mm1 \n\t" "punpckldq %%mm1, %%mm1 \n\t" MOVNTQ (%%mm1, (%1)) "\n\t" MOVNTQ (%%mm1, (%1,%2)) "\n\t" : /* nothing */ : /*0*/"r" (src_p), /*1*/"r" (dst_p), /*2*/"r" (dlen*sizeof(Uint32)) ); ++src_p; dst_p += 2; --x; } for (x >>= 1; x; --x, src_p += 2, dst_p += 4) { // two-pixel transfer __asm__ ( "movq (%0), %%mm1 \n\t" "movq %%mm1, %%mm2 \n\t" PREFETCH (0x100(%0)) "\n\t" "punpckldq %%mm1, %%mm1 \n\t" MOVNTQ (%%mm1, (%1)) "\n\t" MOVNTQ (%%mm1, (%1,%2)) "\n\t" "punpckhdq %%mm2, %%mm2 \n\t" MOVNTQ (%%mm2, 8(%1)) "\n\t" MOVNTQ (%%mm2, 8(%1,%2)) "\n\t" : /* nothing */ : /*0*/"r" (src_p), /*1*/"r" (dst_p), /*2*/"r" (dlen*sizeof(Uint32)) ); } src_p += dsrc; // try to prefetch as early as possible to have it on time SCALE_(Prefetch) (src_p); dst_p += ddst; SCALE_(Prefetch) (src_p + 16); SCALE_(Prefetch) (src_p + 32); SCALE_(Prefetch) (src_p + 48); } #else // Plain C version for (y = 0; y < rh; ++y) { int x; for (x = 0; x < rw; ++x, ++src_p, dst_p += 2) { Uint32 pix = *src_p; dst_p[0] = pix; dst_p[1] = pix; dst_p[dlen] = pix; dst_p[dlen + 1] = pix; } dst_p += ddst; src_p += dsrc; } #endif SCALE_(PlatDone) (); } #endif /* GFXMODULE_SDL */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/bbox.c0000600000175000017500000000612510543202052020215 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "port.h" #include SDL_INCLUDE(SDL.h) #include "bbox.h" TFB_BoundingBox TFB_BBox; void TFB_BBox_Reset (void) { TFB_BBox.valid = 0; TFB_BBox.clip.corner.x = 0; TFB_BBox.clip.corner.y = 0; TFB_BBox.clip.extent.width = ScreenWidth; TFB_BBox.clip.extent.height = ScreenHeight; } void TFB_BBox_GetClipRect (TFB_Canvas c) { SDL_Rect r; SDL_GetClipRect ((SDL_Surface *)c, &r); TFB_BBox.clip.corner.x = r.x; TFB_BBox.clip.corner.y = r.y; TFB_BBox.clip.extent.width = r.w; TFB_BBox.clip.extent.height = r.h; } void TFB_BBox_RegisterPoint (int x, int y) { int x1 = TFB_BBox.clip.corner.x; int y1 = TFB_BBox.clip.corner.y; int x2 = TFB_BBox.clip.corner.x + TFB_BBox.clip.extent.width - 1; int y2 = TFB_BBox.clip.corner.y + TFB_BBox.clip.extent.height - 1; /* Make sure the cliprect is sane */ if (x1 < 0) x1 = TFB_BBox.clip.corner.x = 0; if (y1 < 0) y1 = TFB_BBox.clip.corner.y = 0; if (x2 >= ScreenWidth) { TFB_BBox.clip.extent.width = ScreenWidth - x1; x2 = ScreenWidth - 1; } if (y2 >= ScreenHeight) { TFB_BBox.clip.extent.height = ScreenHeight - y1; y2 = ScreenHeight - 1; } /* Constrain coordinates */ if (x < x1) x = x1; if (x >= x2) x = x2; if (y < y1) y = y1; if (y >= y2) y = y2; /* Is this the first point? If so, set a pixel-region and return. */ if (!TFB_BBox.valid) { TFB_BBox.valid = 1; TFB_BBox.region.corner.x = x; TFB_BBox.region.corner.y = y; TFB_BBox.region.extent.width = 1; TFB_BBox.region.extent.height = 1; return; } /* Otherwise expand the rectangle if necessary. */ x1 = TFB_BBox.region.corner.x; y1 = TFB_BBox.region.corner.y; x2 = TFB_BBox.region.corner.x + TFB_BBox.region.extent.width - 1; y2 = TFB_BBox.region.corner.y + TFB_BBox.region.extent.height - 1; if (x < x1) { TFB_BBox.region.corner.x = x; TFB_BBox.region.extent.width += x1 - x; } if (y < y1) { TFB_BBox.region.corner.y = y; TFB_BBox.region.extent.height += y1 - y; } if (x > x2) { TFB_BBox.region.extent.width += x - x2; } if (y > y2) { TFB_BBox.region.extent.height += y - y2; } } void TFB_BBox_RegisterRect (PRECT r) { TFB_BBox_RegisterPoint (r->corner.x, r->corner.y); TFB_BBox_RegisterPoint (r->corner.x + r->extent.width, r->corner.y + r->extent.height); } void TFB_BBox_RegisterCanvas (TFB_Canvas c, int x, int y) { SDL_Surface *s = (SDL_Surface *)c; TFB_BBox_RegisterPoint (x, y); TFB_BBox_RegisterPoint (x + s->w, y + s->h); } uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/canvas.c0000600000175000017500000010114510543202052020534 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "port.h" #include SDL_INCLUDE(SDL.h) #include "sdl_common.h" #include "libs/graphics/gfx_common.h" #include "libs/graphics/sdl/primitives.h" #include "libs/graphics/tfb_draw.h" #include "libs/log.h" #include "rotozoom.h" #include "options.h" #include "types.h" typedef SDL_Surface *NativeCanvas; // BYTE x BYTE weight (mult >> 8) table static Uint8 btable[256][256]; void TFB_DrawCanvas_Initialize (void) { int i, j; for (i = 0; i < 256; ++i) for (j = 0; j < 256; ++j) btable[j][i] = (j * i + 0x80) >> 8; // need error correction here } void TFB_DrawCanvas_Line (int x1, int y1, int x2, int y2, int r, int g, int b, TFB_Canvas target) { Uint32 color; PutPixelFn screen_plot; screen_plot = putpixel_for (target); color = SDL_MapRGB (((NativeCanvas) target)->format, r, g, b); SDL_LockSurface ((NativeCanvas) target); line (x1, y1, x2, y2, color, screen_plot, (NativeCanvas) target); SDL_UnlockSurface ((NativeCanvas) target); } void TFB_DrawCanvas_Rect (PRECT rect, int r, int g, int b, TFB_Canvas target) { SDL_Surface *dst = target; SDL_PixelFormat *fmt = dst->format; Uint32 color; SDL_Rect sr; sr.x = rect->corner.x; sr.y = rect->corner.y; sr.w = rect->extent.width; sr.h = rect->extent.height; color = SDL_MapRGB (fmt, r, g, b); if (fmt->Amask && (dst->flags & SDL_SRCCOLORKEY)) { // special case -- alpha surface with colorkey // colorkey rects are transparent if ((color & ~fmt->Amask) == (fmt->colorkey & ~fmt->Amask)) color &= ~fmt->Amask; // make transparent } SDL_FillRect (dst, &sr, color); } void TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale, TFB_ColorMap *cmap, TFB_Canvas target) { SDL_Rect srcRect, targetRect, *pSrcRect; SDL_Surface *surf; TFB_Palette* palette; if (img == 0) { log_add (log_Warning, "ERROR: TFB_DrawCanvas_Image passed null image ptr"); return; } LockMutex (img->mutex); if (cmap) palette = cmap->colors; else palette = img->Palette; // only set the new palette if it changed if (((SDL_Surface *)img->NormalImg)->format->palette && cmap && img->colormap_version != cmap->version) SDL_SetColors (img->NormalImg, (SDL_Color*)palette, 0, 256); if (scale != 0 && scale != GSCALE_IDENTITY) { int type; if (optMeleeScale == TFB_SCALE_TRILINEAR && img->MipmapImg) { type = TFB_SCALE_TRILINEAR; // only set the new palette if it changed if (((SDL_Surface *)img->MipmapImg)->format->palette && cmap && img->colormap_version != cmap->version) SDL_SetColors (img->MipmapImg, (SDL_Color*)palette, 0, 256); } else { type = TFB_SCALE_NEAREST; } TFB_DrawImage_FixScaling (img, scale, type); surf = img->ScaledImg; if (surf->format->palette) SDL_SetColors (surf, (SDL_Color*)palette, 0, 256); srcRect.x = 0; srcRect.y = 0; srcRect.w = img->extent.width; srcRect.h = img->extent.height; pSrcRect = &srcRect; targetRect.x = x - img->last_scale_hs.x; targetRect.y = y - img->last_scale_hs.y; } else { surf = img->NormalImg; pSrcRect = NULL; targetRect.x = x - img->NormalHs.x; targetRect.y = y - img->NormalHs.y; } if (cmap) { img->colormap_version = cmap->version; TFB_ReturnColorMap (cmap); } SDL_BlitSurface (surf, pSrcRect, (NativeCanvas) target, &targetRect); UnlockMutex (img->mutex); } void TFB_DrawCanvas_Fill (TFB_Canvas source, int width, int height, Uint32 fillcolor, TFB_Canvas target) { SDL_Surface *src = (SDL_Surface *)source; SDL_Surface *dst = (SDL_Surface *)target; const SDL_PixelFormat *srcfmt = src->format; SDL_PixelFormat *dstfmt = dst->format; const int bpp = dstfmt->BytesPerPixel; const int sp = src->pitch, dp = dst->pitch; const int slen = sp / bpp, dlen = dp / bpp; const int dsrc = slen - width, ddst = dlen - width; Uint32 *src_p; Uint32 *dst_p; int x, y; Uint32 dstkey = 0; // 0 means alpha=0 too if (srcfmt->BytesPerPixel != 4 || dstfmt->BytesPerPixel != 4) { log_add (log_Warning, "TFB_DrawCanvas_Fill: Unsupported surface " "formats: %d bytes/pixel source, %d bytes/pixel destination", (int)srcfmt->BytesPerPixel, (int)dstfmt->BytesPerPixel); return; } SDL_LockSurface(src); SDL_LockSurface(dst); src_p = (Uint32 *)src->pixels; dst_p = (Uint32 *)dst->pixels; if (dstkey == fillcolor) { // color collision, must switch colorkey // new colorkey is grey (1/2,1/2,1/2) dstkey = SDL_MapRGBA (dstfmt, 127, 127, 127, 0); } if (srcfmt->Amask) { // alpha-based fill Uint32 amask = srcfmt->Amask; for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x, ++src_p, ++dst_p) { Uint32 p = *src_p & amask; *dst_p = (p == 0) ? dstkey : (p | fillcolor); } dst_p += ddst; src_p += dsrc; } } else if (src->flags & SDL_SRCCOLORKEY) { // colorkey-based fill Uint32 srckey = srcfmt->colorkey; Uint32 notmask = ~srcfmt->Amask; for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x, ++src_p, ++dst_p) { Uint32 p = *src_p & notmask; *dst_p = (p == srckey) ? dstkey : fillcolor; } dst_p += ddst; src_p += dsrc; } } else { log_add (log_Warning, "TFB_DrawCanvas_Fill: Unsupported source" "surface format\n"); } SDL_UnlockSurface(dst); SDL_UnlockSurface(src); // save the colorkey (dynamic image -- not using RLE coding here) SDL_SetColorKey (dst, SDL_SRCCOLORKEY, dstkey); // if the filled surface is RGBA, colorkey will only be used // when SDL_SRCALPHA flag is cleared. this allows us to blit // the surface in different ways to diff targets } void TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int g, int b, TFB_Canvas target) { SDL_Rect srcRect, targetRect, *pSrcRect; SDL_Surface *surf; int i; SDL_Color pal[256]; EXTENT prevextent = img->extent; if (img == 0) { log_add (log_Warning, "ERROR: TFB_DrawCanvas_FilledImage passed null image ptr"); return; } LockMutex (img->mutex); if (scale != 0 && scale != GSCALE_IDENTITY) { TFB_DrawImage_FixScaling (img, scale, TFB_SCALE_NEAREST); surf = img->ScaledImg; srcRect.x = 0; srcRect.y = 0; srcRect.w = img->extent.width; srcRect.h = img->extent.height; pSrcRect = &srcRect; targetRect.x = x - img->last_scale_hs.x; targetRect.y = y - img->last_scale_hs.y; } else { surf = img->NormalImg; pSrcRect = NULL; targetRect.x = x - img->NormalHs.x; targetRect.y = y - img->NormalHs.y; } if (surf->format->palette) { // set palette for fill-stamp for (i = 0; i < 256; i++) { pal[i].r = r; pal[i].g = g; pal[i].b = b; } SDL_SetColors (surf, pal, 0, 256); // reflect the change in *actual* image palette img->colormap_version--; } else { // fill the non-transparent parts of the image with fillcolor SDL_Surface *src = img->NormalImg; SDL_Surface *newfill = img->FilledImg; BOOLEAN force = FALSE; // prepare the filled image if (!newfill) { newfill = SDL_CreateRGBSurface (SDL_SWSURFACE, src->w, src->h, surf->format->BitsPerPixel, surf->format->Rmask, surf->format->Gmask, surf->format->Bmask, surf->format->Amask); force = TRUE; } if (force || prevextent.height != img->extent.height || prevextent.width != img->extent.width || img->last_fill.r != r || img->last_fill.g != g || img->last_fill.b != b) { // image or fillcolor changed - regenerate TFB_DrawCanvas_Fill (surf, img->extent.width, img->extent.height, SDL_MapRGBA (newfill->format, r, g, b, 0), newfill); // important to keep alpha=0 in fillcolor // -- we process alpha ourselves } // cache filled image if possible img->last_fill.r = r; img->last_fill.g = g; img->last_fill.b = b; img->FilledImg = newfill; surf = newfill; } SDL_BlitSurface (surf, pSrcRect, (NativeCanvas) target, &targetRect); UnlockMutex (img->mutex); } void TFB_DrawCanvas_FontChar (TFB_Char *fontChar, TFB_Image *backing, int x, int y, TFB_Canvas target) { SDL_Rect srcRect, targetRect; SDL_Surface *surf; int w, h; if (fontChar == 0) { log_add (log_Warning, "ERROR: " "TFB_DrawCanvas_FontChar passed null char ptr"); return; } if (backing == 0) { log_add (log_Warning, "ERROR: " "TFB_DrawCanvas_FontChar passed null backing ptr"); return; } w = fontChar->extent.width; h = fontChar->extent.height; LockMutex (backing->mutex); surf = backing->NormalImg; if (surf->format->BytesPerPixel != 4 || surf->w < w || surf->h < h) { log_add (log_Warning, "ERROR: " "TFB_DrawCanvas_FontChar bad backing surface: %dx%dx%d; " "char: %dx%d", surf->w, surf->h, (int)surf->format->BytesPerPixel, w, h); UnlockMutex (backing->mutex); return; } srcRect.x = 0; srcRect.y = 0; srcRect.w = fontChar->extent.width; srcRect.h = fontChar->extent.height; targetRect.x = x - fontChar->HotSpot.x; targetRect.y = y - fontChar->HotSpot.y; // transfer the alpha channel to the backing surface SDL_LockSurface (surf); { int x, y; const int sskip = fontChar->pitch - w; const int dskip = (surf->pitch / 4) - w; const Uint32 dmask = ~surf->format->Amask; const int ashift = surf->format->Ashift; Uint8 *src_p = fontChar->data; Uint32 *dst_p = (Uint32 *)surf->pixels; for (y = 0; y < h; ++y, src_p += sskip, dst_p += dskip) { for (x = 0; x < w; ++x, ++src_p, ++dst_p) { *dst_p = (*dst_p & dmask) | (((Uint32)*src_p) << ashift); } } } SDL_UnlockSurface (surf); SDL_BlitSurface (surf, &srcRect, (NativeCanvas) target, &targetRect); UnlockMutex (backing->mutex); } TFB_Canvas TFB_DrawCanvas_New_TrueColor (int w, int h, BOOLEAN hasalpha) { SDL_Surface *new_surf; SDL_PixelFormat* fmt = format_conv_surf->format; new_surf = SDL_CreateRGBSurface (SDL_SWSURFACE, w, h, fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, hasalpha ? fmt->Amask : 0); if (!new_surf) { log_add (log_Fatal, "INTERNAL PANIC: Failed to create TFB_Canvas: %s", SDL_GetError()); exit (EXIT_FAILURE); } return new_surf; } TFB_Canvas TFB_DrawCanvas_New_ForScreen (int w, int h, BOOLEAN withalpha) { SDL_Surface *new_surf; SDL_PixelFormat* fmt = SDL_Screen->format; if (fmt->palette) { log_add (log_Warning, "TFB_DrawCanvas_New_ForScreen() WARNING:" "Paletted display format will be slow"); new_surf = TFB_DrawCanvas_New_TrueColor (w, h, withalpha); } else { if (withalpha && fmt->Amask == 0) fmt = format_conv_surf->format; // Screen has no alpha and we need it new_surf = SDL_CreateRGBSurface (SDL_SWSURFACE, w, h, fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, withalpha ? fmt->Amask : 0); } if (!new_surf) { log_add (log_Fatal, "TFB_DrawCanvas_New_ForScreen() INTERNAL PANIC:" "Failed to create TFB_Canvas: %s", SDL_GetError()); exit (EXIT_FAILURE); } return new_surf; } TFB_Canvas TFB_DrawCanvas_New_Paletted (int w, int h, TFB_Palette *palette, int transparent_index) { SDL_Surface *new_surf; new_surf = SDL_CreateRGBSurface (SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0); if (!new_surf) { log_add (log_Fatal, "INTERNAL PANIC: Failed to create TFB_Canvas: %s", SDL_GetError()); exit (EXIT_FAILURE); } if (palette != NULL) { SDL_SetColors(new_surf, (SDL_Color *)palette, 0, 256); } if (transparent_index >= 0) { SDL_SetColorKey (new_surf, SDL_SRCCOLORKEY, transparent_index); } else { SDL_SetColorKey (new_surf, 0, 0); } return new_surf; } TFB_Canvas TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas, TFB_Canvas oldcanvas, int type, int last_type) { SDL_Surface *src = (SDL_Surface *)canvas; SDL_Surface *old = (SDL_Surface *)oldcanvas; SDL_Surface *newsurf = old; if (type == TFB_SCALE_NEAREST) { if (old && type != last_type) { TFB_DrawCanvas_Delete (old); old = NULL; } if (!old) { newsurf = SDL_CreateRGBSurface (SDL_SWSURFACE, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); if (src->format->palette) TFB_DrawCanvas_SetTransparentIndex (newsurf, TFB_DrawCanvas_GetTransparentIndex (src), FALSE); else { int r, g, b; if (TFB_DrawCanvas_GetTransparentColor (src, &r, &g, &b)) TFB_DrawCanvas_SetTransparentColor (newsurf, r, g, b, FALSE); } } } else { if (old && type != last_type) { TFB_DrawCanvas_Delete (old); old = NULL; } if (!old) { if (SDL_Screen->format->BitsPerPixel == 32) newsurf = TFB_DrawCanvas_New_ForScreen (src->w, src->h, TRUE); else newsurf = TFB_DrawCanvas_New_TrueColor (src->w, src->h, TRUE); } } return newsurf; } TFB_Canvas TFB_DrawCanvas_New_RotationTarget (TFB_Canvas src_canvas, int angle) { SDL_Surface *src = (SDL_Surface *)src_canvas; SDL_Surface *newsurf; EXTENT size; TFB_DrawCanvas_GetRotatedExtent (src_canvas, angle, &size); newsurf = SDL_CreateRGBSurface (SDL_SWSURFACE, size.width, size.height, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); if (!newsurf) { log_add (log_Fatal, "TFB_DrawCanvas_New_RotationTarget()" " INTERNAL PANIC: Failed to create TFB_Canvas: %s", SDL_GetError()); exit (EXIT_FAILURE); } if (src->format->palette) TFB_DrawCanvas_SetTransparentIndex (newsurf, TFB_DrawCanvas_GetTransparentIndex (src), FALSE); else { int r, g, b; if (TFB_DrawCanvas_GetTransparentColor (src, &r, &g, &b)) TFB_DrawCanvas_SetTransparentColor (newsurf, r, g, b, FALSE); } return newsurf; } void TFB_DrawCanvas_Delete (TFB_Canvas canvas) { if (!canvas) { log_add (log_Warning, "INTERNAL PANIC: Attempted" " to delete a NULL canvas!"); /* Should we actually die here? */ } else { SDL_FreeSurface ((SDL_Surface *) canvas); } } TFB_Palette * TFB_DrawCanvas_ExtractPalette (TFB_Canvas canvas) { int i; TFB_Palette *result; SDL_Surface *surf = (SDL_Surface *)canvas; if (!surf->format->palette) { return NULL; } result = (TFB_Palette*) HMalloc (sizeof (TFB_Palette) * 256); for (i = 0; i < 256; ++i) { result[i].r = surf->format->palette->colors[i].r; result[i].g = surf->format->palette->colors[i].g; result[i].b = surf->format->palette->colors[i].b; } return result; } TFB_Canvas TFB_DrawCanvas_ToScreenFormat (TFB_Canvas canvas) { SDL_Surface *result = TFB_DisplayFormatAlpha ((SDL_Surface *)canvas); if (result == NULL) { log_add (log_Debug, "WARNING: Could not convert" " sprite-canvas to display format."); return canvas; } else if (result == canvas) { // no conversion was necessary return canvas; } else { // converted TFB_DrawCanvas_Delete (canvas); return result; } return canvas; } BOOLEAN TFB_DrawCanvas_IsPaletted (TFB_Canvas canvas) { return ((SDL_Surface *)canvas)->format->palette != NULL; } void TFB_DrawCanvas_SetPalette (TFB_Canvas target, TFB_Palette *palette) { SDL_SetColors ((SDL_Surface *)target, (SDL_Color *)palette, 0, 256); } int TFB_DrawCanvas_GetTransparentIndex (TFB_Canvas canvas) { if (((SDL_Surface *)canvas)->flags & SDL_SRCCOLORKEY) return ((SDL_Surface *)canvas)->format->colorkey; return -1; } void TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int index, BOOLEAN rleaccel) { if (index >= 0) { int flags = SDL_SRCCOLORKEY; if (rleaccel) flags |= SDL_RLEACCEL; SDL_SetColorKey ((SDL_Surface *)canvas, flags, index); if (!TFB_DrawCanvas_IsPaletted (canvas)) { // disables alpha channel so color key transparency actually works SDL_SetAlpha ((SDL_Surface *)canvas, 0, 255); } } else { SDL_SetColorKey ((SDL_Surface *)canvas, 0, 0); } } BOOLEAN TFB_DrawCanvas_GetTransparentColor (TFB_Canvas canvas, int *r, int *g, int *b) { if (!TFB_DrawCanvas_IsPaletted (canvas) && (((SDL_Surface *)canvas)->flags & SDL_SRCCOLORKEY) ) { Uint8 ur, ug, ub; int colorkey = ((SDL_Surface *)canvas)->format->colorkey; SDL_GetRGB (colorkey, ((SDL_Surface *)canvas)->format, &ur, &ug, &ub); *r = ur; *g = ug; *b = ub; return TRUE; } return FALSE; } void TFB_DrawCanvas_SetTransparentColor (TFB_Canvas canvas, int r, int g, int b, BOOLEAN rleaccel) { Uint32 color; int flags = SDL_SRCCOLORKEY; if (rleaccel) flags |= SDL_RLEACCEL; color = SDL_MapRGBA (((SDL_Surface *)canvas)->format, r, g, b, 0); SDL_SetColorKey ((SDL_Surface *)canvas, flags, color); if (!TFB_DrawCanvas_IsPaletted (canvas)) { // disables alpha channel so color key transparency actually works SDL_SetAlpha ((SDL_Surface *)canvas, 0, 255); } } void TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, HOT_SPOT src_hs, TFB_Canvas src_mipmap, HOT_SPOT mm_hs, int scale, PEXTENT size, HOT_SPOT *hs) { SDL_Surface *src = (SDL_Surface *)src_canvas; if (!src_mipmap) { size->width = src->w * scale / GSCALE_IDENTITY; size->height = src->h * scale / GSCALE_IDENTITY; hs->x = src_hs.x * scale / GSCALE_IDENTITY; hs->y = src_hs.y * scale / GSCALE_IDENTITY; } else { // interpolates extents between src and mipmap to get smoother // transition when surface changes SDL_Surface *mipmap = (SDL_Surface *)src_mipmap; float ratio = (scale / (float)GSCALE_IDENTITY) * 2.0f - 1.0f; if (ratio < 0.0f) ratio = 0.0f; else if (ratio > 1.0f) ratio = 1.0f; size->width = (int)((src->w - mipmap->w) * ratio + mipmap->w + 0.5); size->height = (int)((src->h - mipmap->h) * ratio + mipmap->h + 0.5); hs->x = (int)((src_hs.x - mm_hs.x) * ratio + mm_hs.x + 0.5); hs->y = (int)((src_hs.y - mm_hs.y) * ratio + mm_hs.y + 0.5); } if (!size->width && src->w) size->width = 1; if (!size->height && src->h) size->height = 1; } void TFB_DrawCanvas_GetExtent (TFB_Canvas canvas, PEXTENT size) { SDL_Surface *src = (SDL_Surface *)canvas; size->width = src->w; size->height = src->h; } void TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, EXTENT size) { #define NNS_MAX_DIMS 600 SDL_Surface *src = (SDL_Surface *)src_canvas; SDL_Surface *dst = (SDL_Surface *)dest_canvas; int x, y, sx, sy, *csax, *csay, csx, csy; int saspace[NNS_MAX_DIMS]; int *sax, *say; if (size.width + size.height > NNS_MAX_DIMS) { log_add (log_Warning, "TFB_DrawCanvas_Scale: Tried to zoom" " an image to unreasonable size! Failing."); return; } if (size.width > dst->w || size.height > dst->h) { log_add (log_Warning, "TFB_DrawCanvas_Scale: Tried to scale" " image to size %d %d when dest_canvas has only" " dimensions of %d %d! Failing.", size.width, size.height, dst->w, dst->h); return; } sx = sy = 0; if (size.width > 1) sx = ((src->w - 1) << 16) / (size.width - 1); if (size.height > 1) sy = ((src->h - 1) << 16) / (size.height - 1); sax = saspace; say = saspace + size.width; /* * Precalculate row increments * We start with a value in 0..0.5 range to shift the bigger * jumps towards the center of the image */ csax = sax; for (x = 0, csx = 0x6000; x < size.width; x++) { *csax = csx >> 16; csax++; csx &= 0xffff; csx += sx; } csay = say; for (y = 0, csy = 0x6000; y < size.height; y++) { *csay = csy >> 16; csay++; csy &= 0xffff; csy += sy; } SDL_LockSurface (src); SDL_LockSurface (dst); if (src->format->BytesPerPixel == 1 && dst->format->BytesPerPixel == 1) { Uint8 *sp, *csp, *dp, *cdp; sp = csp = (Uint8 *) src->pixels; dp = cdp = (Uint8 *) dst->pixels; csay = say; for (y = 0; y < size.height; ++y) { csp += (*csay) * src->pitch; sp = csp; dp = cdp; csax = sax; for (x = 0; x < size.width; ++x) { sp += *csax; *dp = *sp; ++csax; ++dp; } ++csay; cdp += dst->pitch; } } else if (src->format->BytesPerPixel == 4 && dst->format->BytesPerPixel == 4) { Uint32 *sp, *csp, *dp, *cdp; int sgap, dgap; sgap = src->pitch >> 2; dgap = dst->pitch >> 2; sp = csp = (Uint32 *) src->pixels; dp = cdp = (Uint32 *) dst->pixels; csay = say; for (y = 0; y < size.height; ++y) { csp += (*csay) * sgap; sp = csp; dp = cdp; csax = sax; for (x = 0; x < size.width; ++x) { sp += *csax; *dp = *sp; ++csax; ++dp; } ++csay; cdp += dgap; } } else { log_add (log_Warning, "Tried to deal with unknown BPP: %d -> %d", src->format->BitsPerPixel, dst->format->BitsPerPixel); } SDL_UnlockSurface (dst); SDL_UnlockSurface (src); } typedef union { Uint32 value; Uint8 chan[4]; struct { Uint8 r, g, b, a; } c; } pixel_t; static inline Uint8 dot_product_8_4 (pixel_t* p, int c, Uint8* v) { // math expanded for speed #if 0 return ( (Uint32)p[0].chan[c] * v[0] + (Uint32)p[1].chan[c] * v[1] + (Uint32)p[2].chan[c] * v[2] + (Uint32)p[3].chan[c] * v[3] ) >> 8; #else // mult-table driven version return btable[p[0].chan[c]][v[0]] + btable[p[1].chan[c]][v[1]] + btable[p[2].chan[c]][v[2]] + btable[p[3].chan[c]][v[3]]; #endif } static inline Uint8 weight_product_8_4 (pixel_t* p, int c, Uint8* w) { // math expanded for speed return ( (Uint32)p[0].chan[c] * w[0] + (Uint32)p[1].chan[c] * w[1] + (Uint32)p[2].chan[c] * w[2] + (Uint32)p[3].chan[c] * w[3] ) / (w[0] + w[1] + w[2] + w[3]); } static inline Uint8 blend_ratio_2 (Uint8 c1, Uint8 c2, int ratio) { // blend 2 color values according to ratio (0..256) // identical to proper alpha blending return (((c1 - c2) * ratio) >> 8) + c2; } static inline Uint32 tri_get_pixel (void* ppix, SDL_PixelFormat *fmt, SDL_Color *pal, Uint32 mask, Uint32 key) { pixel_t p; // start off with non-present pixel p.value = 0; if (pal) { // paletted pixel; mask not used Uint32 c = *(Uint8 *)ppix; if (c != key) { p.c.r = pal[c].r; p.c.g = pal[c].g; p.c.b = pal[c].b; p.c.a = SDL_ALPHA_OPAQUE; } } else { // RGB(A) pixel; (pix & mask) != key Uint32 c = *(Uint32 *)ppix; if ((c & mask) != key) { #if 0 SDL_GetRGBA (c, fmt, &p.c.r, &p.c.g, &p.c.b, &p.c.a); #else p.c.r = (c >> fmt->Rshift) & 0xff; p.c.g = (c >> fmt->Gshift) & 0xff; p.c.b = (c >> fmt->Bshift) & 0xff; if (fmt->Amask) p.c.a = (c >> fmt->Ashift) & 0xff; else p.c.a = SDL_ALPHA_OPAQUE; } #endif } return p.value; } void TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, TFB_Canvas src_mipmap, EXTENT size) { SDL_Surface *src = (SDL_Surface *)src_canvas; SDL_Surface *dst = (SDL_Surface *)dest_canvas; SDL_Surface *mipmap = (SDL_Surface *)src_mipmap; SDL_PixelFormat *srcfmt = src->format; SDL_PixelFormat *mmfmt = mipmap->format; SDL_PixelFormat *dstfmt = dst->format; SDL_Color *srcpal = srcfmt->palette? srcfmt->palette->colors : 0; SDL_Color *mmpal = mmfmt->palette ? mmfmt->palette->colors : 0; const int sbpp = srcfmt->BytesPerPixel; const int mmbpp = mmfmt->BytesPerPixel; const int slen = src->pitch; const int mmlen = mipmap->pitch; const int dst_has_alpha = (dstfmt->Amask != 0); const int transparent = (dst->flags & SDL_SRCCOLORKEY) ? dstfmt->colorkey : 0; const int w = size.width, h = size.height; const int alpha_threshold = dst_has_alpha ? 0 : 127; // src v. mipmap importance factor int ratio; // source masks and keys Uint32 mk0 = 0, ck0 = ~0, mk1 = 0, ck1 = ~0; // source fractional x and y positions int sx0, sy0, sx1, sy1; // source fractional dx and dy increments int fsx0 = 0, fsy0 = 0, fsx1 = 0, fsy1 = 0; // source fractional x and y starting points int ssx0 = 0, ssy0 = 0, ssx1 = 0, ssy1 = 0; int x, y; fsx0 = (src->w << 16) / w; fsy0 = (src->h << 16) / h; if (w > 1) fsx1 = ((mipmap->w - 1) << 16) / (w - 1); if (h > 1) fsy1 = ((mipmap->h - 1) << 16) / (h - 1); // give equal importance to both edges ssx0 = (((src->w - 1) << 16) - fsx0 * (w - 1)) >> 1; ssy0 = (((src->h - 1) << 16) - fsy0 * (h - 1)) >> 1; ssx1 = (((mipmap->w - 1) << 16) - fsx1 * (w - 1)) >> 1; ssy1 = (((mipmap->h - 1) << 16) - fsy1 * (h - 1)) >> 1; // src v. mipmap importance factor ratio = (w << 9) / src->w - 256; if (ratio < 0) ratio = 0; if (ratio > 256) ratio = 256; if (size.width > dst->w || size.height > dst->h) { log_add (log_Warning, "TFB_DrawCanvas_Rescale_Trilinear: " "Tried to scale image to size %d %d when dest_canvas" " has only dimensions of %d %d! Failing.", size.width, size.height, dst->w, dst->h); return; } if ((srcfmt->BytesPerPixel != 1 && srcfmt->BytesPerPixel != 4) || (mmfmt->BytesPerPixel != 1 && mmfmt->BytesPerPixel != 4) || (dst->format->BytesPerPixel != 4)) { log_add (log_Warning, "TFB_DrawCanvas_Rescale_Trilinear: " "Tried to deal with unknown BPP: %d -> %d, mipmap %d", srcfmt->BitsPerPixel, dst->format->BitsPerPixel, mmfmt->BitsPerPixel); return; } // use colorkeys where appropriate if (srcfmt->Amask) { // alpha transparency mk0 = srcfmt->Amask; ck0 = 0; } else if (src->flags & SDL_SRCCOLORKEY) { // colorkey transparency mk0 = ~srcfmt->Amask; ck0 = srcfmt->colorkey & mk0; } if (mmfmt->Amask) { // alpha transparency mk1 = mmfmt->Amask; ck1 = 0; } else if (mipmap->flags & SDL_SRCCOLORKEY) { // colorkey transparency mk1 = ~mmfmt->Amask; ck1 = mmfmt->colorkey & mk1; } SDL_LockSurface(src); SDL_LockSurface(dst); SDL_LockSurface(mipmap); for (y = 0, sy0 = ssy0, sy1 = ssy1; y < h; ++y, sy0 += fsy0, sy1 += fsy1) { Uint32 *dst_p = (Uint32 *) ((Uint8*)dst->pixels + y * dst->pitch); Uint8 *src_a0 = (Uint8*)src->pixels + (sy0 >> 16) * slen; Uint8 *src_a1 = (Uint8*)mipmap->pixels + (sy1 >> 16) * mmlen; // retrieve the fractional portions of y const Uint8 v0 = (sy0 >> 8) & 0xff; const Uint8 v1 = (sy1 >> 8) & 0xff; Uint8 w0[4], w1[4]; // pixel weight vectors for (x = 0, sx0 = ssx0, sx1 = ssx1; x < w; ++x, ++dst_p, sx0 += fsx0, sx1 += fsx1) { Uint8 *src_p0 = src_a0 + (sx0 >> 16) * sbpp; Uint8 *src_p1 = src_a1 + (sx1 >> 16) * mmbpp; // retrieve the fractional portions of x const Uint8 u0 = (sx0 >> 8) & 0xff; const Uint8 u1 = (sx1 >> 8) & 0xff; // pixels are examined and numbered in pattern // 0 1 // 2 3 // the ideal pixel (4) is somewhere between these four // and is calculated from these using weight vector (w) // with a dot product pixel_t p0[5], p1[5]; Uint8 res_a; w0[0] = btable[255 - u0][255 - v0]; w0[1] = btable[u0][255 - v0]; w0[2] = btable[255 - u0][v0]; w0[3] = btable[u0][v0]; w1[0] = btable[255 - u1][255 - v1]; w1[1] = btable[u1][255 - v1]; w1[2] = btable[255 - u1][v1]; w1[3] = btable[u1][v1]; // collect interesting pixels from src image p0[0].value = tri_get_pixel (src_p0, srcfmt, srcpal, mk0, ck0); if ((sx0 >> 16) <= src->w - 2) { p0[1].value = tri_get_pixel (src_p0 + sbpp, srcfmt, srcpal, mk0, ck0); if ((sy0 >> 16) <= src->h - 2) { p0[2].value = tri_get_pixel (src_p0 + slen, srcfmt, srcpal, mk0, ck0); p0[3].value = tri_get_pixel (src_p0 + slen + sbpp, srcfmt, srcpal, mk0, ck0); } else { p0[2].value = p0[0].value; p0[3].value = p0[1].value; } } else { p0[1].value = p0[0].value; if ((sy0 >> 16) <= src->h - 2) { p0[2].value = tri_get_pixel (src_p0 + slen, srcfmt, srcpal, mk0, ck0); } else { p0[2].value = p0[0].value; } p0[3].value = p0[2].value; } // collect interesting pixels from mipmap image p1[0].value = tri_get_pixel (src_p1, mmfmt, mmpal, mk1, ck1); if ((sx1 >> 16) <= mipmap->w - 2) { p1[1].value = tri_get_pixel (src_p1 + mmbpp, mmfmt, mmpal, mk1, ck1); if ((sy1 >> 16) <= mipmap->h - 2) { p1[2].value = tri_get_pixel (src_p1 + mmlen, mmfmt, mmpal, mk1, ck1); p1[3].value = tri_get_pixel (src_p1 + mmlen + mmbpp, mmfmt, mmpal, mk1, ck1); } else { p1[2].value = p1[0].value; p1[3].value = p1[1].value; } } else { p1[1].value = p1[0].value; if ((sy1 >> 16) <= mipmap->h - 2) { p1[2].value = tri_get_pixel (src_p1 + mmlen, mmfmt, mmpal, mk1, ck1); } else { p1[2].value = p1[0].value; } p1[3].value = p1[2].value; } p0[4].c.a = dot_product_8_4 (p0, 3, w0); p1[4].c.a = dot_product_8_4 (p1, 3, w1); res_a = blend_ratio_2 (p0[4].c.a, p1[4].c.a, ratio); if (res_a <= alpha_threshold) { *dst_p = transparent; } else if (!dst_has_alpha) { // RGB surface handling p0[4].c.r = dot_product_8_4 (p0, 0, w0); p0[4].c.g = dot_product_8_4 (p0, 1, w0); p0[4].c.b = dot_product_8_4 (p0, 2, w0); p1[4].c.r = dot_product_8_4 (p1, 0, w1); p1[4].c.g = dot_product_8_4 (p1, 1, w1); p1[4].c.b = dot_product_8_4 (p1, 2, w1); p0[4].c.r = blend_ratio_2 (p0[4].c.r, p1[4].c.r, ratio); p0[4].c.g = blend_ratio_2 (p0[4].c.g, p1[4].c.g, ratio); p0[4].c.b = blend_ratio_2 (p0[4].c.b, p1[4].c.b, ratio); *dst_p = (p0[4].c.r << dstfmt->Rshift) | (p0[4].c.g << dstfmt->Gshift) | (p0[4].c.b << dstfmt->Bshift); } else { // RGBA surface handling // we do not want to blend with non-present pixels // (pixels that have alpha == 0) as these will // skew the result and make resulting alpha useless if (p0[4].c.a != 0) { int i; for (i = 0; i < 4; ++i) if (p0[i].c.a == 0) w0[i] = 0; p0[4].c.r = weight_product_8_4 (p0, 0, w0); p0[4].c.g = weight_product_8_4 (p0, 1, w0); p0[4].c.b = weight_product_8_4 (p0, 2, w0); } if (p1[4].c.a != 0) { int i; for (i = 0; i < 4; ++i) if (p1[i].c.a == 0) w1[i] = 0; p1[4].c.r = weight_product_8_4 (p1, 0, w1); p1[4].c.g = weight_product_8_4 (p1, 1, w1); p1[4].c.b = weight_product_8_4 (p1, 2, w1); } if (p0[4].c.a != 0 && p1[4].c.a != 0) { // blend if both present p0[4].c.r = blend_ratio_2 (p0[4].c.r, p1[4].c.r, ratio); p0[4].c.g = blend_ratio_2 (p0[4].c.g, p1[4].c.g, ratio); p0[4].c.b = blend_ratio_2 (p0[4].c.b, p1[4].c.b, ratio); } else if (p1[4].c.a != 0) { // other pixel is present p0[4].value = p1[4].value; } // error-correct alpha to fully opaque to remove // the often unwanted and unnecessary blending if (res_a > 0xf8) res_a = 0xff; *dst_p = (p0[4].c.r << dstfmt->Rshift) | (p0[4].c.g << dstfmt->Gshift) | (p0[4].c.b << dstfmt->Bshift) | (res_a << dstfmt->Ashift); } } } SDL_UnlockSurface(mipmap); SDL_UnlockSurface(dst); SDL_UnlockSurface(src); } void TFB_DrawCanvas_GetScreenFormat (TFB_PixelFormat *fmt) { SDL_PixelFormat *sdl = SDL_Screen->format; if (sdl->palette) { log_add (log_Warning, "TFB_DrawCanvas_GetScreenFormat() WARNING:" "Paletted display format will be slow"); fmt->BitsPerPixel = 32; fmt->Rmask = 0x000000ff; fmt->Gmask = 0x0000ff00; fmt->Bmask = 0x00ff0000; fmt->Amask = 0xff000000; } else { fmt->BitsPerPixel = sdl->BitsPerPixel; fmt->Rmask = sdl->Rmask; fmt->Gmask = sdl->Gmask; fmt->Bmask = sdl->Bmask; fmt->Amask = sdl->Amask; } } void* TFB_DrawCanvas_GetLine (TFB_Canvas canvas, int line) { SDL_Surface* surf = (SDL_Surface *)canvas; return (uint8*)surf->pixels + surf->pitch * line; } void TFB_DrawCanvas_GetPixel (TFB_Canvas canvas, int x, int y, int *r, int *g, int *b) { SDL_Surface* surf = (SDL_Surface *)canvas; Uint8 ur, ug, ub; Uint32 pixel; GetPixelFn getpixel; getpixel = getpixel_for(surf); pixel = (*getpixel)(surf, x, y); SDL_GetRGB (pixel, surf->format, &ur, &ug, &ub); *r = ur; *g = ug; *b = ub; } void TFB_DrawCanvas_Rotate (TFB_Canvas src_canvas, TFB_Canvas dst_canvas, int angle, EXTENT size) { SDL_Surface *src = (SDL_Surface *)src_canvas; SDL_Surface *dst = (SDL_Surface *)dst_canvas; int ret; int r, g, b; if (size.width > dst->w || size.height > dst->h) { log_add (log_Warning, "TFB_DrawCanvas_Rotate: Tried to rotate" " image to size %d %d when dst_canvas has only dimensions" " of %d %d! Failing.", size.width, size.height, dst->w, dst->h); return; } if (TFB_DrawCanvas_GetTransparentColor (src, &r, &g, &b)) { TFB_DrawCanvas_SetTransparentColor (dst, r, g, b, FALSE); /* fill destination with transparent color before rotating */ SDL_FillRect(dst, NULL, SDL_MapRGBA (dst->format, r, g, b, 0)); } ret = rotateSurface (src, dst, angle, 0); if (ret != 0) { log_add (log_Warning, "TFB_DrawCanvas_Rotate: WARNING:" " actual rotation func returned failure\n"); } } void TFB_DrawCanvas_GetRotatedExtent (TFB_Canvas src_canvas, int angle, PEXTENT size) { int dstw, dsth; SDL_Surface *src = (SDL_Surface *)src_canvas; rotozoomSurfaceSize (src->w, src->h, angle, 1, &dstw, &dsth); size->height = dsth; size->width = dstw; } uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/dcqueue.c0000600000175000017500000001352510543202052020720 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "port.h" #include "sdl_common.h" #include "libs/threadlib.h" #include SDL_INCLUDE(SDL_thread.h) #include "libs/graphics/drawcmd.h" #include "libs/graphics/sdl/dcqueue.h" #include "libs/log.h" static RecursiveMutex DCQ_Mutex; CondVar RenderingCond; TFB_DrawCommand DCQ[DCQ_MAX]; TFB_DrawCommandQueue DrawCommandQueue; // Wait for the queue to be emptied. static void TFB_WaitForSpace (int requested_slots) { int old_depth, i; log_add (log_Debug, "DCQ overload (Size = %d, FullSize = %d, " "Requested = %d). Sleeping until renderer is done.", DrawCommandQueue.Size, DrawCommandQueue.FullSize, requested_slots); // Restore the DCQ locking level. I *think* this is // always 1, but... TFB_BatchReset (); old_depth = GetRecursiveMutexDepth (DCQ_Mutex); for (i = 0; i < old_depth; i++) UnlockRecursiveMutex (DCQ_Mutex); WaitCondVar (RenderingCond); for (i = 0; i < old_depth; i++) LockRecursiveMutex (DCQ_Mutex); log_add (log_Debug, "DCQ clear (Size = %d, FullSize = %d). Continuing.", DrawCommandQueue.Size, DrawCommandQueue.FullSize); } void Lock_DCQ (int slots) { LockRecursiveMutex (DCQ_Mutex); while (DrawCommandQueue.FullSize >= DCQ_MAX - slots) { TFB_WaitForSpace (slots); } } void Unlock_DCQ (void) { UnlockRecursiveMutex (DCQ_Mutex); } // Always have the DCQ locked when calling this. static void Synchronize_DCQ (void) { if (!DrawCommandQueue.Batching) { int front = DrawCommandQueue.Front; int back = DrawCommandQueue.InsertionPoint; DrawCommandQueue.Back = DrawCommandQueue.InsertionPoint; if (front <= back) { DrawCommandQueue.Size = (back - front); } else { DrawCommandQueue.Size = (back + DCQ_MAX - front); } DrawCommandQueue.FullSize = DrawCommandQueue.Size; } } void TFB_BatchGraphics (void) { LockRecursiveMutex (DCQ_Mutex); DrawCommandQueue.Batching++; UnlockRecursiveMutex (DCQ_Mutex); } void TFB_UnbatchGraphics (void) { LockRecursiveMutex (DCQ_Mutex); if (DrawCommandQueue.Batching) { DrawCommandQueue.Batching--; } Synchronize_DCQ (); UnlockRecursiveMutex (DCQ_Mutex); } // Cancel all pending batch operations, making them unbatched. This will // cause a small amount of flicker when invoked, but prevents // batching problems from freezing the game. void TFB_BatchReset (void) { LockRecursiveMutex (DCQ_Mutex); DrawCommandQueue.Batching = 0; Synchronize_DCQ (); UnlockRecursiveMutex (DCQ_Mutex); } // Draw Command Queue Stuff void Init_DrawCommandQueue (void) { DrawCommandQueue.Back = 0; DrawCommandQueue.Front = 0; DrawCommandQueue.InsertionPoint = 0; DrawCommandQueue.Batching = 0; DrawCommandQueue.FullSize = 0; DrawCommandQueue.Size = 0; DCQ_Mutex = CreateRecursiveMutex ("DCQ", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); } void Uninit_DrawCommandQueue (void) { DestroyRecursiveMutex (DCQ_Mutex); } void TFB_DrawCommandQueue_Push (TFB_DrawCommand* Command) { Lock_DCQ (1); DCQ[DrawCommandQueue.InsertionPoint] = *Command; DrawCommandQueue.InsertionPoint = (DrawCommandQueue.InsertionPoint + 1) % DCQ_MAX; DrawCommandQueue.FullSize++; Synchronize_DCQ (); Unlock_DCQ (); } int TFB_DrawCommandQueue_Pop (TFB_DrawCommand *target) { LockRecursiveMutex (DCQ_Mutex); if (DrawCommandQueue.Size == 0) { Unlock_DCQ (); return (0); } if (DrawCommandQueue.Front == DrawCommandQueue.Back && DrawCommandQueue.Size != DCQ_MAX) { log_add (log_Debug, "Augh! Assertion failure in DCQ! " "Front == Back, Size != DCQ_MAX"); DrawCommandQueue.Size = 0; Unlock_DCQ (); return (0); } *target = DCQ[DrawCommandQueue.Front]; DrawCommandQueue.Front = (DrawCommandQueue.Front + 1) % DCQ_MAX; DrawCommandQueue.Size--; DrawCommandQueue.FullSize--; UnlockRecursiveMutex (DCQ_Mutex); return 1; } void TFB_DrawCommandQueue_Clear () { LockRecursiveMutex (DCQ_Mutex); DrawCommandQueue.Size = 0; DrawCommandQueue.Front = 0; DrawCommandQueue.Back = 0; DrawCommandQueue.Batching = 0; DrawCommandQueue.FullSize = 0; DrawCommandQueue.InsertionPoint = 0; UnlockRecursiveMutex (DCQ_Mutex); } void TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand) { if (TFB_DEBUG_HALT) { return; } if (DrawCommand->Type <= TFB_DRAWCOMMANDTYPE_COPYTOIMAGE && _CurFramePtr->Type == SCREEN_DRAWABLE) { static RECT scissor_rect; // Set the clipping region. if (scissor_rect.corner.x != _pCurContext->ClipRect.corner.x || scissor_rect.corner.y != _pCurContext->ClipRect.corner.y || scissor_rect.extent.width != _pCurContext->ClipRect.extent.width || scissor_rect.extent.height != _pCurContext->ClipRect.extent.height) { // Enqueue command to set the glScissor spec TFB_DrawCommand DC; scissor_rect = _pCurContext->ClipRect; if (scissor_rect.extent.width) { DC.Type = TFB_DRAWCOMMANDTYPE_SCISSORENABLE; DC.data.scissor.x = scissor_rect.corner.x; DC.data.scissor.y = scissor_rect.corner.y; DC.data.scissor.w = scissor_rect.extent.width; DC.data.scissor.h = scissor_rect.extent.height; } else { DC.Type = TFB_DRAWCOMMANDTYPE_SCISSORDISABLE; } TFB_EnqueueDrawCommand(&DC); } } TFB_DrawCommandQueue_Push (DrawCommand); } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/scalemmx.h0000644000175000017500000005143310552135701021121 0ustar joeyjoey/* * Copyright (C) 2005 Alex Volkov (codepro@usa.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SCALEMMX_H_ #define SCALEMMX_H_ #if !defined(SCALE_) # error Please define SCALE_(name) before including scalemmx.h #endif #if !defined(MSVC_ASM) && !defined(GCC_ASM) # error Please define target assembler (MSVC_ASM, GCC_ASM) before including scalemmx.h #endif // MMX defaults (no Format param) #undef SCALE_CMPRGB #define SCALE_CMPRGB(p1, p2) \ SCALE_(GetRGBDelta) (p1, p2) #undef SCALE_TOYUV #define SCALE_TOYUV(p) \ SCALE_(RGBtoYUV) (p) #undef SCALE_CMPYUV #define SCALE_CMPYUV(p1, p2, toler) \ SCALE_(CmpYUV) (p1, p2, toler) #undef SCALE_GETY #define SCALE_GETY(p) \ SCALE_(GetPixY) (p) // MMX transformation multipliers extern Uint64 mmx_888to555_mult; extern Uint64 mmx_Y_mult; extern Uint64 mmx_U_mult; extern Uint64 mmx_V_mult; extern Uint64 mmx_YUV_threshold; #define USE_YUV_LOOKUP #if defined(MSVC_ASM) // MSVC inline assembly versions #if defined(USE_MOVNTQ) # define MOVNTQ(addr, val) movntq [addr], val #else # define MOVNTQ(addr, val) movq [addr], val #endif #if USE_PREFETCH == INTEL_PREFETCH // using Intel SSE non-temporal prefetch # define PREFETCH(addr) prefetchnta [addr] # define HAVE_PREFETCH #elif USE_PREFETCH == AMD_PREFETCH // using AMD 3DNOW! prefetch # define PREFETCH(addr) prefetch [addr] # define HAVE_PREFETCH #else // no prefetch -- too bad for poor MMX-only souls # define PREFETCH(addr) # undef HAVE_PREFETCH #endif #if defined(_MSC_VER) && (_MSC_VER >= 1300) # pragma warning( disable : 4799 ) #endif static inline void SCALE_(PlatInit) (void) { __asm { // mm0 will be kept == 0 throughout // 0 is needed for bytes->words unpack instructions pxor mm0, mm0 } } static inline void SCALE_(PlatDone) (void) { // finish with MMX registers and yield them to FPU __asm { emms } } #if defined(HAVE_PREFETCH) static inline void SCALE_(Prefetch) (const void* p) { __asm { mov eax, p PREFETCH (eax) } } #else /* Not HAVE_PREFETCH */ static inline void SCALE_(Prefetch) (const void* p) { /* no-op */ } #endif /* HAVE_PREFETCH */ // compute the RGB distance squared between 2 pixels static inline int SCALE_(GetRGBDelta) (Uint32 pix1, Uint32 pix2) { __asm { // load pixels movd mm1, pix1 punpcklbw mm1, mm0 movd mm2, pix2 punpcklbw mm2, mm0 // get the difference between RGBA components psubw mm1, mm2 // squared and sumed pmaddwd mm1, mm1 // finish suming the squares movq mm2, mm1 punpckhdq mm2, mm0 paddd mm1, mm2 // store result movd eax, mm1 } } // retrieve the Y (intensity) component of pixel's YUV static inline int SCALE_(GetPixY) (Uint32 pix) { __asm { // load pixel movd mm1, pix punpcklbw mm1, mm0 // process pmaddwd mm1, mmx_Y_mult // RGB * Yvec movq mm2, mm1 // finish suming punpckhdq mm2, mm0 // ditto paddd mm1, mm2 // ditto // store result movd eax, mm1 shr eax, 14 } } #ifdef USE_YUV_LOOKUP // convert pixel RGB vector into YUV representation vector static inline YUV_VECTOR SCALE_(RGBtoYUV) (Uint32 pix) { __asm { // convert RGB888 to 555 movd mm1, pix punpcklbw mm1, mm0 psrlw mm1, 3 // 8->5 bit pmaddwd mm1, mmx_888to555_mult // shuffle into the right channel order movq mm2, mm1 // finish shuffling punpckhdq mm2, mm0 // ditto por mm1, mm2 // ditto // lookup the YUV vector movd eax, mm1 mov eax, [RGB15_to_YUV + eax * 4] } } // compare 2 pixels with respect to their YUV representations // tolerance set by toler arg // returns true: close; false: distant (-gt toler) static inline bool SCALE_(CmpYUV) (Uint32 pix1, Uint32 pix2, int toler) { __asm { // convert RGB888 to 555 movd mm1, pix1 punpcklbw mm1, mm0 psrlw mm1, 3 // 8->5 bit movd mm3, pix2 punpcklbw mm3, mm0 psrlw mm3, 3 // 8->5 bit pmaddwd mm1, mmx_888to555_mult // shuffle into the right channel order movq mm2, mm1 // finish shuffling pmaddwd mm3, mmx_888to555_mult // shuffle into the right channel order movq mm4, mm3 // finish shuffling punpckhdq mm2, mm0 // ditto por mm1, mm2 // ditto punpckhdq mm4, mm0 // ditto por mm3, mm4 // ditto // lookup the YUV vector movd eax, mm1 movd edx, mm3 movd mm1, [RGB15_to_YUV + eax * 4] movq mm4, mm1 movd mm2, [RGB15_to_YUV + edx * 4] // get abs difference between YUV components #ifdef USE_PSADBW // we can use PSADBW and save us some grief psadbw mm1, mm2 movd edx, mm1 #else // no PSADBW -- have to do it the hard way psubusb mm1, mm2 psubusb mm2, mm4 por mm1, mm2 // sum the differences // XXX: technically, this produces a MAX diff of 510 // but we do not need anything bigger, currently movq mm2, mm1 psrlq mm2, 8 paddusb mm1, mm2 psrlq mm2, 8 paddusb mm1, mm2 movd edx, mm1 and edx, 0xff #endif /* USE_PSADBW */ xor eax, eax shl edx, 1 cmp edx, toler // store result setle al } } #else /* Not USE_YUV_LOOKUP */ // convert pixel RGB vector into YUV representation vector static inline YUV_VECTOR SCALE_(RGBtoYUV) (Uint32 pix) { __asm { movd mm1, pix punpcklbw mm1, mm0 movq mm2, mm1 // Y vector multiply pmaddwd mm1, mmx_Y_mult movq mm4, mm1 punpckhdq mm4, mm0 punpckldq mm1, mm0 // clear out the high dword paddd mm1, mm4 psrad mm1, 15 movq mm3, mm2 // U vector multiply pmaddwd mm2, mmx_U_mult psrad mm2, 10 // V vector multiply pmaddwd mm3, mmx_V_mult psrad mm3, 10 // load (1|1|1|1) into mm4 pcmpeqw mm4, mm4 psrlw mm4, 15 packssdw mm3, mm2 pmaddwd mm3, mm4 psrad mm3, 5 // load (64|64) into mm4 punpcklwd mm4, mm0 pslld mm4, 6 paddd mm3, mm4 packssdw mm3, mm1 packuswb mm3, mm0 movd eax, mm3 } } // compare 2 pixels with respect to their YUV representations // tolerance set by toler arg // returns true: close; false: distant (-gt toler) static inline bool SCALE_(CmpYUV) (Uint32 pix1, Uint32 pix2, int toler) { __asm { movd mm1, pix1 punpcklbw mm1, mm0 movd mm2, pix2 punpcklbw mm2, mm0 psubw mm1, mm2 movq mm2, mm1 // Y vector multiply pmaddwd mm1, mmx_Y_mult movq mm4, mm1 punpckhdq mm4, mm0 paddd mm1, mm4 // abs() movq mm4, mm1 psrad mm4, 31 pxor mm4, mm1 psubd mm1, mm4 movq mm3, mm2 // U vector multiply pmaddwd mm2, mmx_U_mult movq mm4, mm2 punpckhdq mm4, mm0 paddd mm2, mm4 // abs() movq mm4, mm2 psrad mm4, 31 pxor mm4, mm2 psubd mm2, mm4 paddd mm1, mm2 // V vector multiply pmaddwd mm3, mmx_V_mult movq mm4, mm3 punpckhdq mm3, mm0 paddd mm3, mm4 // abs() movq mm4, mm3 psrad mm4, 31 pxor mm4, mm3 psubd mm3, mm4 paddd mm1, mm3 movd edx, mm1 xor eax, eax shr edx, 14 cmp edx, toler // store result setle al } } #endif /* USE_YUV_LOOKUP */ // Check if 2 pixels are different with respect to their // YUV representations // returns 0: close; ~0: distant static inline int SCALE_(DiffYUV) (Uint32 yuv1, Uint32 yuv2) { __asm { // load YUV pixels movd mm1, yuv1 movq mm4, mm1 movd mm2, yuv2 // abs difference between channels psubusb mm1, mm2 psubusb mm2, mm4 por mm1, mm2 // compare to threshold psubusb mm1, mmx_YUV_threshold movd edx, mm1 // transform eax to 0 or ~0 xor eax, eax or edx, edx setz al dec eax } } // bilinear weighted blend of four pixels // MSVC asm version static inline void SCALE_(Blend_bilinear) (const Uint32* row0, const Uint32* row1, Uint32* dst_p, Uint32 dlen) { __asm { // EL0: setup vars mov ebx, row0 // EL0 // EL0: load pixels movq mm1, [ebx] // EL0 movq mm2, mm1 // EL0: p[1] -> mm2 PREFETCH (ebx + 0x80) punpckhbw mm2, mm0 // EL0: p[1] -> mm2 mov ebx, row1 punpcklbw mm1, mm0 // EL0: p[0] -> mm1 movq mm3, [ebx] movq mm4, mm3 // EL0: p[3] -> mm4 movq mm6, mm2 // EL1.1: p[1] -> mm6 PREFETCH (ebx + 0x80) punpcklbw mm3, mm0 // EL0: p[2] -> mm3 movq mm5, mm1 // EL1.1: p[0] -> mm5 punpckhbw mm4, mm0 // EL0: p[3] -> mm4 mov edi, dst_p // EL0 // EL1: cache p[0] + 3*(p[1] + p[2]) + p[3] in mm6 paddw mm6, mm3 // EL1.2: p[1] + p[2] -> mm6 // EL1: cache p[0] + p[1] + p[2] + p[3] in mm7 movq mm7, mm6 // EL1.3: p[1] + p[2] -> mm7 // EL1: cache p[1] + 3*(p[0] + p[3]) + p[2] in mm5 paddw mm5, mm4 // EL1.2: p[0] + p[3] -> mm5 psllw mm6, 1 // EL1.4: 2*(p[1] + p[2]) -> mm6 paddw mm7, mm5 // EL1.4: sum(p[]) -> mm7 psllw mm5, 1 // EL1.5: 2*(p[0] + p[3]) -> mm5 paddw mm6, mm7 // EL1.5: p[0] + 3*(p[1] + p[2]) + p[3] -> mm6 paddw mm5, mm7 // EL1.6: p[1] + 3*(p[0] + p[3]) + p[2] -> mm5 // EL2: pixel 0 math -- (9*p[0] + 3*(p[1] + p[2]) + p[3]) / 16 psllw mm1, 3 // EL2.1: 8*p[0] -> mm1 paddw mm1, mm6 // EL2.2: 9*p[0] + 3*(p[1] + p[2]) + p[3] -> mm1 psrlw mm1, 4 // EL2.3: sum[0]/16 -> mm1 mov edx, dlen // EL0 // EL3: pixel 1 math -- (9*p[1] + 3*(p[0] + p[3]) + p[2]) / 16 psllw mm2, 3 // EL3.1: 8*p[1] -> mm2 paddw mm2, mm5 // EL3.2: 9*p[1] + 3*(p[0] + p[3]) + p[2] -> mm2 psrlw mm2, 4 // EL3.3: sum[1]/16 -> mm5 // EL2/3: store pixels 0 & 1 packuswb mm1, mm2 // EL2/3: pack into bytes MOVNTQ (edi, mm1) // EL2/3: store 2 pixels // EL4: pixel 2 math -- (9*p[2] + 3*(p[0] + p[3]) + p[1]) / 16 psllw mm3, 3 // EL4.1: 8*p[2] -> mm3 paddw mm3, mm5 // EL4.2: 9*p[2] + 3*(p[0] + p[3]) + p[1] -> mm3 psrlw mm3, 4 // EL4.3: sum[2]/16 -> mm3 // EL5: pixel 3 math -- (9*p[3] + 3*(p[1] + p[2]) + p[0]) / 16 psllw mm4, 3 // EL5.1: 8*p[3] -> mm4 paddw mm4, mm6 // EL5.2: 9*p[3] + 3*(p[1] + p[2]) + p[0] -> mm4 psrlw mm4, 4 // EL5.3: sum[3]/16 -> mm4 // EL4/5: store pixels 2 & 3 packuswb mm3, mm4 // EL4/5: pack into bytes MOVNTQ (edi + edx*4, mm3) // EL4/5: store 2 pixels } } // End MSVC_ASM #elif defined(GCC_ASM) // GCC inline assembly versions #if defined(USE_MOVNTQ) # define MOVNTQ(val, addr) "movntq " #val "," #addr #else # define MOVNTQ(val, addr) "movq " #val "," #addr #endif #if USE_PREFETCH == INTEL_PREFETCH // using Intel SSE non-temporal prefetch # define PREFETCH(addr) "prefetchnta " #addr #elif USE_PREFETCH == AMD_PREFETCH // using AMD 3DNOW! prefetch # define PREFETCH(addr) "prefetch " #addr #else // no prefetch -- too bad for poor MMX-only souls # define PREFETCH(addr) #endif #if defined(__x86_64__) # define A_REG "rax" # define D_REG "rdx" # define CLR_UPPER32(r) "xor " "%%" r "," "%%" r # define OFFSETABLE_PTR(p) "r" (p) # define MOVD_WMO(base, ofs, mult, dst) \ "movd " "(" #base "," ofs "," #mult ")," #dst #else # define A_REG "eax" # define D_REG "edx" # define CLR_UPPER32(r) # define OFFSETABLE_PTR(p) "o" (*(p)) # define MOVD_WMO(base, ofs, mult, dst) \ "movd " #base "(," ofs "," #mult ")," #dst #endif static inline void SCALE_(PlatInit) (void) { __asm__ ( // mm0 will be kept == 0 throughout // 0 is needed for bytes->words unpack instructions "pxor %%mm0, %%mm0 \n\t" : /* nothing */ : /* nothing */ ); } static inline void SCALE_(PlatDone) (void) { // finish with MMX registers and yield them to FPU __asm__ ( "emms \n\t" : /* nothing */ : /* nothing */ ); } static inline void SCALE_(Prefetch) (const void* p) { __asm__ __volatile__ ("" PREFETCH (%0) : /*nothing*/ : "m" (p) ); } // compute the RGB distance squared between 2 pixels static inline int SCALE_(GetRGBDelta) (Uint32 pix1, Uint32 pix2) { int res; __asm__ ( // load pixels "movd %1, %%mm1 \n\t" "punpcklbw %%mm0, %%mm1 \n\t" "movd %2, %%mm2 \n\t" "punpcklbw %%mm0, %%mm2 \n\t" // get the difference between RGBA components "psubw %%mm2, %%mm1 \n\t" // squared and sumed "pmaddwd %%mm1, %%mm1 \n\t" // finish suming the squares "movq %%mm1, %%mm2 \n\t" "punpckhdq %%mm0, %%mm2 \n\t" "paddd %%mm2, %%mm1 \n\t" // store result "movd %%mm1, %0 \n\t" : /*0*/"=r" (res) : /*1*/"rm" (pix1), /*2*/"rm" (pix2) ); return res; } // retrieve the Y (intensity) component of pixel's YUV static inline int SCALE_(GetPixY) (Uint32 pix) { int ret; __asm__ ( // load pixel "movd %1, %%mm1 \n\t" "punpcklbw %%mm0, %%mm1 \n\t" // process "pmaddwd %2, %%mm1 \n\t" // R,G,B * Yvec "movq %%mm1, %%mm2 \n\t" // finish suming "punpckhdq %%mm0, %%mm2 \n\t" // ditto "paddd %%mm2, %%mm1 \n\t" // ditto // store index "movd %%mm1, %0 \n\t" : /*0*/"=r" (ret) : /*1*/"rm" (pix), /*2*/"m" (mmx_Y_mult) ); return ret >> 14; } #ifdef USE_YUV_LOOKUP // convert pixel RGB vector into YUV representation vector static inline YUV_VECTOR SCALE_(RGBtoYUV) (Uint32 pix) { int i; __asm__ ( // convert RGB888 to 555 "movd %1, %%mm1 \n\t" "punpcklbw %%mm0, %%mm1 \n\t" "psrlw $3, %%mm1 \n\t" // 8->5 bit "pmaddwd %2, %%mm1 \n\t" // shuffle into the right channel order "movq %%mm1, %%mm2 \n\t" // finish shuffling "punpckhdq %%mm0, %%mm2 \n\t" // ditto "por %%mm2, %%mm1 \n\t" // ditto "movd %%mm1, %0 \n\t" : /*0*/"=r" (i) : /*1*/"rm" (pix), /*2*/"m" (mmx_888to555_mult) ); return RGB15_to_YUV[i]; } // compare 2 pixels with respect to their YUV representations // tolerance set by toler arg // returns true: close; false: distant (-gt toler) static inline bool SCALE_(CmpYUV) (Uint32 pix1, Uint32 pix2, int toler) { int delta; __asm__ ( "movd %1, %%mm1 \n\t" "movd %2, %%mm3 \n\t" // convert RGB888 to 555 // this is somewhat parallelized "punpcklbw %%mm0, %%mm1 \n\t" CLR_UPPER32 (A_REG) "\n\t" "psrlw $3, %%mm1 \n\t" // 8->5 bit "punpcklbw %%mm0, %%mm3 \n\t" "psrlw $3, %%mm3 \n\t" // 8->5 bit "pmaddwd %4, %%mm1 \n\t" // shuffle into the right channel order "movq %%mm1, %%mm2 \n\t" // finish shuffling "pmaddwd %4, %%mm3 \n\t" // shuffle into the right channel order CLR_UPPER32 (D_REG) "\n\t" "movq %%mm3, %%mm4 \n\t" // finish shuffling "punpckhdq %%mm0, %%mm2 \n\t" // ditto "por %%mm2, %%mm1 \n\t" // ditto "punpckhdq %%mm0, %%mm4 \n\t" // ditto "por %%mm4, %%mm3 \n\t" // ditto // lookup the YUV vector "movd %%mm1, %%eax \n\t" "movd %%mm3, %%edx \n\t" //movd (%3, %%eax, 4), %%mm1 MOVD_WMO (%3, "%%" A_REG, 4, %%mm1) "\n\t" "movq %%mm1, %%mm4 \n\t" //movd (%3, %%edx, 4), %%mm2 MOVD_WMO (%3, "%%" D_REG, 4, %%mm2) "\n\t" // get abs difference between YUV components #ifdef USE_PSADBW // we can use PSADBW and save us some grief "psadbw %%mm2, %%mm1 \n\t" "movd %%mm1, %0 \n\t" #else // no PSADBW -- have to do it the hard way "psubusb %%mm2, %%mm1 \n\t" "psubusb %%mm4, %%mm2 \n\t" "por %%mm2, %%mm1 \n\t" // sum the differences // technically, this produces a MAX diff of 510 // but we do not need anything bigger, currently "movq %%mm1, %%mm2 \n\t" "psrlq $8, %%mm2 \n\t" "paddusb %%mm2, %%mm1 \n\t" "psrlq $8, %%mm2 \n\t" "paddusb %%mm2, %%mm1 \n\t" // store intermediate delta "movd %%mm1, %0 \n\t" "andl $0xff, %0 \n\t" #endif /* USE_PSADBW */ : /*0*/"=r" (delta) : /*1*/"rm" (pix1), /*2*/"rm" (pix2), /*3*/OFFSETABLE_PTR(RGB15_to_YUV), /*4*/"m" (mmx_888to555_mult) : "%" A_REG, "%" D_REG ); return (delta << 1) <= toler; } #endif /* USE_YUV_LOOKUP */ // Check if 2 pixels are different with respect to their // YUV representations // returns 0: close; ~0: distant static inline int SCALE_(DiffYUV) (Uint32 yuv1, Uint32 yuv2) { sint32 ret; __asm__ ( // load YUV pixels "movd %1, %%mm1 \n\t" "movq %%mm1, %%mm4 \n\t" "movd %2, %%mm2 \n\t" // abs difference between channels "psubusb %%mm2, %%mm1 \n\t" "psubusb %%mm4, %%mm2 \n\t" CLR_UPPER32(D_REG) "\n\t" "por %%mm2, %%mm1 \n\t" // compare to threshold "psubusb %3, %%mm1 \n\t" "movd %%mm1, %%edx \n\t" // transform eax to 0 or ~0 "xor %%" A_REG ", %%" A_REG "\n\t" "or %%" D_REG ", %%" D_REG "\n\t" "setz %%al \n\t" "dec %%" A_REG " \n\t" : /*0*/"=a" (ret) : /*1*/"rm" (yuv1), /*2*/"rm" (yuv2), /*3*/"m" (mmx_YUV_threshold) : "%" D_REG ); return ret; } // Bilinear weighted blend of four pixels // Function produces 4 blended pixels (in 2x2 matrix) and writes them // out to the surface // Last version static inline void SCALE_(Blend_bilinear) (const Uint32* row0, const Uint32* row1, Uint32* dst_p, Uint32 dlen) { __asm__ ( // EL0: load pixels "movq %0, %%mm1 \n\t" // EL0 "movq %%mm1, %%mm2 \n\t" // EL0: p[1] -> mm2 PREFETCH (0x80%0) "\n\t" "punpckhbw %%mm0, %%mm2 \n\t" // EL0: p[1] -> mm2 "punpcklbw %%mm0, %%mm1 \n\t" // EL0: p[0] -> mm1 "movq %1, %%mm3 \n\t" "movq %%mm3, %%mm4 \n\t" // EL0: p[3] -> mm4 "movq %%mm2, %%mm6 \n\t" // EL1.1: p[1] -> mm6 PREFETCH (0x80%1) "\n\t" "punpcklbw %%mm0, %%mm3 \n\t" // EL0: p[2] -> mm3 "movq %%mm1, %%mm5 \n\t" // EL1.1: p[0] -> mm5 "punpckhbw %%mm0, %%mm4 \n\t" // EL0: p[3] -> mm4 // EL1: cache p[0] + 3*(p[1] + p[2]) + p[3] in mm6 "paddw %%mm3, %%mm6 \n\t" // EL1.2: p[1] + p[2] -> mm6 // EL1: cache p[0] + p[1] + p[2] + p[3] in mm7 "movq %%mm6, %%mm7 \n\t" // EL1.3: p[1] + p[2] -> mm7 // EL1: cache p[1] + 3*(p[0] + p[3]) + p[2] in mm5 "paddw %%mm4, %%mm5 \n\t" // EL1.2: p[0] + p[3] -> mm5 "psllw $1, %%mm6 \n\t" // EL1.4: 2*(p[1] + p[2]) -> mm6 "paddw %%mm5, %%mm7 \n\t" // EL1.4: sum(p[]) -> mm7 "psllw $1, %%mm5 \n\t" // EL1.5: 2*(p[0] + p[3]) -> mm5 "paddw %%mm7, %%mm6 \n\t" // EL1.5: p[0] + 3*(p[1] + p[2]) + p[3] -> mm6 "paddw %%mm7, %%mm5 \n\t" // EL1.6: p[1] + 3*(p[0] + p[3]) + p[2] -> mm5 // EL2: pixel 0 math -- (9*p[0] + 3*(p[1] + p[2]) + p[3]) / 16 "psllw $3, %%mm1 \n\t" // EL2.1: 8*p[0] -> mm1 "paddw %%mm6, %%mm1 \n\t" // EL2.2: 9*p[0] + 3*(p[1] + p[2]) + p[3] -> mm1 "psrlw $4, %%mm1 \n\t" // EL2.3: sum[0]/16 -> mm1 // EL3: pixel 1 math -- (9*p[1] + 3*(p[0] + p[3]) + p[2]) / 16 "psllw $3, %%mm2 \n\t" // EL3.1: 8*p[1] -> mm2 "paddw %%mm5, %%mm2 \n\t" // EL3.2: 9*p[1] + 3*(p[0] + p[3]) + p[2] -> mm5 "psrlw $4, %%mm2 \n\t" // EL3.3: sum[1]/16 -> mm5 // EL2/4: store pixels 0 & 1 "packuswb %%mm2, %%mm1 \n\t" // EL2/4: pack into bytes MOVNTQ (%%mm1, (%2)) "\n\t" // EL2/4: store 2 pixels // EL4: pixel 2 math -- (9*p[2] + 3*(p[0] + p[3]) + p[1]) / 16 "psllw $3, %%mm3 \n\t" // EL4.1: 8*p[2] -> mm3 "paddw %%mm5, %%mm3 \n\t" // EL4.2: 9*p[2] + 3*(p[0] + p[3]) + p[1] -> mm3 "psrlw $4, %%mm3 \n\t" // EL4.3: sum[2]/16 -> mm3 // EL5: pixel 3 math -- (9*p[3] + 3*(p[1] + p[2]) + p[0]) / 16 "psllw $3, %%mm4 \n\t" // EL5.1: 8*p[3] -> mm4 "paddw %%mm6, %%mm4 \n\t" // EL5.2: 9*p[3] + 3*(p[1] + p[2]) + p[0] -> mm4 "psrlw $4, %%mm4 \n\t" // EL5.3: sum[3]/16 -> mm4 // EL4/5: store pixels 2 & 3 "packuswb %%mm4, %%mm3 \n\t" // EL4/5: pack into bytes MOVNTQ (%%mm3, (%2,%3,4)) "\n\t" // EL4/5: store 2 pixels : /* nothing */ : /*0*/"m" (*row0), /*1*/"m" (*row1), /*2*/"r" (dst_p), /*3*/"r" ((unsigned long)dlen) /* 'long' is for proper reg alloc on amd64 */ : "memory" ); } #undef A_REG #undef D_REG #undef CLR_UPPER32 #undef OFFSETABLE_PTR #endif // GCC_ASM #endif /* SCALEMMX_H_ */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/scalers.c0000644000175000017500000001616010552135701020735 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "types.h" #include "libs/graphics/sdl/sdl_common.h" #include "libs/platform.h" #include "libs/log.h" #include "scalers.h" #include "scaleint.h" #include "2xscalers.h" #ifdef USE_PLATFORM_ACCEL # ifndef __APPLE__ // MacOS X framework has no SDL_cpuinfo.h for some reason # include SDL_INCLUDE(SDL_cpuinfo.h) # endif # ifdef MMX_ASM # include "2xscalers_mmx.h" # endif /* MMX_ASM */ #endif /* USE_PLATFORM_ACCEL */ typedef enum { SCALEPLAT_NULL = PLATFORM_NULL, SCALEPLAT_C = PLATFORM_C, SCALEPLAT_MMX = PLATFORM_MMX, SCALEPLAT_SSE = PLATFORM_SSE, SCALEPLAT_3DNOW = PLATFORM_3DNOW, SCALEPLAT_ALTIVEC = PLATFORM_ALTIVEC, SCALEPLAT_C_RGBA, SCALEPLAT_C_BGRA, SCALEPLAT_C_ARGB, SCALEPLAT_C_ABGR, } Scale_PlatType_t; // RGB -> YUV transformation // the RGB vector is multiplied by the transformation matrix // to get the YUV vector #if 0 // original table -- not used const int YUV_matrix[3][3] = { /* Y U V */ /* R */ {0.2989, -0.1687, 0.5000}, /* G */ {0.5867, -0.3312, -0.4183}, /* B */ {0.1144, 0.5000, -0.0816} }; #else // scaled up by a 2^14 factor, with Y doubled const int YUV_matrix[3][3] = { /* Y U V */ /* R */ { 9794, -2764, 8192}, /* G */ {19224, -5428, -6853}, /* B */ { 3749, 8192, -1339} }; #endif // pre-computed transformations for 8 bits per channel int RGB_to_YUV[/*RGB*/ 3][/*YUV*/ 3][ /*mult-res*/ 256]; sint16 dRGB_to_dYUV[/*RGB*/ 3][/*YUV*/ 3][ /*mult-res*/ 512]; // pre-computed transformations for RGB555 YUV_VECTOR RGB15_to_YUV[0x8000]; PLATFORM_TYPE force_platform = PLATFORM_NULL; Scale_PlatType_t Scale_Platform = SCALEPLAT_NULL; // pre-compute the RGB->YUV transformations void Scale_Init (void) { int i1, i2, i3; for (i1 = 0; i1 < 3; i1++) // enum R,G,B for (i2 = 0; i2 < 3; i2++) // enum Y,U,V for (i3 = 0; i3 < 256; i3++) // enum possible channel vals { RGB_to_YUV[i1][i2][i3] = (YUV_matrix[i1][i2] * i3) >> 14; } for (i1 = 0; i1 < 3; i1++) // enum R,G,B for (i2 = 0; i2 < 3; i2++) // enum Y,U,V for (i3 = -255; i3 < 256; i3++) // enum possible channel delta vals { dRGB_to_dYUV[i1][i2][i3 + 255] = (YUV_matrix[i1][i2] * i3) >> 14; } for (i1 = 0; i1 < 32; ++i1) for (i2 = 0; i2 < 32; ++i2) for (i3 = 0; i3 < 32; ++i3) { int y, u, v; // adding upper bits halved for error correction int r = (i1 << 3) | (i1 >> 3); int g = (i2 << 3) | (i2 >> 3); int b = (i3 << 3) | (i3 >> 3); y = ( r * YUV_matrix[YUV_XFORM_R][YUV_XFORM_Y] + g * YUV_matrix[YUV_XFORM_G][YUV_XFORM_Y] + b * YUV_matrix[YUV_XFORM_B][YUV_XFORM_Y] ) >> 15; // we dont need Y doubled, need Y to fit 8 bits // U and V are half the importance of Y u = 64+(( r * YUV_matrix[YUV_XFORM_R][YUV_XFORM_U] + g * YUV_matrix[YUV_XFORM_G][YUV_XFORM_U] + b * YUV_matrix[YUV_XFORM_B][YUV_XFORM_U] ) >> 15); // halved v = 64+(( r * YUV_matrix[YUV_XFORM_R][YUV_XFORM_V] + g * YUV_matrix[YUV_XFORM_G][YUV_XFORM_V] + b * YUV_matrix[YUV_XFORM_B][YUV_XFORM_V] ) >> 15); // halved RGB15_to_YUV[(i1 << 10) | (i2 << 5) | i3] = (y << 16) | (u << 8) | v; } } // expands the given rectangle in all directions by 'expansion' // guarded by 'limits' void Scale_ExpandRect (SDL_Rect* rect, int expansion, const SDL_Rect* limits) { if (rect->x - expansion >= limits->x) { rect->w += expansion; rect->x -= expansion; } else { rect->w += rect->x - limits->x; rect->x = limits->x; } if (rect->y - expansion >= limits->y) { rect->h += expansion; rect->y -= expansion; } else { rect->h += rect->y - limits->y; rect->y = limits->y; } if (rect->x + rect->w + expansion <= limits->w) rect->w += expansion; else rect->w = limits->w - rect->x; if (rect->y + rect->h + expansion <= limits->h) rect->h += expansion; else rect->h = limits->h - rect->y; } // Platform+Scaler function lookups typedef struct { Scale_PlatType_t platform; const Scale_FuncDef_t* funcdefs; } Scale_PlatDef_t; static const Scale_PlatDef_t Scale_PlatDefs[] = { #if defined(MMX_ASM) {SCALEPLAT_SSE, Scale_SSE_Functions}, {SCALEPLAT_3DNOW, Scale_3DNow_Functions}, {SCALEPLAT_MMX, Scale_MMX_Functions}, #endif /* MMX_ASM */ // Default {SCALEPLAT_NULL, Scale_C_Functions} }; TFB_ScaleFunc Scale_PrepPlatform (int flags, const SDL_PixelFormat* fmt) { const Scale_PlatDef_t* pdef; const Scale_FuncDef_t* fdef; (void)flags; Scale_Platform = SCALEPLAT_NULL; // first match wins // add better platform techs to the top #ifdef MMX_ASM if ( (!force_platform && (SDL_HasSSE () || SDL_HasMMXExt ())) || force_platform == SCALEPLAT_SSE) { log_add (log_Info, "Screen scalers are using SSE/MMX-Ext/MMX code"); Scale_Platform = SCALEPLAT_SSE; Scale_SSE_PrepPlatform (fmt); } else if ( (!force_platform && SDL_HasAltiVec ()) || force_platform == SCALEPLAT_ALTIVEC) { log_add (log_Info, "Screen scalers would use AltiVec code " "if someone actually wrote it"); //Scale_Platform = SCALEPLAT_ALTIVEC; } else if ( (!force_platform && SDL_Has3DNow ()) || force_platform == SCALEPLAT_3DNOW) { log_add (log_Info, "Screen scalers are using 3DNow/MMX code"); Scale_Platform = SCALEPLAT_3DNOW; Scale_3DNow_PrepPlatform (fmt); } else if ( (!force_platform && SDL_HasMMX ()) || force_platform == SCALEPLAT_MMX) { log_add (log_Info, "Screen scalers are using MMX code"); Scale_Platform = SCALEPLAT_MMX; Scale_MMX_PrepPlatform (fmt); } #endif if (Scale_Platform == SCALEPLAT_NULL) { // Plain C versions if (fmt->Rmask == 0xff000000) Scale_Platform = SCALEPLAT_C_RGBA; else if (fmt->Rmask == 0x00ff0000) Scale_Platform = SCALEPLAT_C_ARGB; else if (fmt->Rmask == 0x0000ff00) Scale_Platform = SCALEPLAT_C_BGRA; else if (fmt->Rmask == 0x000000ff) Scale_Platform = SCALEPLAT_C_ABGR; else { // use slowest default log_add (log_Warning, "Scale_PrepPlatform(): " "unknown Red mask (0x%08x)", fmt->Rmask); Scale_Platform = SCALEPLAT_C; } if (Scale_Platform == SCALEPLAT_C) log_add (log_Info, "Screen scalers are using slow generic C code"); else log_add (log_Info, "Screen scalers are using optimized C code"); } // Lookup the scaling function // First find the right platform for (pdef = Scale_PlatDefs; pdef->platform != Scale_Platform && pdef->platform != SCALEPLAT_NULL; ++pdef) ; // Next find the right function for (fdef = pdef->funcdefs; (flags & fdef->flag) != fdef->flag; ++fdef) ; return fdef->func; } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/sdluio.c0000600000175000017500000000642610543202053020567 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sdluio.h" #include "port.h" #include "libs/uio.h" #include SDL_INCLUDE(SDL.h) #include SDL_INCLUDE(SDL_error.h) #include SDL_INCLUDE(SDL_rwops.h) #include SDL_IMAGE_INCLUDE(SDL_image.h) #include "libs/misc.h" #include #include static SDL_RWops *sdluio_makeRWops (uio_Stream *stream); #if 0 // For use for initialisation, using structure assignment. static SDL_RWops sdluio_templateRWops = { .seek = sdluio_seek, .read = sdluio_read, .write = sdluio_write, .close = sdluio_close, }; #endif SDL_Surface * sdluio_loadImage (uio_DirHandle *dir, const char *fileName) { uio_Stream *stream; SDL_RWops *rwops; SDL_Surface *result; stream = uio_fopen (dir, fileName, "rb"); if (stream == NULL) { SDL_SetError ("Couldn't open '%s': %s", fileName, strerror(errno)); return NULL; } rwops = sdluio_makeRWops (stream); result = IMG_Load_RW (rwops, 1); return result; } int sdluio_seek (SDL_RWops *context, int offset, int whence) { if (uio_fseek ((uio_Stream *) context->hidden.unknown.data1, offset, whence) == -1) { SDL_SetError ("Error seeking in uio_Stream: %s", strerror(errno)); return -1; } return uio_ftell ((uio_Stream *) context->hidden.unknown.data1); } int sdluio_read (SDL_RWops *context, void *ptr, int size, int maxnum) { size_t numRead; numRead = uio_fread (ptr, (size_t) size, (size_t) maxnum, (uio_Stream *) context->hidden.unknown.data1); if (numRead == 0 && uio_ferror ((uio_Stream *) context->hidden.unknown.data1)) { SDL_SetError ("Error reading from uio_Stream: %s", strerror(errno)); return 0; } return (int) numRead; } int sdluio_write (SDL_RWops *context, const void *ptr, int size, int num) { size_t numWritten; numWritten = uio_fwrite (ptr, (size_t) size, (size_t) num, (uio_Stream *) context->hidden.unknown.data1); if (numWritten == 0 && uio_ferror ((uio_Stream *) context->hidden.unknown.data1)) { SDL_SetError ("Error writing to uio_Stream: %s", strerror(errno)); return 0; } return (size_t) numWritten; } int sdluio_close (SDL_RWops *context) { int result; result = uio_fclose ((uio_Stream *) context->hidden.unknown.data1); HFree (context); return result; } static SDL_RWops * sdluio_makeRWops (uio_Stream *stream) { SDL_RWops *result; result = HMalloc (sizeof (SDL_RWops)); #if 0 *(struct SDL_RWops *) result = sdluio_templateRWops; // structure assignment #endif result->seek = sdluio_seek; result->read = sdluio_read; result->write = sdluio_write; result->close = sdluio_close; result->hidden.unknown.data1 = (void *) stream; return result; } uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/3do_blt.c0000600000175000017500000000363610543202052020615 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "sdl_common.h" #include "graphics/tfb_draw.h" #include "libs/log.h" static int gscale = GSCALE_IDENTITY; void SetGraphicScale (int scale) { gscale = (scale ? scale : GSCALE_IDENTITY); } int GetGraphicScale () { return gscale; } static void read_screen (PRECT lpRect, FRAMEPTR DstFramePtr) { if (_CurFramePtr->Type != SCREEN_DRAWABLE || DstFramePtr->Type == SCREEN_DRAWABLE || !(GetFrameParentDrawable (DstFramePtr)->Flags & MAPPED_TO_DISPLAY)) { log_add (log_Warning, "Unimplemented function activated: read_screen()"); } else { TFB_Image *img = DstFramePtr->image; TFB_DrawScreen_CopyToImage (img, lpRect, TFB_SCREEN_MAIN); } } static DRAWABLE alloc_image (COUNT NumFrames, DRAWABLE_TYPE DrawableType, CREATE_FLAGS flags, SIZE width, SIZE height) { /* dodge compiler warnings */ (void)DrawableType; (void)flags; (void)width; (void)height; return AllocDrawable (NumFrames); } static DISPLAY_INTERFACE DisplayInterface = { WANT_MASK, 16, // SCREEN_DEPTH, 320, 240, alloc_image, read_screen, }; void LoadDisplay (PDISPLAY_INTERFACE *pDisplay) { *pDisplay = &DisplayInterface; } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/3do_getbody.c0000600000175000017500000004320510543202053021466 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #ifdef WIN32 #include #endif #include #include "options.h" #include "port.h" #include "sdl_common.h" #include "sdluio.h" #include "libs/file.h" #include "libs/reslib.h" #include "libs/log.h" #include "../font.h" #include "primitives.h" typedef struct anidata { int transparent_color; int colormap_index; int hotspot_x; int hotspot_y; } AniData; static void process_image (FRAMEPTR FramePtr, SDL_Surface *img[], AniData *ani, int cel_ct) { TFB_Image *tfbimg; int hx, hy; FramePtr->Type = ROM_DRAWABLE; FramePtr->Index = cel_ct; // handle transparency cases if (img[cel_ct]->format->palette) { // indexed color image if (ani[cel_ct].transparent_color >= 0) SDL_SetColorKey (img[cel_ct], SDL_SRCCOLORKEY, ani[cel_ct].transparent_color); } else if (img[cel_ct]->format->BitsPerPixel > 8) { // special transparency cases for truecolor images if (ani[cel_ct].transparent_color == 0) // make RGB=0,0,0 transparent SDL_SetColorKey (img[cel_ct], SDL_SRCCOLORKEY, SDL_MapRGBA (img[cel_ct]->format, 0, 0, 0, 0)); } if (ani[cel_ct].transparent_color == -1) { // enforce -1 to mean 'no transparency' SDL_SetColorKey (img[cel_ct], 0, 0); // set transparent_color == -2 to use PNG tRNS transparency } hx = ani[cel_ct].hotspot_x; hy = ani[cel_ct].hotspot_y; FramePtr->image = TFB_DrawImage_New (img[cel_ct]); tfbimg = FramePtr->image; tfbimg->colormap_index = ani[cel_ct].colormap_index; img[cel_ct] = (SDL_Surface *)tfbimg->NormalImg; FramePtr->HotSpot = MAKE_HOT_SPOT (hx, hy); SetFrameBounds (FramePtr, img[cel_ct]->w, img[cel_ct]->h); #ifdef CLIPDEBUG { /* for debugging clipping: draws white (or most matching color from palette) pixels to every corner of the image */ Uint32 color = SDL_MapRGB (img[cel_ct]->format, 255, 255, 255); SDL_Rect r = {0, 0, 1, 1}; if (img[cel_ct]->w > 2 && img[cel_ct]->h > 2) { SDL_FillRect (img[cel_ct], &r, color); r.x = img[cel_ct]->w - 1; SDL_FillRect (img[cel_ct], &r, color); r.y = img[cel_ct]->h - 1; SDL_FillRect (img[cel_ct], &r, color); r.x = 0; SDL_FillRect (img[cel_ct], &r, color); } } #endif } static void processFontChar (TFB_Char* CharPtr, SDL_Surface *surf) { int x,y; Uint8 r,g,b,a; Uint32 p; SDL_PixelFormat* srcfmt = surf->format; GetPixelFn getpix; BYTE* newdata; Uint32 dpitch; // Currently, each font char has its own separate data // but that can change to common mem area newdata = HMalloc (surf->w * surf->h * sizeof(BYTE)); dpitch = surf->w; SDL_LockSurface (surf); getpix = getpixel_for (surf); // produce an alpha-only image in internal BYTE[] format // from the SDL surface for (y = 0; y < surf->h; ++y) { BYTE* dst = newdata + dpitch * y; for (x = 0; x < surf->w; ++x, ++dst) { p = getpix (surf, x, y); SDL_GetRGBA (p, srcfmt, &r, &g, &b, &a); if (!srcfmt->Amask) { // produce alpha from intensity (Y component) // using a fast approximation // contributions to Y are: R=2, G=4, B=1 a = (((int)r << 1) + ((int)g << 2) + b) / 7; } *dst = a; } } SDL_UnlockSurface (surf); CharPtr->data = newdata; CharPtr->pitch = dpitch; CharPtr->extent.width = surf->w; CharPtr->extent.height = surf->h; CharPtr->disp.width = surf->w + 1; CharPtr->disp.height = surf->h + 1; // XXX: why the +1? // I brought it into this function from the only calling // function, but I don't know why it was there in the first // place. // XXX: the +1 appears to be for character and line spacing // text_blt just adds the frame width to move to the next char { // This tunes the font positioning to be about what it should // TODO: prolly needs a little tweaking still int tune_amount = 0; if (CharPtr->extent.height == 8) tune_amount = -1; else if (CharPtr->extent.height == 9) tune_amount = -2; else if (CharPtr->extent.height > 9) tune_amount = -3; CharPtr->HotSpot = MAKE_HOT_SPOT (0, CharPtr->extent.height + tune_amount); } } // stretch_frame // create a new frame of size neww x newh, and blit a scaled version FramePtr // into it. // destroy the old frame if 'destroy' is 1 FRAMEPTR stretch_frame (FRAMEPTR FramePtr, int neww, int newh, int destroy) { FRAMEPTR NewFrame; CREATE_FLAGS flags; TFB_Image *tfbImg; TFB_Canvas src, dst; EXTENT ext; flags = GetFrameParentDrawable (FramePtr)->Flags; NewFrame = CaptureDrawable ( CreateDrawable (flags, (SIZE)neww, (SIZE)newh, 1)); tfbImg = FramePtr->image; LockMutex (tfbImg->mutex); src = tfbImg->NormalImg; dst = NewFrame->image->NormalImg; ext.width = neww; ext.height = newh; TFB_DrawCanvas_Rescale_Nearest (src, dst, ext); UnlockMutex (tfbImg->mutex); if (destroy) DestroyDrawable (ReleaseDrawable (FramePtr)); return (NewFrame); } void process_rgb_bmp (FRAMEPTR FramePtr, Uint32 *rgba, int maxx, int maxy) { int x, y; TFB_Image *tfbImg; SDL_Surface *img; PutPixelFn putpix; tfbImg = FramePtr->image; LockMutex (tfbImg->mutex); img = (SDL_Surface *)tfbImg->NormalImg; SDL_LockSurface (img); putpix = putpixel_for (img); for (y = 0; y < maxy; ++y) for (x = 0; x < maxx; ++x) putpix (img, x, y, *rgba++); SDL_UnlockSurface (img); UnlockMutex (tfbImg->mutex); } void fill_frame_rgb (FRAMEPTR FramePtr, Uint32 color, int x0, int y0, int x, int y) { SDL_Surface *img; TFB_Image *tfbImg; SDL_Rect rect; tfbImg = FramePtr->image; LockMutex (tfbImg->mutex); img = (SDL_Surface *)tfbImg->NormalImg; SDL_LockSurface (img); if (x0 == 0 && y0 == 0 && x == 0 && y == 0) SDL_FillRect(img, NULL, color); else { rect.x = x0; rect.y = y0; rect.w = x - x0; rect.h = y - y0; SDL_FillRect(img, &rect, color); } SDL_UnlockSurface (img); UnlockMutex (tfbImg->mutex); } void arith_frame_blit (FRAMEPTR srcFrame, RECT *rsrc, FRAMEPTR dstFrame, RECT *rdst, int num, int denom) { TFB_Image *srcImg, *dstImg; SDL_Surface *src, *dst; SDL_Rect srcRect, dstRect, *srp = NULL, *drp = NULL; srcImg = srcFrame->image; dstImg = dstFrame->image; LockMutex (srcImg->mutex); LockMutex (dstImg->mutex); src = (SDL_Surface *)srcImg->NormalImg; dst = (SDL_Surface *)dstImg->NormalImg; if (rdst) { dstRect.x = rdst->corner.x; dstRect.y = rdst->corner.y; dstRect.w = rdst->extent.width; dstRect.h = rdst->extent.height; drp = &dstRect; } if (rsrc) { srcRect.x = rsrc->corner.x; srcRect.y = rsrc->corner.y; srcRect.w = rsrc->extent.width; srcRect.h = rsrc->extent.height; srp = &srcRect; } else if (srcFrame->HotSpot.x || srcFrame->HotSpot.y) { if (rdst) { dstRect.x -= srcFrame->HotSpot.x; dstRect.y -= srcFrame->HotSpot.y; } else { dstRect.x = -srcFrame->HotSpot.x; dstRect.y = -srcFrame->HotSpot.y; dstRect.w = GetFrameWidth (srcFrame); dstRect.h = GetFrameHeight (srcFrame); drp =&dstRect; } } TFB_BlitSurface (src, srp, dst, drp, num, denom); UnlockMutex (srcImg->mutex); UnlockMutex (dstImg->mutex); } // Generate an array of all pixels in FramePtr // The 32bpp pixel format is : // bits 24-31 : red // bits 16-23 : green // bits 8-15 : blue // bits 0-7 : alpha // The 8bpp pixel format is 1 index per pixel void getpixelarray (void *map, int Bpp, FRAMEPTR FramePtr, int width, int height) { Uint8 r,g,b,a; Uint32 p, pos, row; TFB_Image *tfbImg; SDL_Surface *img; GetPixelFn getpix; int x, y, w, h; tfbImg = FramePtr->image; LockMutex (tfbImg->mutex); img = (SDL_Surface *)tfbImg->NormalImg; getpix = getpixel_for (img); w = width < img->w ? width : img->w; h = height < img->h ? height : img->h; SDL_LockSurface (img); if (Bpp == 4) { Uint32 *dp = (Uint32 *)map; for (y = 0, row = 0; y < h; y++, row += width) { for (x = 0, pos = row; x < w; x++, pos++) { p = getpix (img, x, y); SDL_GetRGBA (p, img->format, &r, &g, &b, &a); dp[pos] = r << 24 | g << 16 | b << 8 | a; } } } else if (Bpp == 1) { Uint8 *dp = (Uint8 *)map; for (y = 0, row = 0; y < h; y++, row += width) { for (x = 0, pos = row; x < w; x++, pos++) { p = getpix (img, x, y); dp[pos] = p; } } } SDL_UnlockSurface (img); UnlockMutex (tfbImg->mutex); } // Generate a pixel (in the correct format to be applied to FramePtr) from the // r,g,b,a values supplied Uint32 frame_mapRGBA (FRAMEPTR FramePtr,Uint8 r, Uint8 g, Uint8 b, Uint8 a) { SDL_Surface *img= (SDL_Surface *)FramePtr->image->NormalImg; return (SDL_MapRGBA (img->format, r, g, b, a)); } MEM_HANDLE _GetCelData (uio_Stream *fp, DWORD length) { int cel_ct, n; DWORD opos; char CurrentLine[1024], filename[1024]; #define MAX_CELS 256 SDL_Surface *img[MAX_CELS]; AniData ani[MAX_CELS]; DRAWABLE Drawable; opos = uio_ftell (fp); { char *s1, *s2; if (_cur_resfile_name == 0 || (((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0) && (s2 = strrchr (_cur_resfile_name, '\\')) == 0)) n = 0; else { if (s2 > s1) s1 = s2; n = s1 - _cur_resfile_name + 1; strncpy (filename, _cur_resfile_name, n); } } cel_ct = 0; while (uio_fgets (CurrentLine, sizeof (CurrentLine), fp) && cel_ct < MAX_CELS) { sscanf (CurrentLine, "%s %d %d %d %d", &filename[n], &ani[cel_ct].transparent_color, &ani[cel_ct].colormap_index, &ani[cel_ct].hotspot_x, &ani[cel_ct].hotspot_y); img[cel_ct] = sdluio_loadImage (contentDir, filename); if (img[cel_ct] == NULL) { const char *err; err = SDL_GetError(); log_add (log_Warning, "_GetCelData: Unable to load image!"); if (err != NULL) log_add (log_Warning, "SDL reports: %s", err); SDL_FreeSurface (img[cel_ct]); } else if (img[cel_ct]->w < 0 || img[cel_ct]->h < 0 || img[cel_ct]->format->BitsPerPixel < 8) { log_add (log_Warning, "_GetCelData: Bad file!"); SDL_FreeSurface (img[cel_ct]); } else { ++cel_ct; } if ((int)uio_ftell (fp) - (int)opos >= (int)length) break; } Drawable = 0; if (cel_ct && (Drawable = AllocDrawable (cel_ct))) { DRAWABLEPTR DrawablePtr; if ((DrawablePtr = LockDrawable (Drawable)) == 0) { while (cel_ct--) SDL_FreeSurface (img[cel_ct]); mem_release ((MEM_HANDLE)Drawable); Drawable = 0; } else { FRAMEPTR FramePtr; DrawablePtr->hDrawable = GetDrawableHandle (Drawable); DrawablePtr->Flags = WANT_PIXMAP; DrawablePtr->MaxIndex = cel_ct - 1; FramePtr = &DrawablePtr->Frame[cel_ct]; while (--FramePtr, cel_ct--) process_image (FramePtr, img, ani, cel_ct); UnlockDrawable (Drawable); } } if (Drawable == 0) log_add (log_Warning, "Couldn't get cel data for '%s'", _cur_resfile_name); return (GetDrawableHandle (Drawable)); } BOOLEAN _ReleaseCelData (MEM_HANDLE handle) { DRAWABLEPTR DrawablePtr; int cel_ct; FRAMEPTR FramePtr = NULL; if ((DrawablePtr = LockDrawable (handle)) == 0) return (FALSE); cel_ct = DrawablePtr->MaxIndex + 1; if (DrawablePtr->Frame) { FramePtr = DrawablePtr->Frame; if (FramePtr->Type == SCREEN_DRAWABLE) { FramePtr = NULL; } } UnlockDrawable (handle); if (mem_release (handle) && FramePtr) { int i; for (i = 0; i < cel_ct; i++) { TFB_Image *img = FramePtr[i].image; if (img) { FramePtr[i].image = NULL; TFB_DrawScreen_DeleteImage (img); } } HFree (FramePtr); } return (TRUE); } typedef struct BuildCharDesc { SDL_Surface *surface; wchar_t index; } BuildCharDesc; int compareBCDIndex(const BuildCharDesc *bcd1, const BuildCharDesc *bcd2) { return (int) bcd1->index - (int) bcd2->index; } MEM_HANDLE _GetFontData (uio_Stream *fp, DWORD length) { COUNT numDirEntries; FONT_REF fontRef = 0; DIRENTRY fontDir = 0; BuildCharDesc *bcds = NULL; size_t numBCDs = 0; int dirEntryI; uio_DirHandle *fontDirHandle = NULL; FONTPTR fontPtr; if (_cur_resfile_name == 0) goto err; fontDir = CaptureDirEntryTable (LoadDirEntryTable (contentDir, _cur_resfile_name, ".", match_MATCH_SUBSTRING, &numDirEntries)); if (fontDir == 0) goto err; fontDirHandle = uio_openDirRelative (contentDir, _cur_resfile_name, 0); if (fontDirHandle == NULL) goto err; bcds = HMalloc (numDirEntries * sizeof (BuildCharDesc)); if (bcds == NULL) goto err; // Load the surfaces for all dir Entries for (dirEntryI = 0; dirEntryI < numDirEntries; dirEntryI++) { char *char_name; unsigned int charIndex; SDL_Surface *surface; char_name = GetDirEntryAddress (SetAbsDirEntryTableIndex ( fontDir, dirEntryI)); if (sscanf (char_name, "%u.", &charIndex) != 1) continue; if (charIndex > 0xffff) continue; surface = sdluio_loadImage (fontDirHandle, char_name); if (surface == NULL) continue; if (surface->w == 0 || surface->h == 0 || surface->format->BitsPerPixel < 8) { SDL_FreeSurface (surface); continue; } bcds[numBCDs].surface = surface; bcds[numBCDs].index = charIndex; numBCDs++; } uio_closeDir (fontDirHandle); DestroyDirEntryTable (ReleaseDirEntryTable (fontDir)); #if 0 if (numBCDs == 0) goto err; #endif // sort on the character index qsort (bcds, numBCDs, sizeof (BuildCharDesc), (int (*)(const void *, const void *)) compareBCDIndex); fontRef = AllocFont (0); if (fontRef == 0) goto err; fontPtr = LockFont (fontRef); if (fontPtr == NULL) goto err; fontPtr->FontRef = fontRef; fontPtr->Leading = 0; fontPtr->LeadingWidth = 0; { size_t startBCD = 0; int pageStart; FONT_PAGE **pageEndPtr = &fontPtr->fontPages; while (startBCD < numBCDs) { // Process one character page. size_t endBCD; pageStart = bcds[startBCD].index & CHARACTER_PAGE_MASK; endBCD = startBCD; while (endBCD < numBCDs && (bcds[endBCD].index & CHARACTER_PAGE_MASK) == pageStart) endBCD++; { size_t bcdI; int numChars = bcds[endBCD - 1].index + 1 - bcds[startBCD].index; FONT_PAGE *page = AllocFontPage (numChars); page->pageStart = pageStart; page->firstChar = bcds[startBCD].index; page->numChars = numChars; *pageEndPtr = page; pageEndPtr = &page->next; for (bcdI = startBCD; bcdI < endBCD; bcdI++) { // Process one character. BuildCharDesc *bcd = &bcds[bcdI]; TFB_Char *destChar = &page->charDesc[bcd->index - page->firstChar]; if (destChar->data != NULL) { // There's already an image for this character. log_add (log_Debug, "Duplicate image for character %d " "for font %s.", (int) bcd->index, _cur_resfile_name); SDL_FreeSurface (bcd->surface); continue; } processFontChar (destChar, bcd->surface); SDL_FreeSurface (bcd->surface); if (destChar->disp.height > fontPtr->Leading) fontPtr->Leading = destChar->disp.height; if (destChar->disp.width > fontPtr->LeadingWidth) fontPtr->LeadingWidth = destChar->disp.width; } } startBCD = endBCD; } *pageEndPtr = NULL; } fontPtr->Leading++; UnlockFont (fontRef); HFree (bcds); (void) fp; /* Satisfying compiler (unused parameter) */ (void) length; /* Satisfying compiler (unused parameter) */ return fontRef; err: if (fontRef != 0) mem_release (fontRef); if (bcds != NULL) { size_t bcdI; for (bcdI = 0; bcdI < numBCDs; bcdI++) SDL_FreeSurface (bcds[bcdI].surface); HFree (bcds); } if (fontDirHandle != NULL) uio_closeDir (fontDirHandle); if (fontDir != 0) DestroyDirEntryTable (ReleaseDirEntryTable (fontDir)); return 0; } BOOLEAN _ReleaseFontData (MEM_HANDLE handle) { FONTPTR font = LockFont (handle); if (font == NULL) return FALSE; { FONT_PAGE *page; FONT_PAGE *nextPage; for (page = font->fontPages; page != NULL; page = nextPage) { size_t charI; for (charI = 0; charI < page->numChars; charI++) { TFB_Char *c = &page->charDesc[charI]; if (c->data == NULL) continue; // XXX: fix this if fonts get per-page data // rather than per-char TFB_DrawScreen_DeleteData (c->data); } nextPage = page->next; FreeFontPage (page); } } UnlockFont (handle); mem_release (handle); return TRUE; } // _request_drawable was in libs/graphics/drawable.c before modularization DRAWABLE _request_drawable (COUNT NumFrames, DRAWABLE_TYPE DrawableType, CREATE_FLAGS flags, SIZE width, SIZE height) { DRAWABLE Drawable; Drawable = AllocDrawableImage ( NumFrames, DrawableType, flags, width, height ); if (Drawable) { DRAWABLEPTR DrawablePtr; if ((DrawablePtr = LockDrawable (Drawable)) == 0) { FreeDrawable (Drawable); Drawable = 0; } else { int imgw, imgh; FRAMEPTR FramePtr; DrawablePtr->hDrawable = GetDrawableHandle (Drawable); DrawablePtr->Flags = flags; DrawablePtr->MaxIndex = NumFrames - 1; imgw = width; imgh = height; FramePtr = &DrawablePtr->Frame[NumFrames - 1]; while (NumFrames--) { TFB_Image *Image; if (DrawableType == RAM_DRAWABLE && imgw > 0 && imgh > 0 && (Image = TFB_DrawImage_New (TFB_DrawCanvas_New_TrueColor ( imgw, imgh, (flags & WANT_ALPHA) ? TRUE : FALSE)))) { FramePtr->image = Image; } FramePtr->Type = DrawableType; FramePtr->Index = NumFrames; SetFrameBounds (FramePtr, width, height); --FramePtr; } UnlockDrawable (Drawable); } } return (Drawable); } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/2xscalers_mmx.h0000644000175000017500000000461310552135701022075 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _2XSCALERS_MMX_H_ #define _2XSCALERS_MMX_H_ // MMX versions void Scale_MMX_PrepPlatform (const SDL_PixelFormat* fmt); void Scale_MMX_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_MMX_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_MMX_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_MMX_TriScanFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_MMX_HqFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); extern const Scale_FuncDef_t Scale_MMX_Functions[]; // SSE (Intel)/MMX Ext (Athlon) versions void Scale_SSE_PrepPlatform (const SDL_PixelFormat* fmt); void Scale_SSE_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_SSE_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_SSE_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_SSE_TriScanFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_SSE_HqFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); extern const Scale_FuncDef_t Scale_SSE_Functions[]; // 3DNow (AMD K6/Athlon) versions void Scale_3DNow_PrepPlatform (const SDL_PixelFormat* fmt); void Scale_3DNow_Nearest (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_3DNow_BilinearFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_3DNow_BiAdaptAdvFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_3DNow_TriScanFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); void Scale_3DNow_HqFilter (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); extern const Scale_FuncDef_t Scale_3DNow_Functions[]; #endif /* _2XSCALERS_MMX_H_ */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/hq2x.c0000600000175000017500000012676610543202052020163 0ustar joeyjoey//hq2x filter //-------------------------------------------------------------------------- //Copyright (C) 2003 MaxSt ( maxst@hiend3d.com ) - Original version // //Portions Copyright (C) 2005 Alex Volkov ( codepro@usa.net ) // Modified Oct-2-2005 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Core algorithm of the HQ screen scaler // adapted from hq2x -- www.hiend3d.com/hq2x.html // Template // When this file is built standalone is produces a plain C version // Also #included by 2xscalers_mmx.c for an MMX version #ifdef GFXMODULE_SDL #include "libs/graphics/sdl/sdl_common.h" #include "types.h" #include "scalers.h" #include "scaleint.h" #include "2xscalers.h" // Pixel blending/manipulation instructions #define PIXEL00_0 dst_p[0] = pix[5]; #define PIXEL00_10 dst_p[0] = Scale_Blend_31(pix[5], pix[1]); #define PIXEL00_11 dst_p[0] = Scale_Blend_31(pix[5], pix[4]); #define PIXEL00_12 dst_p[0] = Scale_Blend_31(pix[5], pix[2]); #define PIXEL00_20 dst_p[0] = Scale_Blend_211(pix[5], pix[4], pix[2]); #define PIXEL00_21 dst_p[0] = Scale_Blend_211(pix[5], pix[1], pix[2]); #define PIXEL00_22 dst_p[0] = Scale_Blend_211(pix[5], pix[1], pix[4]); #define PIXEL00_60 dst_p[0] = Scale_Blend_521(pix[5], pix[2], pix[4]); #define PIXEL00_61 dst_p[0] = Scale_Blend_521(pix[5], pix[4], pix[2]); #define PIXEL00_70 dst_p[0] = Scale_Blend_611(pix[5], pix[4], pix[2]); #define PIXEL00_90 dst_p[0] = Scale_Blend_233(pix[5], pix[4], pix[2]); #define PIXEL00_100 dst_p[0] = Scale_Blend_e11(pix[5], pix[4], pix[2]); #define PIXEL01_0 dst_p[1] = pix[5]; #define PIXEL01_10 dst_p[1] = Scale_Blend_31(pix[5], pix[3]); #define PIXEL01_11 dst_p[1] = Scale_Blend_31(pix[5], pix[2]); #define PIXEL01_12 dst_p[1] = Scale_Blend_31(pix[5], pix[6]); #define PIXEL01_20 dst_p[1] = Scale_Blend_211(pix[5], pix[2], pix[6]); #define PIXEL01_21 dst_p[1] = Scale_Blend_211(pix[5], pix[3], pix[6]); #define PIXEL01_22 dst_p[1] = Scale_Blend_211(pix[5], pix[3], pix[2]); #define PIXEL01_60 dst_p[1] = Scale_Blend_521(pix[5], pix[6], pix[2]); #define PIXEL01_61 dst_p[1] = Scale_Blend_521(pix[5], pix[2], pix[6]); #define PIXEL01_70 dst_p[1] = Scale_Blend_611(pix[5], pix[2], pix[6]); #define PIXEL01_90 dst_p[1] = Scale_Blend_233(pix[5], pix[2], pix[6]); #define PIXEL01_100 dst_p[1] = Scale_Blend_e11(pix[5], pix[2], pix[6]); #define PIXEL10_0 dst_p[dlen] = pix[5]; #define PIXEL10_10 dst_p[dlen] = Scale_Blend_31(pix[5], pix[7]); #define PIXEL10_11 dst_p[dlen] = Scale_Blend_31(pix[5], pix[8]); #define PIXEL10_12 dst_p[dlen] = Scale_Blend_31(pix[5], pix[4]); #define PIXEL10_20 dst_p[dlen] = Scale_Blend_211(pix[5], pix[8], pix[4]); #define PIXEL10_21 dst_p[dlen] = Scale_Blend_211(pix[5], pix[7], pix[4]); #define PIXEL10_22 dst_p[dlen] = Scale_Blend_211(pix[5], pix[7], pix[8]); #define PIXEL10_60 dst_p[dlen] = Scale_Blend_521(pix[5], pix[4], pix[8]); #define PIXEL10_61 dst_p[dlen] = Scale_Blend_521(pix[5], pix[8], pix[4]); #define PIXEL10_70 dst_p[dlen] = Scale_Blend_611(pix[5], pix[8], pix[4]); #define PIXEL10_90 dst_p[dlen] = Scale_Blend_233(pix[5], pix[8], pix[4]); #define PIXEL10_100 dst_p[dlen] = Scale_Blend_e11(pix[5], pix[8], pix[4]); #define PIXEL11_0 dst_p[dlen + 1] = pix[5]; #define PIXEL11_10 dst_p[dlen + 1] = Scale_Blend_31(pix[5], pix[9]); #define PIXEL11_11 dst_p[dlen + 1] = Scale_Blend_31(pix[5], pix[6]); #define PIXEL11_12 dst_p[dlen + 1] = Scale_Blend_31(pix[5], pix[8]); #define PIXEL11_20 dst_p[dlen + 1] = Scale_Blend_211(pix[5], pix[6], pix[8]); #define PIXEL11_21 dst_p[dlen + 1] = Scale_Blend_211(pix[5], pix[9], pix[8]); #define PIXEL11_22 dst_p[dlen + 1] = Scale_Blend_211(pix[5], pix[9], pix[6]); #define PIXEL11_60 dst_p[dlen + 1] = Scale_Blend_521(pix[5], pix[8], pix[6]); #define PIXEL11_61 dst_p[dlen + 1] = Scale_Blend_521(pix[5], pix[6], pix[8]); #define PIXEL11_70 dst_p[dlen + 1] = Scale_Blend_611(pix[5], pix[6], pix[8]); #define PIXEL11_90 dst_p[dlen + 1] = Scale_Blend_233(pix[5], pix[6], pix[8]); #define PIXEL11_100 dst_p[dlen + 1] = Scale_Blend_e11(pix[5], pix[6], pix[8]); // HQ scaling to 2x // The name expands to // Scale_HqFilter (for plain C) // Scale_MMX_HqFilter (for MMX) // [others when platforms are added] void SCALE_(HqFilter) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) { int x, y; const int w = src->w, h = src->h; int xend, yend; int dsrc, ddst; SDL_Rect *region = r; SDL_Rect limits; SDL_PixelFormat *fmt = dst->format; const int sp = src->pitch, dp = dst->pitch; const int bpp = fmt->BytesPerPixel; const int slen = sp / bpp, dlen = dp / bpp; Uint32 *src_p = (Uint32 *)src->pixels; Uint32 *dst_p = (Uint32 *)dst->pixels; int prevline, nextline; Uint32 pix[10]; Uint32 yuv[10]; // +----+----+----+ // | | | | // | p1 | p2 | p3 | // +----+----+----+ // | | | | // | p4 | p5 | p6 | // +----+----+----+ // | | | | // | p7 | p8 | p9 | // +----+----+----+ // MMX code runs faster w/o branching #define HQXX_DIFFYUV(p1, p2) \ SCALE_DIFFYUV (p1, p2) SCALE_(PlatInit) (); // expand updated region if necessary // pixels neighbooring the updated region may // change as a result of updates limits.x = 0; limits.y = 0; limits.w = src->w; limits.h = src->h; Scale_ExpandRect (region, 1, &limits); xend = region->x + region->w; yend = region->y + region->h; dsrc = slen - region->w; ddst = (dlen - region->w) * 2; // move ptrs to the first updated pixel src_p += slen * region->y + region->x; dst_p += (dlen * region->y + region->x) * 2; for (y = region->y; y < yend; ++y, dst_p += ddst, src_p += dsrc) { if (y > 0) prevline = -slen; else prevline = 0; if (y < h - 1) nextline = slen; else nextline = 0; // prime the (tiny) sliding-window pixel arrays pix[3] = src_p[prevline]; pix[6] = src_p[0]; pix[9] = src_p[nextline]; yuv[3] = SCALE_TOYUV (pix[3]); yuv[6] = SCALE_TOYUV (pix[6]); yuv[9] = SCALE_TOYUV (pix[9]); if (region->x > 0) { pix[2] = src_p[prevline - 1]; pix[5] = src_p[-1]; pix[8] = src_p[nextline - 1]; yuv[2] = SCALE_TOYUV (pix[2]); yuv[5] = SCALE_TOYUV (pix[5]); yuv[8] = SCALE_TOYUV (pix[8]); } else { pix[2] = pix[3]; pix[5] = pix[6]; pix[8] = pix[9]; yuv[2] = yuv[3]; yuv[5] = yuv[6]; yuv[8] = yuv[9]; } for (x = region->x; x < xend; ++x, ++src_p, dst_p += 2) { int pattern = 0; // slide the window pix[1] = pix[2]; pix[4] = pix[5]; pix[7] = pix[8]; yuv[1] = yuv[2]; yuv[4] = yuv[5]; yuv[7] = yuv[8]; pix[2] = pix[3]; pix[5] = pix[6]; pix[8] = pix[9]; yuv[2] = yuv[3]; yuv[5] = yuv[6]; yuv[8] = yuv[9]; if (x < w - 1) { pix[3] = src_p[prevline + 1]; pix[6] = src_p[1]; pix[9] = src_p[nextline + 1]; yuv[3] = SCALE_TOYUV (pix[3]); yuv[6] = SCALE_TOYUV (pix[6]); yuv[9] = SCALE_TOYUV (pix[9]); } else { pix[3] = pix[2]; pix[6] = pix[5]; pix[9] = pix[8]; yuv[3] = yuv[2]; yuv[6] = yuv[5]; yuv[9] = yuv[8]; } // this runs much faster with branching removed pattern |= HQXX_DIFFYUV (yuv[5], yuv[1]) & 0x0001; pattern |= HQXX_DIFFYUV (yuv[5], yuv[2]) & 0x0002; pattern |= HQXX_DIFFYUV (yuv[5], yuv[3]) & 0x0004; pattern |= HQXX_DIFFYUV (yuv[5], yuv[4]) & 0x0008; pattern |= HQXX_DIFFYUV (yuv[5], yuv[6]) & 0x0010; pattern |= HQXX_DIFFYUV (yuv[5], yuv[7]) & 0x0020; pattern |= HQXX_DIFFYUV (yuv[5], yuv[8]) & 0x0040; pattern |= HQXX_DIFFYUV (yuv[5], yuv[9]) & 0x0080; switch (pattern) { case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: { PIXEL00_20 PIXEL01_20 PIXEL10_20 PIXEL11_20 break; } case 2: case 34: case 130: case 162: { PIXEL00_22 PIXEL01_21 PIXEL10_20 PIXEL11_20 break; } case 16: case 17: case 48: case 49: { PIXEL00_20 PIXEL01_22 PIXEL10_20 PIXEL11_21 break; } case 64: case 65: case 68: case 69: { PIXEL00_20 PIXEL01_20 PIXEL10_21 PIXEL11_22 break; } case 8: case 12: case 136: case 140: { PIXEL00_21 PIXEL01_20 PIXEL10_22 PIXEL11_20 break; } case 3: case 35: case 131: case 163: { PIXEL00_11 PIXEL01_21 PIXEL10_20 PIXEL11_20 break; } case 6: case 38: case 134: case 166: { PIXEL00_22 PIXEL01_12 PIXEL10_20 PIXEL11_20 break; } case 20: case 21: case 52: case 53: { PIXEL00_20 PIXEL01_11 PIXEL10_20 PIXEL11_21 break; } case 144: case 145: case 176: case 177: { PIXEL00_20 PIXEL01_22 PIXEL10_20 PIXEL11_12 break; } case 192: case 193: case 196: case 197: { PIXEL00_20 PIXEL01_20 PIXEL10_21 PIXEL11_11 break; } case 96: case 97: case 100: case 101: { PIXEL00_20 PIXEL01_20 PIXEL10_12 PIXEL11_22 break; } case 40: case 44: case 168: case 172: { PIXEL00_21 PIXEL01_20 PIXEL10_11 PIXEL11_20 break; } case 9: case 13: case 137: case 141: { PIXEL00_12 PIXEL01_20 PIXEL10_22 PIXEL11_20 break; } case 18: case 50: { PIXEL00_22 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_20 } PIXEL10_20 PIXEL11_21 break; } case 80: case 81: { PIXEL00_20 PIXEL01_22 PIXEL10_21 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_20 } break; } case 72: case 76: { PIXEL00_21 PIXEL01_20 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_20 } PIXEL11_22 break; } case 10: case 138: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_20 } PIXEL01_21 PIXEL10_22 PIXEL11_20 break; } case 66: { PIXEL00_22 PIXEL01_21 PIXEL10_21 PIXEL11_22 break; } case 24: { PIXEL00_21 PIXEL01_22 PIXEL10_22 PIXEL11_21 break; } case 7: case 39: case 135: { PIXEL00_11 PIXEL01_12 PIXEL10_20 PIXEL11_20 break; } case 148: case 149: case 180: { PIXEL00_20 PIXEL01_11 PIXEL10_20 PIXEL11_12 break; } case 224: case 228: case 225: { PIXEL00_20 PIXEL01_20 PIXEL10_12 PIXEL11_11 break; } case 41: case 169: case 45: { PIXEL00_12 PIXEL01_20 PIXEL10_11 PIXEL11_20 break; } case 22: case 54: { PIXEL00_22 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_20 PIXEL11_21 break; } case 208: case 209: { PIXEL00_20 PIXEL01_22 PIXEL10_21 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 104: case 108: { PIXEL00_21 PIXEL01_20 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_22 break; } case 11: case 139: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_21 PIXEL10_22 PIXEL11_20 break; } case 19: case 51: { if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL00_11 PIXEL01_10 } else { PIXEL00_60 PIXEL01_90 } PIXEL10_20 PIXEL11_21 break; } case 146: case 178: { PIXEL00_22 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 PIXEL11_12 } else { PIXEL01_90 PIXEL11_61 } PIXEL10_20 break; } case 84: case 85: { PIXEL00_20 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL01_11 PIXEL11_10 } else { PIXEL01_60 PIXEL11_90 } PIXEL10_21 break; } case 112: case 113: { PIXEL00_20 PIXEL01_22 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL10_12 PIXEL11_10 } else { PIXEL10_61 PIXEL11_90 } break; } case 200: case 204: { PIXEL00_21 PIXEL01_20 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 PIXEL11_11 } else { PIXEL10_90 PIXEL11_60 } break; } case 73: case 77: { if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL00_12 PIXEL10_10 } else { PIXEL00_61 PIXEL10_90 } PIXEL01_20 PIXEL11_22 break; } case 42: case 170: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 PIXEL10_11 } else { PIXEL00_90 PIXEL10_60 } PIXEL01_21 PIXEL11_20 break; } case 14: case 142: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 PIXEL01_12 } else { PIXEL00_90 PIXEL01_61 } PIXEL10_22 PIXEL11_20 break; } case 67: { PIXEL00_11 PIXEL01_21 PIXEL10_21 PIXEL11_22 break; } case 70: { PIXEL00_22 PIXEL01_12 PIXEL10_21 PIXEL11_22 break; } case 28: { PIXEL00_21 PIXEL01_11 PIXEL10_22 PIXEL11_21 break; } case 152: { PIXEL00_21 PIXEL01_22 PIXEL10_22 PIXEL11_12 break; } case 194: { PIXEL00_22 PIXEL01_21 PIXEL10_21 PIXEL11_11 break; } case 98: { PIXEL00_22 PIXEL01_21 PIXEL10_12 PIXEL11_22 break; } case 56: { PIXEL00_21 PIXEL01_22 PIXEL10_11 PIXEL11_21 break; } case 25: { PIXEL00_12 PIXEL01_22 PIXEL10_22 PIXEL11_21 break; } case 26: case 31: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_22 PIXEL11_21 break; } case 82: case 214: { PIXEL00_22 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_21 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 88: case 248: { PIXEL00_21 PIXEL01_22 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 74: case 107: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_21 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_22 break; } case 27: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_10 PIXEL10_22 PIXEL11_21 break; } case 86: { PIXEL00_22 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_21 PIXEL11_10 break; } case 216: { PIXEL00_21 PIXEL01_22 PIXEL10_10 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 106: { PIXEL00_10 PIXEL01_21 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_22 break; } case 30: { PIXEL00_10 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_22 PIXEL11_21 break; } case 210: { PIXEL00_22 PIXEL01_10 PIXEL10_21 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 120: { PIXEL00_21 PIXEL01_22 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_10 break; } case 75: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_21 PIXEL10_10 PIXEL11_22 break; } case 29: { PIXEL00_12 PIXEL01_11 PIXEL10_22 PIXEL11_21 break; } case 198: { PIXEL00_22 PIXEL01_12 PIXEL10_21 PIXEL11_11 break; } case 184: { PIXEL00_21 PIXEL01_22 PIXEL10_11 PIXEL11_12 break; } case 99: { PIXEL00_11 PIXEL01_21 PIXEL10_12 PIXEL11_22 break; } case 57: { PIXEL00_12 PIXEL01_22 PIXEL10_11 PIXEL11_21 break; } case 71: { PIXEL00_11 PIXEL01_12 PIXEL10_21 PIXEL11_22 break; } case 156: { PIXEL00_21 PIXEL01_11 PIXEL10_22 PIXEL11_12 break; } case 226: { PIXEL00_22 PIXEL01_21 PIXEL10_12 PIXEL11_11 break; } case 60: { PIXEL00_21 PIXEL01_11 PIXEL10_11 PIXEL11_21 break; } case 195: { PIXEL00_11 PIXEL01_21 PIXEL10_21 PIXEL11_11 break; } case 102: { PIXEL00_22 PIXEL01_12 PIXEL10_12 PIXEL11_22 break; } case 153: { PIXEL00_12 PIXEL01_22 PIXEL10_22 PIXEL11_12 break; } case 58: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_11 PIXEL11_21 break; } case 83: { PIXEL00_11 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_21 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 92: { PIXEL00_21 PIXEL01_11 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 202: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } PIXEL01_21 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } PIXEL11_11 break; } case 78: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } PIXEL01_12 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } PIXEL11_22 break; } case 154: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_22 PIXEL11_12 break; } case 114: { PIXEL00_22 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_12 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 89: { PIXEL00_12 PIXEL01_22 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 90: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 55: case 23: { if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL00_11 PIXEL01_0 } else { PIXEL00_60 PIXEL01_90 } PIXEL10_20 PIXEL11_21 break; } case 182: case 150: { PIXEL00_22 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 PIXEL11_12 } else { PIXEL01_90 PIXEL11_61 } PIXEL10_20 break; } case 213: case 212: { PIXEL00_20 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL01_11 PIXEL11_0 } else { PIXEL01_60 PIXEL11_90 } PIXEL10_21 break; } case 241: case 240: { PIXEL00_20 PIXEL01_22 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL10_12 PIXEL11_0 } else { PIXEL10_61 PIXEL11_90 } break; } case 236: case 232: { PIXEL00_21 PIXEL01_20 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 PIXEL11_11 } else { PIXEL10_90 PIXEL11_60 } break; } case 109: case 105: { if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL00_12 PIXEL10_0 } else { PIXEL00_61 PIXEL10_90 } PIXEL01_20 PIXEL11_22 break; } case 171: case 43: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 PIXEL10_11 } else { PIXEL00_90 PIXEL10_60 } PIXEL01_21 PIXEL11_20 break; } case 143: case 15: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 PIXEL01_12 } else { PIXEL00_90 PIXEL01_61 } PIXEL10_22 PIXEL11_20 break; } case 124: { PIXEL00_21 PIXEL01_11 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_10 break; } case 203: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_21 PIXEL10_10 PIXEL11_11 break; } case 62: { PIXEL00_10 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_11 PIXEL11_21 break; } case 211: { PIXEL00_11 PIXEL01_10 PIXEL10_21 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 118: { PIXEL00_22 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_12 PIXEL11_10 break; } case 217: { PIXEL00_12 PIXEL01_22 PIXEL10_10 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 110: { PIXEL00_10 PIXEL01_12 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_22 break; } case 155: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_10 PIXEL10_22 PIXEL11_12 break; } case 188: { PIXEL00_21 PIXEL01_11 PIXEL10_11 PIXEL11_12 break; } case 185: { PIXEL00_12 PIXEL01_22 PIXEL10_11 PIXEL11_12 break; } case 61: { PIXEL00_12 PIXEL01_11 PIXEL10_11 PIXEL11_21 break; } case 157: { PIXEL00_12 PIXEL01_11 PIXEL10_22 PIXEL11_12 break; } case 103: { PIXEL00_11 PIXEL01_12 PIXEL10_12 PIXEL11_22 break; } case 227: { PIXEL00_11 PIXEL01_21 PIXEL10_12 PIXEL11_11 break; } case 230: { PIXEL00_22 PIXEL01_12 PIXEL10_12 PIXEL11_11 break; } case 199: { PIXEL00_11 PIXEL01_12 PIXEL10_21 PIXEL11_11 break; } case 220: { PIXEL00_21 PIXEL01_11 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 158: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_22 PIXEL11_12 break; } case 234: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } PIXEL01_21 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_11 break; } case 242: { PIXEL00_22 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_12 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 59: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_11 PIXEL11_21 break; } case 121: { PIXEL00_12 PIXEL01_22 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 87: { PIXEL00_11 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_21 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 79: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_12 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } PIXEL11_22 break; } case 122: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 94: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 218: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 91: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 229: { PIXEL00_20 PIXEL01_20 PIXEL10_12 PIXEL11_11 break; } case 167: { PIXEL00_11 PIXEL01_12 PIXEL10_20 PIXEL11_20 break; } case 173: { PIXEL00_12 PIXEL01_20 PIXEL10_11 PIXEL11_20 break; } case 181: { PIXEL00_20 PIXEL01_11 PIXEL10_20 PIXEL11_12 break; } case 186: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_11 PIXEL11_12 break; } case 115: { PIXEL00_11 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_12 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 93: { PIXEL00_12 PIXEL01_11 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 206: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } PIXEL01_12 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } PIXEL11_11 break; } case 205: case 201: { PIXEL00_12 PIXEL01_20 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_10 } else { PIXEL10_70 } PIXEL11_11 break; } case 174: case 46: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_10 } else { PIXEL00_70 } PIXEL01_12 PIXEL10_11 PIXEL11_20 break; } case 179: case 147: { PIXEL00_11 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_20 PIXEL11_12 break; } case 117: case 116: { PIXEL00_20 PIXEL01_11 PIXEL10_12 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 189: { PIXEL00_12 PIXEL01_11 PIXEL10_11 PIXEL11_12 break; } case 231: { PIXEL00_11 PIXEL01_12 PIXEL10_12 PIXEL11_11 break; } case 126: { PIXEL00_10 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_10 break; } case 219: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_10 PIXEL10_10 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 125: { if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL00_12 PIXEL10_0 } else { PIXEL00_61 PIXEL10_90 } PIXEL01_11 PIXEL11_10 break; } case 221: { PIXEL00_12 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL01_11 PIXEL11_0 } else { PIXEL01_60 PIXEL11_90 } PIXEL10_10 break; } case 207: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 PIXEL01_12 } else { PIXEL00_90 PIXEL01_61 } PIXEL10_10 PIXEL11_11 break; } case 238: { PIXEL00_10 PIXEL01_12 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 PIXEL11_11 } else { PIXEL10_90 PIXEL11_60 } break; } case 190: { PIXEL00_10 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 PIXEL11_12 } else { PIXEL01_90 PIXEL11_61 } PIXEL10_11 break; } case 187: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 PIXEL10_11 } else { PIXEL00_90 PIXEL10_60 } PIXEL01_10 PIXEL11_12 break; } case 243: { PIXEL00_11 PIXEL01_10 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL10_12 PIXEL11_0 } else { PIXEL10_61 PIXEL11_90 } break; } case 119: { if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL00_11 PIXEL01_0 } else { PIXEL00_60 PIXEL01_90 } PIXEL10_12 PIXEL11_10 break; } case 237: case 233: { PIXEL00_12 PIXEL01_20 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_100 } PIXEL11_11 break; } case 175: case 47: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_100 } PIXEL01_12 PIXEL10_11 PIXEL11_20 break; } case 183: case 151: { PIXEL00_11 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_20 PIXEL11_12 break; } case 245: case 244: { PIXEL00_20 PIXEL01_11 PIXEL10_12 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 250: { PIXEL00_10 PIXEL01_10 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 123: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_10 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_10 break; } case 95: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_10 PIXEL11_10 break; } case 222: { PIXEL00_10 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_10 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 252: { PIXEL00_21 PIXEL01_11 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 249: { PIXEL00_12 PIXEL01_22 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_100 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 235: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_21 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_100 } PIXEL11_11 break; } case 111: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_100 } PIXEL01_12 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_22 break; } case 63: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_100 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_11 PIXEL11_21 break; } case 159: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_22 PIXEL11_12 break; } case 215: { PIXEL00_11 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_21 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 246: { PIXEL00_22 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_12 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 254: { PIXEL00_10 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 253: { PIXEL00_12 PIXEL01_11 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_100 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 251: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_10 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_100 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 239: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_100 } PIXEL01_12 if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_100 } PIXEL11_11 break; } case 127: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_100 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_20 } if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_10 break; } case 191: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_100 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_11 PIXEL11_12 break; } case 223: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_20 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_10 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 247: { PIXEL00_11 if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_12 if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 255: { if (HQXX_DIFFYUV (yuv[4], yuv[2])) { PIXEL00_0 } else { PIXEL00_100 } if (HQXX_DIFFYUV (yuv[2], yuv[6])) { PIXEL01_0 } else { PIXEL01_100 } if (HQXX_DIFFYUV (yuv[8], yuv[4])) { PIXEL10_0 } else { PIXEL10_100 } if (HQXX_DIFFYUV (yuv[6], yuv[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } } } } SCALE_(PlatDone) (); } #endif /* GFXMODULE_SDL */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/sdl_common.c0000644000175000017500000005165410552135701021442 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "sdl_common.h" #include "opengl.h" #include "pure.h" #include "primitives.h" #include "dcqueue.h" #include "options.h" #include "uqmversion.h" #include "libs/graphics/drawcmd.h" #include "libs/input/sdl/vcontrol.h" #include "bbox.h" #include "port.h" #include "libs/uio.h" #include "libs/log.h" #include "controls.h" // XXX: Should not be included from here. #include "uqmdebug.h" #include SDL_INCLUDE(SDL_thread.h) SDL_Surface *SDL_Video; SDL_Surface *SDL_Screen; SDL_Surface *TransitionScreen; SDL_Surface *SDL_Screens[TFB_GFX_NUMSCREENS]; SDL_Surface *format_conv_surf = NULL; volatile int TransitionAmount = 255; SDL_Rect TransitionClipRect; static volatile BOOLEAN abortFlag = FALSE; int GfxFlags = 0; static TFB_Palette palette[256]; TFB_GRAPHICS_BACKEND *graphics_backend = NULL; #define FPS_PERIOD 100 int RenderedFrames = 0; void TFB_Abort (void) { abortFlag = TRUE; } void TFB_PreInit (void) { log_add (log_Info, "Initializing base SDL functionality."); log_add (log_Info, "Using SDL version %d.%d.%d (compiled with " "%d.%d.%d)", SDL_Linked_Version ()->major, SDL_Linked_Version ()->minor, SDL_Linked_Version ()->patch, SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL); if ((SDL_Init (SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) == -1)) { log_add (log_Fatal, "Could not initialize SDL: %s.", SDL_GetError()); exit (EXIT_FAILURE); } } int TFB_ReInitGraphics (int driver, int flags, int width, int height) { int result; char caption[200]; GfxFlags = flags; if (driver == TFB_GFXDRIVER_SDL_OPENGL) { #ifdef HAVE_OPENGL result = TFB_GL_ConfigureVideo (driver, flags, width, height); #else driver = TFB_GFXDRIVER_SDL_PURE; log_add (log_Warning, "OpenGL support not compiled in," " so using pure SDL driver"); result = TFB_Pure_ConfigureVideo (driver, flags, width, height); #endif } else { result = TFB_Pure_ConfigureVideo (driver, flags, width, height); } sprintf (caption, "The Ur-Quan Masters v%d.%d.%d%s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION); SDL_WM_SetCaption (caption, NULL); if (flags & TFB_GFXFLAGS_FULLSCREEN) SDL_ShowCursor (SDL_DISABLE); else SDL_ShowCursor (SDL_ENABLE); return result; } int TFB_InitGraphics (int driver, int flags, int width, int height) { int result, i; char caption[200]; /* Null out screen pointers the first time */ for (i = 0; i < TFB_GFX_NUMSCREENS; i++) { SDL_Screens[i] = NULL; } GfxFlags = flags; if (driver == TFB_GFXDRIVER_SDL_OPENGL) { #ifdef HAVE_OPENGL result = TFB_GL_InitGraphics (driver, flags, width, height); #else driver = TFB_GFXDRIVER_SDL_PURE; log_add (log_Warning, "OpenGL support not compiled in," " so using pure SDL driver"); result = TFB_Pure_InitGraphics (driver, flags, width, height); #endif } else { result = TFB_Pure_InitGraphics (driver, flags, width, height); } sprintf (caption, "The Ur-Quan Masters v%d.%d.%d%s", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION); SDL_WM_SetCaption (caption, NULL); if (flags & TFB_GFXFLAGS_FULLSCREEN) SDL_ShowCursor (SDL_DISABLE); Init_DrawCommandQueue (); TFB_DrawCanvas_Initialize (); RenderingCond = CreateCondVar ("DCQ empty", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); atexit (TFB_UninitGraphics); return 0; } void TFB_UninitGraphics (void) { Uninit_DrawCommandQueue (); SDL_Quit (); } void TFB_ProcessEvents () { SDL_Event Event; while (SDL_PollEvent (&Event)) { /* Run through the InputEvent filter. */ ProcessInputEvent (&Event); /* Handle Graphics events. */ switch (Event.type) { case SDL_ACTIVEEVENT: /* Loose/gain visibility */ // TODO break; case SDL_QUIT: log_showBox (false, false); exit (EXIT_SUCCESS); break; case SDL_VIDEORESIZE: /* User resized video mode */ // TODO break; case SDL_VIDEOEXPOSE: /* Screen needs to be redrawn */ TFB_SwapBuffers (1); break; default: break; } } if (ImmediateInputState.menu[KEY_ABORT] || abortFlag) { log_showBox (false, false); exit (EXIT_SUCCESS); } #if defined(DEBUG) || defined(USE_DEBUG_KEY) if (ImmediateInputState.menu[KEY_DEBUG]) { FlushInput (); debugKeyPressed (); } #endif /* DEBUG */ } static BOOLEAN system_box_active = 0; static SDL_Rect system_box; void SetSystemRect (PRECT r) { system_box_active = TRUE; system_box.x = r->corner.x; system_box.y = r->corner.y; system_box.w = r->extent.width; system_box.h = r->extent.height; } void ClearSystemRect (void) { system_box_active = FALSE; } void TFB_SwapBuffers (int force_full_redraw) { static int last_fade_amount = 255, last_transition_amount = 255; static int fade_amount = 255, transition_amount = 255; fade_amount = FadeAmount; transition_amount = TransitionAmount; if (!force_full_redraw && !TFB_BBox.valid && fade_amount == 255 && transition_amount == 255 && last_fade_amount == 255 && last_transition_amount == 255) return; if (fade_amount != 255 || transition_amount != 255 || last_fade_amount != 255 || last_transition_amount != 255) { force_full_redraw = 1; } last_fade_amount = fade_amount; last_transition_amount = transition_amount; graphics_backend->preprocess (force_full_redraw, transition_amount, fade_amount); graphics_backend->screen (TFB_SCREEN_MAIN, 255, NULL); if (transition_amount != 255) { graphics_backend->screen (TFB_SCREEN_TRANSITION, 255 - transition_amount, &TransitionClipRect); } if (fade_amount != 255) { if (fade_amount < 255) { graphics_backend->color (0, 0, 0, 255 - fade_amount, NULL); } else { graphics_backend->color (255, 255, 255, fade_amount - 255, NULL); } } if (system_box_active) { graphics_backend->screen (TFB_SCREEN_MAIN, 255, &system_box); } graphics_backend->postprocess (); } /* Probably ought to clean this away at some point. */ SDL_Surface* TFB_DisplayFormatAlpha (SDL_Surface *surface) { SDL_Surface* newsurf; SDL_PixelFormat* dstfmt; const SDL_PixelFormat* srcfmt = surface->format; // figure out what format to use (alpha/no alpha) if (surface->format->Amask) dstfmt = format_conv_surf->format; else dstfmt = SDL_Screen->format; if (srcfmt->BytesPerPixel == dstfmt->BytesPerPixel && srcfmt->Rmask == dstfmt->Rmask && srcfmt->Gmask == dstfmt->Gmask && srcfmt->Bmask == dstfmt->Bmask && srcfmt->Amask == dstfmt->Amask) return surface; // no conversion needed newsurf = SDL_ConvertSurface (surface, dstfmt, surface->flags); // SDL_SRCCOLORKEY and SDL_SRCALPHA cannot work at the same time, // so we need to disable one of them if ((surface->flags & SDL_SRCCOLORKEY) && newsurf && (newsurf->flags & SDL_SRCCOLORKEY) && (newsurf->flags & SDL_SRCALPHA)) SDL_SetAlpha (newsurf, 0, 255); return newsurf; } void TFB_BlitSurface (SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, int blend_numer, int blend_denom) { BOOLEAN has_colorkey; int x, y, x1, y1, x2, y2, dst_x2, dst_y2, nr, ng, nb; int srcx, srcy, w, h; Uint8 sr, sg, sb, dr, dg, db; Uint32 src_pixval, dst_pixval, colorkey; GetPixelFn src_getpix, dst_getpix; PutPixelFn putpix; SDL_Rect fulldst; if (blend_numer == blend_denom) { // normal blit: dst = src // log_add (log_Debug, "normal blit\n"); SDL_BlitSurface (src, srcrect, dst, dstrect); return; } // NOTE: following clipping code is copied from SDL-1.2.4 sources // If the destination rectangle is NULL, use the entire dest surface if (dstrect == NULL) { fulldst.x = fulldst.y = 0; dstrect = &fulldst; } // clip the source rectangle to the source surface if (srcrect) { int maxw, maxh; srcx = srcrect->x; w = srcrect->w; if(srcx < 0) { w += srcx; dstrect->x -= srcx; srcx = 0; } maxw = src->w - srcx; if(maxw < w) w = maxw; srcy = srcrect->y; h = srcrect->h; if(srcy < 0) { h += srcy; dstrect->y -= srcy; srcy = 0; } maxh = src->h - srcy; if(maxh < h) h = maxh; } else { srcx = srcy = 0; w = src->w; h = src->h; } // clip the destination rectangle against the clip rectangle { SDL_Rect *clip = &dst->clip_rect; int dx, dy; dx = clip->x - dstrect->x; if(dx > 0) { w -= dx; dstrect->x += dx; srcx += dx; } dx = dstrect->x + w - clip->x - clip->w; if(dx > 0) w -= dx; dy = clip->y - dstrect->y; if(dy > 0) { h -= dy; dstrect->y += dy; srcy += dy; } dy = dstrect->y + h - clip->y - clip->h; if(dy > 0) h -= dy; } dstrect->w = w; dstrect->h = h; if (w <= 0 || h <= 0) return; x1 = srcx; y1 = srcy; x2 = srcx + w; y2 = srcy + h; if (src->flags & SDL_SRCCOLORKEY) { has_colorkey = TRUE; colorkey = src->format->colorkey; } else { has_colorkey = FALSE; } src_getpix = getpixel_for (src); dst_getpix = getpixel_for (dst); putpix = putpixel_for (dst); if (blend_denom < 0) { // additive blit: dst = src + dst #if 0 log_add (log_Debug, "additive blit %d %d, src %d %d %d %d dst %d %d," " srcbpp %d", blend_numer, blend_denom, x1, y1, x2, y2, dstrect->x, dstrect->y, src->format->BitsPerPixel); #endif for (y = y1; y < y2; ++y) { dst_y2 = dstrect->y + (y - y1); for (x = x1; x < x2; ++x) { dst_x2 = dstrect->x + (x - x1); src_pixval = src_getpix (src, x, y); if (has_colorkey && src_pixval == colorkey) continue; dst_pixval = dst_getpix (dst, dst_x2, dst_y2); SDL_GetRGB (src_pixval, src->format, &sr, &sg, &sb); SDL_GetRGB (dst_pixval, dst->format, &dr, &dg, &db); nr = sr + dr; ng = sg + dg; nb = sb + db; if (nr > 255) nr = 255; if (ng > 255) ng = 255; if (nb > 255) nb = 255; putpix (dst, dst_x2, dst_y2, SDL_MapRGB (dst->format, nr, ng, nb)); } } } else if (blend_numer < 0) { // subtractive blit: dst = src - dst #if 0 log_add (log_Debug, "subtractive blit %d %d, src %d %d %d %d" " dst %d %d, srcbpp %d", blend_numer, blend_denom, x1, y1, x2, y2, dstrect->x, dstrect->y, src->format->BitsPerPixel); #endif for (y = y1; y < y2; ++y) { dst_y2 = dstrect->y + (y - y1); for (x = x1; x < x2; ++x) { dst_x2 = dstrect->x + (x - x1); src_pixval = src_getpix (src, x, y); if (has_colorkey && src_pixval == colorkey) continue; dst_pixval = dst_getpix (dst, dst_x2, dst_y2); SDL_GetRGB (src_pixval, src->format, &sr, &sg, &sb); SDL_GetRGB (dst_pixval, dst->format, &dr, &dg, &db); nr = sr - dr; ng = sg - dg; nb = sb - db; if (nr < 0) nr = 0; if (ng < 0) ng = 0; if (nb < 0) nb = 0; putpix (dst, dst_x2, dst_y2, SDL_MapRGB (dst->format, nr, ng, nb)); } } } else { // modulated blit: dst = src * (blend_numer / blend_denom) float f = blend_numer / (float)blend_denom; #if 0 log_add (log_Debug, "modulated blit %d %d, f %f, src %d %d %d %d" " dst %d %d, srcbpp %d\n", blend_numer, blend_denom, f, x1, y1, x2, y2, dstrect->x, dstrect->y, src->format->BitsPerPixel); #endif for (y = y1; y < y2; ++y) { dst_y2 = dstrect->y + (y - y1); for (x = x1; x < x2; ++x) { dst_x2 = dstrect->x + (x - x1); src_pixval = src_getpix (src, x, y); if (has_colorkey && src_pixval == colorkey) continue; SDL_GetRGB (src_pixval, src->format, &sr, &sg, &sb); nr = (int)(sr * f); ng = (int)(sg * f); nb = (int)(sb * f); if (nr > 255) nr = 255; if (ng > 255) ng = 255; if (nb > 255) nb = 255; putpix (dst, dst_x2, dst_y2, SDL_MapRGB (dst->format, nr, ng, nb)); } } } } void TFB_ComputeFPS (void) { static Uint32 last_time = 0, fps_counter = 0; Uint32 current_time, delta_time; current_time = SDL_GetTicks (); delta_time = current_time - last_time; last_time = current_time; fps_counter += delta_time; if (fps_counter > FPS_PERIOD) { log_add (log_User, "fps %.2f, effective %.2f", 1000.0 / delta_time, 1000.0 * RenderedFrames / fps_counter); fps_counter = 0; RenderedFrames = 0; } } void TFB_FlushGraphics () // Only call from main thread!! { int commands_handled; BOOLEAN livelock_deterrence; BOOLEAN done; // This is technically a locking violation on DrawCommandQueue.Size, // but it is likely to not be very destructive. if (DrawCommandQueue.Size == 0) { static int last_fade = 255; static int last_transition = 255; int current_fade = FadeAmount; int current_transition = TransitionAmount; if ((current_fade != 255 && current_fade != last_fade) || (current_transition != 255 && current_transition != last_transition) || (current_fade == 255 && last_fade != 255) || (current_transition == 255 && last_transition != 255)) { TFB_SwapBuffers (1); // if fading, redraw every frame } else { TaskSwitch (); } last_fade = current_fade; last_transition = current_transition; BroadcastCondVar (RenderingCond); return; } if (GfxFlags & TFB_GFXFLAGS_SHOWFPS) TFB_ComputeFPS (); commands_handled = 0; livelock_deterrence = FALSE; if (DrawCommandQueue.FullSize > DCQ_FORCE_BREAK_SIZE) { TFB_BatchReset (); } if (DrawCommandQueue.Size > DCQ_FORCE_SLOWDOWN_SIZE) { Lock_DCQ (-1); livelock_deterrence = TRUE; } TFB_BBox_Reset (); TFB_BBox_GetClipRect (SDL_Screens[0]); done = FALSE; while (!done) { TFB_DrawCommand DC; if (!TFB_DrawCommandQueue_Pop (&DC)) { // the Queue is now empty. break; } ++commands_handled; if (!livelock_deterrence && commands_handled + DrawCommandQueue.Size > DCQ_LIVELOCK_MAX) { // log_add (log_Debug, "Initiating livelock deterrence!"); livelock_deterrence = TRUE; Lock_DCQ (-1); } switch (DC.Type) { case TFB_DRAWCOMMANDTYPE_SETPALETTE: { int index = DC.data.setpalette.index; if (index < 0 || index > 255) { log_add (log_Debug, "DCQ panic: Tried to set palette #%i", index); } else { palette[index].r = DC.data.setpalette.r & 0xFF; palette[index].g = DC.data.setpalette.g & 0xFF; palette[index].b = DC.data.setpalette.b & 0xFF; } break; } case TFB_DRAWCOMMANDTYPE_SETMIPMAP: LockMutex (DC.data.setmipmap.image->mutex); DC.data.setmipmap.image->MipmapImg = DC.data.setmipmap.mipmap; DC.data.setmipmap.image->MipmapHs.x = DC.data.setmipmap.hotx; DC.data.setmipmap.image->MipmapHs.y = DC.data.setmipmap.hoty; UnlockMutex (DC.data.setmipmap.image->mutex); break; case TFB_DRAWCOMMANDTYPE_IMAGE: { TFB_Image *DC_image = DC.data.image.image; TFB_ColorMap *cmap = DC.data.image.colormap; int x = DC.data.image.x; int y = DC.data.image.y; TFB_DrawCanvas_Image (DC_image, x, y, DC.data.image.scale, cmap, SDL_Screens[DC.data.image.destBuffer]); if (DC.data.image.destBuffer == 0) { LockMutex (DC_image->mutex); if (DC.data.image.scale) TFB_BBox_RegisterCanvas (DC_image->ScaledImg, x - DC_image->last_scale_hs.x, y - DC_image->last_scale_hs.y); else TFB_BBox_RegisterCanvas (DC_image->NormalImg, x - DC_image->NormalHs.x, y - DC_image->NormalHs.y); UnlockMutex (DC_image->mutex); } break; } case TFB_DRAWCOMMANDTYPE_FILLEDIMAGE: { TFB_Image *DC_image = DC.data.filledimage.image; int x = DC.data.filledimage.x; int y = DC.data.filledimage.y; TFB_DrawCanvas_FilledImage (DC.data.filledimage.image, DC.data.filledimage.x, DC.data.filledimage.y, DC.data.filledimage.scale, DC.data.filledimage.r, DC.data.filledimage.g, DC.data.filledimage.b, SDL_Screens[DC.data.filledimage.destBuffer]); if (DC.data.filledimage.destBuffer == 0) { LockMutex (DC_image->mutex); if (DC.data.filledimage.scale) TFB_BBox_RegisterCanvas (DC_image->ScaledImg, x - DC_image->last_scale_hs.x, y - DC_image->last_scale_hs.y); else TFB_BBox_RegisterCanvas (DC_image->NormalImg, x - DC_image->NormalHs.x, y - DC_image->NormalHs.y); UnlockMutex (DC_image->mutex); } break; } case TFB_DRAWCOMMANDTYPE_FONTCHAR: { TFB_Char *DC_char = DC.data.fontchar.fontchar; int x = DC.data.fontchar.x; int y = DC.data.fontchar.y; TFB_DrawCanvas_FontChar (DC.data.fontchar.fontchar, DC.data.fontchar.backing, DC.data.fontchar.x, DC.data.fontchar.y, SDL_Screens[DC.data.fontchar.destBuffer]); if (DC.data.fontchar.destBuffer == 0) { RECT r; r.corner.x = x - DC_char->HotSpot.x; r.corner.y = y - DC_char->HotSpot.y; r.extent.width = DC_char->extent.width; r.extent.height = DC_char->extent.height; TFB_BBox_RegisterRect (&r); } break; } case TFB_DRAWCOMMANDTYPE_LINE: { if (DC.data.line.destBuffer == 0) { TFB_BBox_RegisterPoint (DC.data.line.x1, DC.data.line.y1); TFB_BBox_RegisterPoint (DC.data.line.x2, DC.data.line.y2); } TFB_DrawCanvas_Line (DC.data.line.x1, DC.data.line.y1, DC.data.line.x2, DC.data.line.y2, DC.data.line.r, DC.data.line.g, DC.data.line.b, SDL_Screens[DC.data.line.destBuffer]); break; } case TFB_DRAWCOMMANDTYPE_RECTANGLE: { if (DC.data.rect.destBuffer == 0) TFB_BBox_RegisterRect (&DC.data.rect.rect); TFB_DrawCanvas_Rect (&DC.data.rect.rect, DC.data.rect.r, DC.data.rect.g, DC.data.rect.b, SDL_Screens[DC.data.rect.destBuffer]); break; } case TFB_DRAWCOMMANDTYPE_SCISSORENABLE: { SDL_Rect r; r.x = TFB_BBox.clip.corner.x = DC.data.scissor.x; r.y = TFB_BBox.clip.corner.y = DC.data.scissor.y; r.w = TFB_BBox.clip.extent.width = DC.data.scissor.w; r.h = TFB_BBox.clip.extent.height = DC.data.scissor.h; SDL_SetClipRect(SDL_Screens[0], &r); break; } case TFB_DRAWCOMMANDTYPE_SCISSORDISABLE: SDL_SetClipRect(SDL_Screens[0], NULL); TFB_BBox.clip.corner.x = 0; TFB_BBox.clip.corner.y = 0; TFB_BBox.clip.extent.width = ScreenWidth; TFB_BBox.clip.extent.height = ScreenHeight; break; case TFB_DRAWCOMMANDTYPE_COPYTOIMAGE: { SDL_Rect src, dest; TFB_Image *DC_image = DC.data.copytoimage.image; if (DC_image == 0) { log_add (log_Debug, "DCQ ERROR: COPYTOIMAGE passed null " "image ptr"); break; } LockMutex (DC_image->mutex); src.x = dest.x = DC.data.copytoimage.x; src.y = dest.y = DC.data.copytoimage.y; src.w = DC.data.copytoimage.w; src.h = DC.data.copytoimage.h; dest.x = 0; dest.y = 0; SDL_BlitSurface(SDL_Screens[DC.data.copytoimage.srcBuffer], &src, DC_image->NormalImg, &dest); UnlockMutex (DC_image->mutex); break; } case TFB_DRAWCOMMANDTYPE_COPY: { SDL_Rect src, dest; src.x = dest.x = DC.data.copy.x; src.y = dest.y = DC.data.copy.y; src.w = DC.data.copy.w; src.h = DC.data.copy.h; if (DC.data.copy.destBuffer == 0) { TFB_BBox_RegisterPoint (src.x, src.y); TFB_BBox_RegisterPoint (src.x + src.w, src.y + src.h); } SDL_BlitSurface(SDL_Screens[DC.data.copy.srcBuffer], &src, SDL_Screens[DC.data.copy.destBuffer], &dest); break; } case TFB_DRAWCOMMANDTYPE_DELETEIMAGE: { TFB_Image *DC_image = (TFB_Image *)DC.data.deleteimage.image; TFB_DrawImage_Delete(DC_image); break; } case TFB_DRAWCOMMANDTYPE_DELETEDATA: { void *data = DC.data.deletedata.data; HFree (data); break; } case TFB_DRAWCOMMANDTYPE_SENDSIGNAL: ClearSemaphore (DC.data.sendsignal.sem); break; case TFB_DRAWCOMMANDTYPE_REINITVIDEO: { int oldDriver = GraphicsDriver; if (TFB_ReInitGraphics (DC.data.reinitvideo.driver, DC.data.reinitvideo.flags, DC.data.reinitvideo.width, DC.data.reinitvideo.height)) { log_add (log_Error, "Could not provide requested mode: " "reverting to last known driver."); if (TFB_ReInitGraphics (oldDriver, DC.data.reinitvideo.flags, DC.data.reinitvideo.width, DC.data.reinitvideo.height)) { log_add (log_Fatal, "Couldn't reinit at that point either." " Your video has been somehow tied in knots."); exit (EXIT_FAILURE); } } break; } } } if (livelock_deterrence) { Unlock_DCQ (); } TFB_SwapBuffers (0); RenderedFrames++; BroadcastCondVar (RenderingCond); } void TFB_SetGamma (float gamma) { if (SDL_SetGamma (gamma, gamma, gamma) == -1) { log_add (log_Warning, "Unable to set gamma correction."); } else { log_add (log_Info, "Gamma correction set to %1.4f.", gamma); } } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/Makeinfo0000600000175000017500000000043310543202052020567 0ustar joeyjoeyuqm_CFILES="3do_blt.c 3do_funcs.c 3do_getbody.c dcqueue.c opengl.c primitives.c pure.c rndzoom.c sdl_common.c scalers.c 2xscalers.c 2xscalers_mmx.c 2xscalers_sse.c 2xscalers_3dnow.c nearest2x.c bilinear2x.c biadv2x.c triscan2x.c hq2x.c canvas.c bbox.c sdluio.c rotozoom.c" uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/pure.c0000644000175000017500000002467310551324106020262 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "pure.h" #include "bbox.h" #include "scalers.h" #include "libs/log.h" static SDL_Surface *fade_color_surface = NULL; static SDL_Surface *fade_temp = NULL; static SDL_Surface *scaled_display = NULL; static TFB_ScaleFunc scaler = NULL; static Uint32 fade_color; static void TFB_Pure_Scaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount); static void TFB_Pure_Scaled_Postprocess (void); static void TFB_Pure_Unscaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount); static void TFB_Pure_Unscaled_Postprocess (void); static void TFB_Pure_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect); static void TFB_Pure_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect); static TFB_GRAPHICS_BACKEND pure_scaled_backend = { TFB_Pure_Scaled_Preprocess, TFB_Pure_Scaled_Postprocess, TFB_Pure_ScreenLayer, TFB_Pure_ColorLayer }; static TFB_GRAPHICS_BACKEND pure_unscaled_backend = { TFB_Pure_Unscaled_Preprocess, TFB_Pure_Unscaled_Postprocess, TFB_Pure_ScreenLayer, TFB_Pure_ColorLayer }; static SDL_Surface * Create_Screen (SDL_Surface *template, int w, int h) { SDL_Surface *newsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, template->format->BitsPerPixel, template->format->Rmask, template->format->Gmask, template->format->Bmask, 0); if (newsurf == 0) { log_add (log_Error, "Couldn't create screen buffers: %s", SDL_GetError()); } return newsurf; } static int ReInit_Screen (SDL_Surface **screen, SDL_Surface *template, int w, int h) { if (*screen) SDL_FreeSurface (*screen); *screen = Create_Screen (template, w, h); return *screen == 0 ? -1 : 0; } int TFB_Pure_ConfigureVideo (int driver, int flags, int width, int height) { int i, videomode_flags; SDL_Surface *temp_surf; GraphicsDriver = driver; // must use SDL_SWSURFACE, HWSURFACE doesn't work properly // with fades/scaling if (width == 320 && height == 240) { videomode_flags = SDL_SWSURFACE; ScreenWidthActual = 320; ScreenHeightActual = 240; graphics_backend = &pure_unscaled_backend; } else { videomode_flags = SDL_SWSURFACE; ScreenWidthActual = 640; ScreenHeightActual = 480; graphics_backend = &pure_scaled_backend; if (width != 640 || height != 480) log_add (log_Error, "Screen resolution of %dx%d not supported " "under pure SDL, using 640x480", width, height); } videomode_flags |= SDL_ANYFORMAT; if (flags & TFB_GFXFLAGS_FULLSCREEN) videomode_flags |= SDL_FULLSCREEN; /* We'll ask for a 32bpp frame, but it doesn't really matter, because we've set SDL_ANYFORMAT */ SDL_Video = SDL_SetVideoMode (ScreenWidthActual, ScreenHeightActual, 32, videomode_flags); if (SDL_Video == NULL) { log_add (log_Error, "Couldn't set %ix%i video mode: %s", ScreenWidthActual, ScreenHeightActual, SDL_GetError ()); return -1; } else { log_add (log_Info, "Set the resolution to: %ix%ix%i", SDL_GetVideoSurface()->w, SDL_GetVideoSurface()->h, SDL_GetVideoSurface()->format->BitsPerPixel); ScreenColorDepth = SDL_GetVideoSurface()->format->BitsPerPixel; } // Create a 32bpp surface in a compatible format which will supply // the format information to all other surfaces used in the game if (format_conv_surf) { SDL_FreeSurface (format_conv_surf); format_conv_surf = NULL; } temp_surf = SDL_CreateRGBSurface (SDL_SWSURFACE, 0, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000); if (temp_surf) { // acquire a fast compatible format from SDL format_conv_surf = SDL_DisplayFormatAlpha (temp_surf); if (!format_conv_surf || format_conv_surf->format->BitsPerPixel != 32) { // absolute fallback case format_conv_surf = SDL_CreateRGBSurface (SDL_SWSURFACE, 0, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); } SDL_FreeSurface (temp_surf); } if (!format_conv_surf) { log_add (log_Error, "Couldn't create format_conv_surf: %s", SDL_GetError()); return -1; } for (i = 0; i < TFB_GFX_NUMSCREENS; i++) { if (0 != ReInit_Screen (&SDL_Screens[i], format_conv_surf, ScreenWidth, ScreenHeight)) return -1; } SDL_Screen = SDL_Screens[0]; TransitionScreen = SDL_Screens[2]; if (0 != ReInit_Screen (&fade_color_surface, format_conv_surf, ScreenWidth, ScreenHeight)) return -1; fade_color = SDL_MapRGB (fade_color_surface->format, 0, 0, 0); SDL_FillRect (fade_color_surface, NULL, fade_color); if (0 != ReInit_Screen (&fade_temp, format_conv_surf, ScreenWidth, ScreenHeight)) return -1; if (ScreenWidthActual > ScreenWidth || ScreenHeightActual > ScreenHeight) { if (0 != ReInit_Screen (&scaled_display, format_conv_surf, ScreenWidthActual, ScreenHeightActual)) return -1; scaler = Scale_PrepPlatform (flags, SDL_Screen->format); } else { // no need to scale scaler = NULL; } return 0; } int TFB_Pure_InitGraphics (int driver, int flags, int width, int height) { char VideoName[256]; log_add (log_Info, "Initializing Pure-SDL graphics."); SDL_VideoDriverName (VideoName, sizeof (VideoName)); log_add (log_Info, "SDL driver used: %s", VideoName); // Set the environment variable SDL_VIDEODRIVER to override // For Linux: x11 (default), dga, fbcon, directfb, svgalib, // ggi, aalib // For Windows: directx (default), windib log_add (log_Info, "SDL initialized."); log_add (log_Info, "Initializing Screen."); ScreenWidth = 320; ScreenHeight = 240; if (TFB_Pure_ConfigureVideo (driver, flags, width, height)) { log_add (log_Fatal, "Could not initialize video: " "no fallback at start of program!"); exit (EXIT_FAILURE); } // Initialize scalers (let them precompute whatever) Scale_Init (); return 0; } static void ScanLines (SDL_Surface *dst, SDL_Rect *r) { const int rw = r->w * 2; const int rh = r->h * 2; SDL_PixelFormat *fmt = dst->format; const int pitch = dst->pitch; const int len = pitch / fmt->BytesPerPixel; int ddst; Uint32 *p = (Uint32 *) dst->pixels; int x, y; p += len * (r->y * 2) + (r->x * 2); ddst = len + len - rw; for (y = rh; y; y -= 2, p += ddst) { for (x = rw; x; --x, ++p) { // we ignore the lower bits as the difference // of 1 in 255 is negligible *p = ((*p >> 1) & 0x7f7f7f7f) + ((*p >> 2) & 0x3f3f3f3f); } } } static SDL_Surface *backbuffer = NULL, *scalebuffer = NULL; static SDL_Rect updated; static void TFB_Pure_Scaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount) { if (force_full_redraw) { updated.x = updated.y = 0; updated.w = ScreenWidth; updated.h = ScreenHeight; } else { updated.x = TFB_BBox.region.corner.x; updated.y = TFB_BBox.region.corner.y; updated.w = TFB_BBox.region.extent.width; updated.h = TFB_BBox.region.extent.height; } if (transition_amount == 255 && fade_amount == 255) backbuffer = SDL_Screens[TFB_SCREEN_MAIN]; else backbuffer = fade_temp; // we can scale directly onto SDL_Video if video is compatible if (SDL_Video->format->BitsPerPixel == SDL_Screen->format->BitsPerPixel) scalebuffer = SDL_Video; else scalebuffer = scaled_display; } static void TFB_Pure_Unscaled_Preprocess (int force_full_redraw, int transition_amount, int fade_amount) { if (force_full_redraw) { updated.x = updated.y = 0; updated.w = ScreenWidth; updated.h = ScreenHeight; } else { updated.x = TFB_BBox.region.corner.x; updated.y = TFB_BBox.region.corner.y; updated.w = TFB_BBox.region.extent.width; updated.h = TFB_BBox.region.extent.height; } backbuffer = SDL_Video; (void)transition_amount; (void)fade_amount; } static void TFB_Pure_Scaled_Postprocess (void) { SDL_LockSurface (scalebuffer); SDL_LockSurface (backbuffer); if (scaler) scaler (backbuffer, scalebuffer, &updated); if (GfxFlags & TFB_GFXFLAGS_SCANLINES) ScanLines (scalebuffer, &updated); SDL_UnlockSurface (backbuffer); SDL_UnlockSurface (scalebuffer); updated.x *= 2; updated.y *= 2; updated.w *= 2; updated.h *= 2; if (scalebuffer != SDL_Video) SDL_BlitSurface (scalebuffer, &updated, SDL_Video, &updated); SDL_UpdateRects (SDL_Video, 1, &updated); } static void TFB_Pure_Unscaled_Postprocess (void) { SDL_UpdateRect (SDL_Video, updated.x, updated.y, updated.w, updated.h); } static void TFB_Pure_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect) { if (SDL_Screens[screen] == backbuffer) return; SDL_SetAlpha (SDL_Screens[screen], SDL_SRCALPHA, a); SDL_BlitSurface (SDL_Screens[screen], rect, backbuffer, rect); } static void TFB_Pure_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect) { Uint32 col = SDL_MapRGB (fade_color_surface->format, r, g, b); if (col != fade_color) { fade_color = col; SDL_FillRect (fade_color_surface, NULL, fade_color); } SDL_SetAlpha (fade_color_surface, SDL_SRCALPHA, a); SDL_BlitSurface (fade_color_surface, rect, backbuffer, rect); } void Scale_PerfTest (void) { DWORD TimeStart, TimeIn, Now; SDL_Rect updated = {0, 0, ScreenWidth, ScreenHeight}; int i; if (!scaler) { log_add (log_Error, "No scaler configured! " "Run with larger resolution, please"); return; } if (!scaled_display) { log_add (log_Error, "Run scaler performance tests " "in Pure mode, please"); return; } SDL_LockSurface (SDL_Screen); SDL_LockSurface (scaled_display); TimeStart = TimeIn = SDL_GetTicks (); for (i = 1; i < 1001; ++i) // run for 1000 frames { scaler (SDL_Screen, scaled_display, &updated); if (GfxFlags & TFB_GFXFLAGS_SCANLINES) ScanLines (scaled_display, &updated); if (i % 100 == 0) { Now = SDL_GetTicks (); log_add (log_Debug, "%03d(%04u) ", 100*1000 / (Now - TimeIn), Now - TimeIn); TimeIn = Now; } } log_add (log_Debug, "Full frames scaled: %d; over %u ms; %d fps\n", (i - 1), Now - TimeStart, i * 1000 / (Now - TimeStart)); SDL_UnlockSurface (scaled_display); SDL_UnlockSurface (SDL_Screen); } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/opengl.c0000644000175000017500000003212410551324106020561 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if defined (GFXMODULE_SDL) && defined (HAVE_OPENGL) #include "libs/graphics/sdl/opengl.h" #include "bbox.h" #include "scalers.h" #include "libs/log.h" typedef struct _gl_screeninfo { SDL_Surface *scaled; GLuint texture; BOOLEAN dirty, active; SDL_Rect updated; } TFB_GL_SCREENINFO; static TFB_GL_SCREENINFO GL_Screens[TFB_GFX_NUMSCREENS]; static int ScreenFilterMode; static TFB_ScaleFunc scaler = NULL; static BOOLEAN first_init = TRUE; #if SDL_BYTEORDER == SDL_BIG_ENDIAN #define R_MASK 0xff000000 #define G_MASK 0x00ff0000 #define B_MASK 0x0000ff00 #define A_MASK 0x000000ff #else #define R_MASK 0x000000ff #define G_MASK 0x0000ff00 #define B_MASK 0x00ff0000 #define A_MASK 0xff000000 #endif static void TFB_GL_Preprocess (int force_full_redraw, int transition_amount, int fade_amount); static void TFB_GL_Postprocess (void); static void TFB_GL_Scaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect); static void TFB_GL_Unscaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect); static void TFB_GL_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect); static TFB_GRAPHICS_BACKEND opengl_scaled_backend = { TFB_GL_Preprocess, TFB_GL_Postprocess, TFB_GL_Scaled_ScreenLayer, TFB_GL_ColorLayer }; static TFB_GRAPHICS_BACKEND opengl_unscaled_backend = { TFB_GL_Preprocess, TFB_GL_Postprocess, TFB_GL_Unscaled_ScreenLayer, TFB_GL_ColorLayer }; static SDL_Surface * Create_Screen (SDL_Surface *template, int w, int h) { SDL_Surface *newsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, template->format->BitsPerPixel, template->format->Rmask, template->format->Gmask, template->format->Bmask, 0); if (newsurf == 0) { log_add (log_Error, "Couldn't create screen buffers: %s", SDL_GetError()); } return newsurf; } static int ReInit_Screen (SDL_Surface **screen, SDL_Surface *template, int w, int h) { if (*screen) SDL_FreeSurface (*screen); *screen = Create_Screen (template, w, h); return *screen == 0 ? -1 : 0; } static int AttemptColorDepth (int flags, int width, int height, int bpp) { int videomode_flags; ScreenColorDepth = bpp; ScreenWidthActual = width; ScreenHeightActual = height; switch (bpp) { case 15: SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5); SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5); break; case 16: SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 6); SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5); break; case 24: SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8); break; case 32: SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 8); break; default: break; } SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0); SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); videomode_flags = SDL_OPENGL; if (flags & TFB_GFXFLAGS_FULLSCREEN) videomode_flags |= SDL_FULLSCREEN; videomode_flags |= SDL_ANYFORMAT; SDL_Video = SDL_SetVideoMode (ScreenWidthActual, ScreenHeightActual, bpp, videomode_flags); if (SDL_Video == NULL) { log_add (log_Error, "Couldn't set OpenGL %ix%ix%i video mode: %s", ScreenWidthActual, ScreenHeightActual, bpp, SDL_GetError ()); return -1; } else { log_add (log_Info, "Set the resolution to: %ix%ix%i" " (surface reports %ix%ix%i)", width, height, bpp, SDL_GetVideoSurface()->w, SDL_GetVideoSurface()->h, SDL_GetVideoSurface()->format->BitsPerPixel); log_add (log_Info, "OpenGL renderer: %s version: %s", glGetString (GL_RENDERER), glGetString (GL_VERSION)); } return 0; } int TFB_GL_ConfigureVideo (int driver, int flags, int width, int height) { int i, texture_width, texture_height; GraphicsDriver = driver; if (AttemptColorDepth (flags, width, height, 32) && AttemptColorDepth (flags, width, height, 24) && AttemptColorDepth (flags, width, height, 16)) { log_add (log_Error, "Couldn't set any OpenGL %ix%i video mode!", width, height); return -1; } if (format_conv_surf) SDL_FreeSurface (format_conv_surf); format_conv_surf = SDL_CreateRGBSurface (SDL_SWSURFACE, 0, 0, 32, R_MASK, G_MASK, B_MASK, A_MASK); if (format_conv_surf == NULL) { log_add (log_Error, "Couldn't create format_conv_surf: %s", SDL_GetError()); return -1; } for (i = 0; i < TFB_GFX_NUMSCREENS; i++) { if (0 != ReInit_Screen (&SDL_Screens[i], format_conv_surf, ScreenWidth, ScreenHeight)) return -1; } SDL_Screen = SDL_Screens[0]; TransitionScreen = SDL_Screens[2]; if (first_init) { for (i = 0; i < TFB_GFX_NUMSCREENS; i++) { GL_Screens[i].scaled = NULL; GL_Screens[i].dirty = TRUE; GL_Screens[i].active = TRUE; } GL_Screens[1].active = FALSE; first_init = FALSE; } if (GfxFlags & TFB_GFXFLAGS_SCALE_SOFT_ONLY) { for (i = 0; i < TFB_GFX_NUMSCREENS; i++) { if (!GL_Screens[i].active) continue; if (0 != ReInit_Screen (&GL_Screens[i].scaled, format_conv_surf, ScreenWidth * 2, ScreenHeight * 2)) return -1; } texture_width = 1024; texture_height = 512; scaler = Scale_PrepPlatform (flags, SDL_Screen->format); graphics_backend = &opengl_scaled_backend; } else { texture_width = 512; texture_height = 256; scaler = NULL; graphics_backend = &opengl_unscaled_backend; } if (GfxFlags & TFB_GFXFLAGS_SCALE_ANY) ScreenFilterMode = GL_LINEAR; else ScreenFilterMode = GL_NEAREST; glViewport (0, 0, ScreenWidthActual, ScreenHeightActual); glClearColor (0,0,0,0); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); SDL_GL_SwapBuffers (); glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glDisable (GL_DITHER); glDepthMask(GL_FALSE); for (i = 0; i < TFB_GFX_NUMSCREENS; i++) { if (!GL_Screens[i].active) continue; glGenTextures (1, &GL_Screens[i].texture); glBindTexture (GL_TEXTURE_2D, GL_Screens[i].texture); glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, texture_width, texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); } return 0; } int TFB_GL_InitGraphics (int driver, int flags, int width, int height) { char VideoName[256]; log_add (log_Info, "Initializing SDL with OpenGL support."); SDL_VideoDriverName (VideoName, sizeof (VideoName)); log_add (log_Info, "SDL driver used: %s", VideoName); log_add (log_Info, "SDL initialized."); log_add (log_Info, "Initializing Screen."); ScreenWidth = 320; ScreenHeight = 240; if (TFB_GL_ConfigureVideo (driver, flags, width, height)) { log_add (log_Fatal, "Could not initialize video: " "no fallback at start of program!"); exit (EXIT_FAILURE); } // Initialize scalers (let them precompute whatever) Scale_Init (); return 0; } void TFB_GL_UploadTransitionScreen (void) { GL_Screens[TFB_SCREEN_TRANSITION].updated.x = 0; GL_Screens[TFB_SCREEN_TRANSITION].updated.y = 0; GL_Screens[TFB_SCREEN_TRANSITION].updated.w = ScreenWidth; GL_Screens[TFB_SCREEN_TRANSITION].updated.h = ScreenHeight; GL_Screens[TFB_SCREEN_TRANSITION].dirty = TRUE; } void TFB_GL_ScanLines (void) { int y; glDisable (GL_TEXTURE_2D); glEnable (GL_BLEND); glBlendFunc (GL_DST_COLOR, GL_ZERO); glColor3f (0.85f, 0.85f, 0.85f); for (y = 0; y < ScreenHeightActual; y += 2) { glBegin (GL_LINES); glVertex2i (0, y); glVertex2i (ScreenWidthActual, y); glEnd (); } glBlendFunc (GL_DST_COLOR, GL_ONE); glColor3f (0.2f, 0.2f, 0.2f); for (y = 1; y < ScreenHeightActual; y += 2) { glBegin (GL_LINES); glVertex2i (0, y); glVertex2i (ScreenWidthActual, y); glEnd (); } } static void TFB_GL_DrawQuad (SDL_Rect *r) { if (r != NULL) { float scale_x = (ScreenWidthActual / (float)ScreenWidth); float scale_y = (ScreenHeightActual / (float)ScreenHeight); glScissor ( (GLint) (r->x * scale_x), (GLint) ((ScreenHeight - (r->y + r->h)) * scale_y), (GLsizei) (r->w * scale_x), (GLsizei) (r->h * scale_y) ); glEnable (GL_SCISSOR_TEST); } glBegin (GL_TRIANGLE_FAN); glTexCoord2f (0, 0); glVertex2i (0, 0); glTexCoord2f (ScreenWidth / 512.0f, 0); glVertex2i (ScreenWidthActual, 0); glTexCoord2f (ScreenWidth / 512.0f, ScreenHeight / 256.0f); glVertex2i (ScreenWidthActual, ScreenHeightActual); glTexCoord2f (0, ScreenHeight / 256.0f); glVertex2i (0, ScreenHeightActual); glEnd (); if (r != NULL) { glDisable (GL_SCISSOR_TEST); } } static void TFB_GL_Preprocess (int force_full_redraw, int transition_amount, int fade_amount) { glMatrixMode (GL_PROJECTION); glLoadIdentity (); glOrtho (0,ScreenWidthActual,ScreenHeightActual, 0, -1, 1); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); (void) force_full_redraw; (void) transition_amount; (void) fade_amount; if (TFB_BBox.valid) { GL_Screens[TFB_SCREEN_MAIN].updated.x = TFB_BBox.region.corner.x; GL_Screens[TFB_SCREEN_MAIN].updated.y = TFB_BBox.region.corner.y; GL_Screens[TFB_SCREEN_MAIN].updated.w = TFB_BBox.region.extent.width; GL_Screens[TFB_SCREEN_MAIN].updated.h = TFB_BBox.region.extent.height; GL_Screens[TFB_SCREEN_MAIN].dirty = TRUE; } } static void TFB_GL_Unscaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect) { glBindTexture (GL_TEXTURE_2D, GL_Screens[screen].texture); glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (GL_Screens[screen].dirty) { glPixelStorei (GL_UNPACK_ROW_LENGTH, ScreenWidth); /* Matrox OpenGL drivers do not handle GL_UNPACK_SKIP_* correctly */ glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); SDL_LockSurface (SDL_Screens[screen]); glTexSubImage2D (GL_TEXTURE_2D, 0, GL_Screens[screen].updated.x, GL_Screens[screen].updated.y, GL_Screens[screen].updated.w, GL_Screens[screen].updated.h, GL_RGBA, GL_UNSIGNED_BYTE, (Uint32 *)SDL_Screens[screen]->pixels + (GL_Screens[screen].updated.y * ScreenWidth + GL_Screens[screen].updated.x)); SDL_UnlockSurface (SDL_Screens[screen]); GL_Screens[screen].dirty = FALSE; } glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ScreenFilterMode); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ScreenFilterMode); glEnable (GL_TEXTURE_2D); if (a == 255) { glDisable (GL_BLEND); glColor4f (1, 1, 1, 1); } else { float a_f = a / 255.0f; glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_BLEND); glColor4f (1, 1, 1, a_f); } TFB_GL_DrawQuad (rect); } static void TFB_GL_Scaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect) { glBindTexture (GL_TEXTURE_2D, GL_Screens[screen].texture); glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (GL_Screens[screen].dirty) { scaler (SDL_Screens[screen], GL_Screens[screen].scaled, &GL_Screens[screen].updated); glPixelStorei (GL_UNPACK_ROW_LENGTH, ScreenWidth * 2); /* Matrox OpenGL drivers do not handle GL_UNPACK_SKIP_* correctly */ glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); SDL_LockSurface (GL_Screens[screen].scaled); glTexSubImage2D (GL_TEXTURE_2D, 0, GL_Screens[screen].updated.x * 2, GL_Screens[screen].updated.y * 2, GL_Screens[screen].updated.w * 2, GL_Screens[screen].updated.h * 2, GL_RGBA, GL_UNSIGNED_BYTE, (Uint32 *)GL_Screens[screen].scaled->pixels + (GL_Screens[screen].updated.y * 4 * ScreenWidth + GL_Screens[screen].updated.x * 2)); SDL_UnlockSurface (GL_Screens[screen].scaled); GL_Screens[screen].dirty = FALSE; } glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ScreenFilterMode); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ScreenFilterMode); glEnable (GL_TEXTURE_2D); if (a == 255) { glDisable (GL_BLEND); glColor4f (1, 1, 1, 1); } else { float a_f = a / 255.0f; glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_BLEND); glColor4f (1, 1, 1, a_f); } TFB_GL_DrawQuad (rect); } static void TFB_GL_ColorLayer (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect) { float r_f = r / 255.0f; float g_f = g / 255.0f; float b_f = b / 255.0f; float a_f = a / 255.0f; glColor4f(r_f, g_f, b_f, a_f); glDisable (GL_TEXTURE_2D); if (a != 255) { glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_BLEND); } else { glDisable (GL_BLEND); } TFB_GL_DrawQuad (rect); } static void TFB_GL_Postprocess (void) { if (GfxFlags & TFB_GFXFLAGS_SCANLINES) TFB_GL_ScanLines (); SDL_GL_SwapBuffers (); } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/sdl_common.h0000644000175000017500000000422710551324106021437 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SDL_COMMON_H #define SDL_COMMON_H #include "port.h" #include SDL_INCLUDE(SDL.h) #include SDL_INCLUDE(SDL_byteorder.h) #include SDL_IMAGE_INCLUDE(SDL_image.h) #include "libs/graphics/gfxintrn.h" #include "libs/graphics/tfb_draw.h" #include "libs/input/inpintrn.h" #include "libs/graphics/gfx_common.h" #include "libs/input/sdl/input.h" #include "libs/threadlib.h" // The Graphics Backend vtable typedef struct _tfb_graphics_backend { void (*preprocess) (int force_redraw, int transition_amount, int fade_amount); void (*postprocess) (void); void (*screen) (SCREEN screen, Uint8 alpha, SDL_Rect *rect); void (*color) (Uint8 r, Uint8 g, Uint8 b, Uint8 a, SDL_Rect *rect); } TFB_GRAPHICS_BACKEND; extern TFB_GRAPHICS_BACKEND *graphics_backend; // constants for TFB_InitGraphics extern SDL_Surface *SDL_Video; extern SDL_Surface *SDL_Screen; extern SDL_Surface *TransitionScreen; extern SDL_Surface *SDL_Screens[TFB_GFX_NUMSCREENS]; extern SDL_Surface *format_conv_surf; extern volatile int TransitionAmount; extern SDL_Rect TransitionClipRect; void ScreenOrigin (FRAME Display, COORD sx, COORD sy); void LoadDisplay (PDISPLAY_INTERFACE *pDisplay); void TFB_SwapBuffers (int force_full_redraw); SDL_Surface* TFB_DisplayFormatAlpha (SDL_Surface *surface); void TFB_BlitSurface (SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, int blend_numer, int blend_denom); #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/2xscalers_sse.c0000644000175000017500000000514210552135701022057 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "port.h" #include "libs/platform.h" #if defined(MMX_ASM) #include "libs/graphics/sdl/sdl_common.h" #include "types.h" #include "scalers.h" #include "scaleint.h" #include "2xscalers.h" #include "2xscalers_mmx.h" // SSE name for all functions #undef SCALE_ #define SCALE_(name) Scale ## _SSE_ ## name // Tell them which opcodes we want to support #define USE_MOVNTQ #define USE_PREFETCH INTEL_PREFETCH #define USE_PSADBW // Bring in inline asm functions #include "scalemmx.h" // Scaler function lookup table // const Scale_FuncDef_t Scale_SSE_Functions[] = { {TFB_GFXFLAGS_SCALE_BILINEAR, Scale_SSE_BilinearFilter}, {TFB_GFXFLAGS_SCALE_BIADAPT, Scale_BiAdaptFilter}, {TFB_GFXFLAGS_SCALE_BIADAPTADV, Scale_SSE_BiAdaptAdvFilter}, {TFB_GFXFLAGS_SCALE_TRISCAN, Scale_SSE_TriScanFilter}, {TFB_GFXFLAGS_SCALE_HQXX, Scale_MMX_HqFilter}, // Default {0, Scale_SSE_Nearest} }; void Scale_SSE_PrepPlatform (const SDL_PixelFormat* fmt) { Scale_MMX_PrepPlatform (fmt); } // Nearest Neighbor scaling to 2x // void Scale_SSE_Nearest (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "nearest2x.c" // Bilinear scaling to 2x // void Scale_SSE_BilinearFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "bilinear2x.c" // Advanced Biadapt scaling to 2x // void Scale_SSE_BiAdaptAdvFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "biadv2x.c" // Triscan scaling to 2x // derivative of scale2x -- scale2x.sf.net // void Scale_SSE_TriScanFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "triscan2x.c" #if 0 && NO_IMPROVEMENT // Hq2x scaling // (adapted from 'hq2x' by Maxim Stepin -- www.hiend3d.com/hq2x.html) // void Scale_SSE_HqFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "hq2x.c" #endif #endif /* MMX_ASM */ #endif /* GFXMODULE_SDL */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/2xscalers_3dnow.c0000644000175000017500000000521610552135701022321 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef GFXMODULE_SDL #include "port.h" #include "libs/platform.h" #if defined(MMX_ASM) #include "libs/graphics/sdl/sdl_common.h" #include "types.h" #include "scalers.h" #include "scaleint.h" #include "2xscalers.h" #include "2xscalers_mmx.h" // 3DNow! name for all functions #undef SCALE_ #define SCALE_(name) Scale ## _3DNow_ ## name // Tell them which opcodes we want to support #undef USE_MOVNTQ #define USE_PREFETCH AMD_PREFETCH #undef USE_PSADBW // Bring in inline asm functions #include "scalemmx.h" // Scaler function lookup table // const Scale_FuncDef_t Scale_3DNow_Functions[] = { {TFB_GFXFLAGS_SCALE_BILINEAR, Scale_3DNow_BilinearFilter}, {TFB_GFXFLAGS_SCALE_BIADAPT, Scale_BiAdaptFilter}, {TFB_GFXFLAGS_SCALE_BIADAPTADV, Scale_MMX_BiAdaptAdvFilter}, {TFB_GFXFLAGS_SCALE_TRISCAN, Scale_MMX_TriScanFilter}, {TFB_GFXFLAGS_SCALE_HQXX, Scale_MMX_HqFilter}, // Default {0, Scale_3DNow_Nearest} }; void Scale_3DNow_PrepPlatform (const SDL_PixelFormat* fmt) { Scale_MMX_PrepPlatform (fmt); } // Nearest Neighbor scaling to 2x // void Scale_3DNow_Nearest (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "nearest2x.c" // Bilinear scaling to 2x // void Scale_3DNow_BilinearFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "bilinear2x.c" #if 0 && NO_IMPROVEMENT // Advanced Biadapt scaling to 2x // void Scale_3DNow_BiAdaptAdvFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "biadv2x.c" // Triscan scaling to 2x // derivative of scale2x -- scale2x.sf.net // void Scale_3DNow_TriScanFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "triscan2x.c" // Hq2x scaling // (adapted from 'hq2x' by Maxim Stepin -- www.hiend3d.com/hq2x.html) // void Scale_3DNow_HqFilter (SDL_Surface *src, // SDL_Surface *dst, SDL_Rect *r) #include "hq2x.c" #endif /* NO_IMPROVEMENT */ #endif /* MMX_ASM */ #endif /* GFXMODULE_SDL */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/sdluio.h0000600000175000017500000000230510543202053020564 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SDLUIO_H #define _SDLUIO_H #include "port.h" #include "libs/uio.h" #include SDL_INCLUDE(SDL.h) #include SDL_INCLUDE(SDL_rwops.h) SDL_Surface *sdluio_loadImage (uio_DirHandle *dir, const char *fileName); int sdluio_seek (SDL_RWops *context, int offset, int whence); int sdluio_read (SDL_RWops *context, void *ptr, int size, int maxnum); int sdluio_write (SDL_RWops *context, const void *ptr, int size, int num); int sdluio_close (SDL_RWops *context); #endif /* _SDLUIO_H */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/triscan2x.c0000644000175000017500000001030710552135701021213 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Core algorithm of the Triscan screen scaler (based on Scale2x) // (for scale2x please see http://scale2x.sf.net) // Template // When this file is built standalone is produces a plain C version // Also #included by 2xscalers_mmx.c for an MMX version #ifdef GFXMODULE_SDL #include "libs/graphics/sdl/sdl_common.h" #include "types.h" #include "scalers.h" #include "scaleint.h" #include "2xscalers.h" // Triscan scaling to 2x // derivative of scale2x -- scale2x.sf.net // The name expands to either // Scale_TriScanFilter (for plain C) or // Scale_MMX_TriScanFilter (for MMX) // [others when platforms are added] void SCALE_(TriScanFilter) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r) { int x, y; const int w = src->w, h = src->h; int xend, yend; int dsrc, ddst; SDL_Rect *region = r; SDL_Rect limits; SDL_PixelFormat *fmt = dst->format; const int sp = src->pitch, dp = dst->pitch; const int bpp = fmt->BytesPerPixel; const int slen = sp / bpp, dlen = dp / bpp; // for clarity purposes, the 'pixels' array here is transposed Uint32 pixels[3][3]; Uint32 *src_p = (Uint32 *)src->pixels; Uint32 *dst_p = (Uint32 *)dst->pixels; int prevline, nextline; // these macros are for clarity; they make the current pixel (0,0) // and allow to access pixels in all directions #define PIX(x, y) (pixels[1 + (x)][1 + (y)]) #define TRISCAN_YUV_MED 100 // medium tolerance pixel comparison #define TRISCAN_CMPYUV(p1, p2) \ (PIX p1 == PIX p2 || SCALE_CMPYUV (PIX p1, PIX p2, TRISCAN_YUV_MED)) SCALE_(PlatInit) (); // expand updated region if necessary // pixels neighbooring the updated region may // change as a result of updates limits.x = 0; limits.y = 0; limits.w = src->w; limits.h = src->h; Scale_ExpandRect (region, 1, &limits); xend = region->x + region->w; yend = region->y + region->h; dsrc = slen - region->w; ddst = (dlen - region->w) * 2; // move ptrs to the first updated pixel src_p += slen * region->y + region->x; dst_p += (dlen * region->y + region->x) * 2; for (y = region->y; y < yend; ++y, dst_p += ddst, src_p += dsrc) { if (y > 0) prevline = -slen; else prevline = 0; if (y < h - 1) nextline = slen; else nextline = 0; // prime the (tiny) sliding-window pixel arrays PIX( 1, 0) = src_p[0]; if (region->x > 0) PIX( 0, 0) = src_p[-1]; else PIX( 0, 0) = PIX( 1, 0); for (x = region->x; x < xend; ++x, ++src_p, dst_p += 2) { // slide the window PIX(-1, 0) = PIX( 0, 0); PIX( 0, -1) = src_p[prevline]; PIX( 0, 0) = PIX( 1, 0); PIX( 0, 1) = src_p[nextline]; if (x < w - 1) PIX( 1, 0) = src_p[1]; else PIX( 1, 0) = PIX( 0, 0); if (!TRISCAN_CMPYUV (( 0, -1), ( 0, 1)) && !TRISCAN_CMPYUV ((-1, 0), ( 1, 0))) { if (TRISCAN_CMPYUV ((-1, 0), ( 0, -1))) dst_p[0] = Scale_Blend_11 (PIX(-1, 0), PIX(0, -1)); else dst_p[0] = PIX(0, 0); if (TRISCAN_CMPYUV (( 1, 0), ( 0, -1))) dst_p[1] = Scale_Blend_11 (PIX(1, 0), PIX(0, -1)); else dst_p[1] = PIX(0, 0); if (TRISCAN_CMPYUV ((-1, 0), ( 0, 1))) dst_p[dlen] = Scale_Blend_11 (PIX(-1, 0), PIX(0, 1)); else dst_p[dlen] = PIX(0, 0); if (TRISCAN_CMPYUV (( 1, 0), ( 0, 1))) dst_p[dlen+1] = Scale_Blend_11 (PIX(1, 0), PIX(0, 1)); else dst_p[dlen+1] = PIX(0, 0); } else { dst_p[0] = PIX(0, 0); dst_p[1] = PIX(0, 0); dst_p[dlen] = PIX(0, 0); dst_p[dlen+1] = PIX(0, 0); } } } SCALE_(PlatDone) (); } #endif /* GFXMODULE_SDL */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/rndzoom.c0000600000175000017500000003203310543202053020751 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* The adjustments are as follows: BLUR_TYPE: 0: No blur 1: A fast but very blurry convolution 2: A fast implementation of gaussian_blur with R0 = 0.8 3: Full 7x7 gaussian blur. use R0 to control how blurry to get larger R0 numbers == more blurry. RANDOM_METHOD: 0: Use standard RotoZoom without interpolation 1: Use standard RotoZoom with interpolationn 2: Choose at random from nearest neighors 3: Choose from nearest-neighbors with probability based on distance from each pixel 4: Use the 'smart' random method, which gaurantees a path of constant color from a given pixel to one of the nearest neighbors. Randomization is based on a weighted average of distance to each nearest neighbor. */ #define BLUR_TYPE 2 #define R0 0.8 #define RANDOM_METHOD 3 #ifdef GFXMODULE_SDL #ifdef WIN32 #include #endif #include #include "sdl_common.h" #include "primitives.h" #include "libs/log.h" #ifndef MAX #define MAX(x,y) ((x) < (y) ? (y) : (x)) #endif #ifndef MIN #define MIN(x,y) ((x) > (y) ? (y) : (x)) #endif #if 0 int MAX(int x, int y) { return ((x) < (y) ? (y) : (x)); } int MIN (int x, int y) { return ((x) > (y) ? (y) : (x)); } #endif void blurSurface32 (SDL_Surface *src) { typedef struct { Uint32 r, g, b; } color; GetPixelFn getpix; Uint32 *ptr; int y, x, yy, xx; Uint32 i, offset, ypos, yof; #if BLUR_TYPE == 1 #define MWID 3 #define ARRAY_SIZE 4 #define BLUR_NORM(f) MIN (255, (f) >> 2) #define BLUR_SHIFT(x,f) ((x) << shift[f]) #define NEED_ZERO_SHIFT unsigned char idx[MWID * MWID] = { 0, 1, 0, 1, 1, 1, 0, 1, 0 }; int shift[ARRAY_SIZE] = {0, 0, 1, 3}; color *blur_array[ARRAY_SIZE]; #elif BLUR_TYPE == 2 #define MWID 3 #define ARRAY_SIZE 3 #define BLUR_NORM(f) MIN (255, (f) >> 9) #define BLUR_SHIFT(x,f) ((x) * shift[f]) unsigned char idx[MWID * MWID] = { 0, 1, 0, 1, 2, 1, 0, 1, 0 }; int shift[ARRAY_SIZE] = {21, 62, 182}; color *blur_array[ARRAY_SIZE]; #elif BLUR_TYPE == 3 #define MWID 7 #define BLUR_NORM(f) MIN (255, (int)((f) / sum)) #define BLUR_SHIFT(x,f) ((Uint32)((x) * shift[f])) // array-size is the triangular number of (MWID+1)/2 #define ARRAY_SIZE ((((MWID + 1) >> 1) * (((MWID + 1) >> 1) + 1)) >> 1) float sum = 0.0; float shift[ARRAY_SIZE]; color *blur_array[ARRAY_SIZE]; unsigned char idx[MWID * MWID]; { // Build th eidx and shift arrays using the gaussian function unsigned int i, j, k = 0; unsigned int r_2; for (i = 0; i <= (MWID >> 1); i++) { for (j = 0; j <= i; j++) { r_2 = i * i + j * j; shift[k] = 1000 * (float)exp (- log (2) * r_2 / (R0 * R0)); if (i == 0 && j == 0) sum += shift[k]; else if (j == 0 || i == j) sum += 4 * shift[k]; else sum += 8 * shift[k]; y = (MWID >> 1) - i; x = (MWID >> 1) - j; idx[y * MWID + x] = k; idx[y * MWID + MWID - x - 1] = k; idx[(MWID - y - 1) * MWID + x] = k; idx[(MWID - y - 1) * MWID + MWID - x - 1] = k; idx[x * MWID + y] = k; idx[x * MWID + MWID - y - 1] = k; idx[(MWID - x - 1) * MWID + y] = k; idx[(MWID - x - 1) * MWID + MWID - y - 1] = k; k++; } } // printf ("sum is: %f\n", sum); // i = 0; // for(y = 0; y < MWID; y++) // { // for (x = 0; x< MWID; x++) // printf(" %f", shift[idx[i++]]); // printf("\n"); // } } #else #define MWID 3 #define ARRAY_SIZE 1 #define BLUR_NORM(f) MIN (255, (f) >> 2) #define BLUR_SHIFT(x,f) ((x) << shift[f]) unsigned char idx[1]; int shift[1]; color *blur_array[1]; return; #endif if (src->format->BitsPerPixel != 32) { log_add (log_Debug, "blurSurface32 requires a 32bit Surface, but surface is %d bits!\n", src->format->BitsPerPixel); return; } SDL_LockSurface (src); getpix = getpixel_for (src); // Make ARRAY_SIZE copies of the surface, each multiplied by a constant in 'shift' for(i = 0; i < ARRAY_SIZE; i++) blur_array[i] = (color *)HMalloc (sizeof(color) * (src->w + MWID - 1) * (src->h + MWID - 1)); offset = 0; ptr = src->pixels; // the blur_array matrices are larger than the target surface by MWID - 1 // this is to allow convolving to work at the image edges. // note that the convolution 'wraps' around on the x coordinate, butnot the y for (y = -(MWID >> 1); y < src->h + (MWID >> 1); y++) { for (x = - (MWID >> 1); x < src->w + (MWID >> 1); x++) { unsigned char r, g, b; Uint32 pixel; i = 0; if (x < 0) pixel = getpix (src, x + src->w, MIN (src->h - 1, MAX (0, y))); else if (x >= src->w) pixel = getpix (src, x - src->w, MIN (src->h - 1, MAX (0, y))); else if (y < 0 || y >= src->h) pixel = getpix (src, x, MIN (src->h - 1, MAX (0, y))); else pixel = *ptr++; SDL_GetRGB (pixel, src->format, &r, &g, &b); #ifdef NEED_ZERO_SHIFT blur_array[i][offset].r = 0; blur_array[i][offset].g = 0; blur_array[i][offset].b = 0; i++; #endif for (; i < ARRAY_SIZE; i++) { blur_array[i][offset].r = BLUR_SHIFT((Uint32)r,i); blur_array[i][offset].g = BLUR_SHIFT((Uint32)g,i); blur_array[i][offset].b = BLUR_SHIFT((Uint32)b,i); } offset++; } } ptr = src->pixels; ypos =0; // actually do theconvolving here. for (y = 0; y < src->h; y++, ypos += src->w + (MWID - 1)) { for (x = 0; x < src->w; x++) { Uint32 pixel; Uint32 bluroff, idxoff; color p; p.r =0; p.g =0; p.b =0; idxoff = 0; yof = ypos; for (yy = - (MWID >> 1); yy <= (MWID >> 1); yy++) { bluroff = yof + x; for (xx = - (MWID >> 1); xx <= (MWID >> 1); xx++) { p.r+=blur_array[idx[idxoff]][bluroff].r; p.g+=blur_array[idx[idxoff]][bluroff].g; p.b+=blur_array[idx[idxoff]][bluroff].b; idxoff++; bluroff++; } yof += src->w + (MWID - 1); } p.r = BLUR_NORM(p.r); p.g = BLUR_NORM(p.g); p.b = BLUR_NORM(p.b); pixel = SDL_MapRGB (src->format, (Uint8)p.r, (Uint8)p.g, (Uint8)p.b); *ptr++ = pixel; } } SDL_UnlockSurface (src); for(i = 0; i < ARRAY_SIZE; i++) HFree (blur_array[i]); } /* the rZF_nearestneighbor method fills the 'dst' image with the 'src' image (performing a 16x zoom). The interior points are generated by randomly choosing the color of one of the 4 nearest neighbors. The randomization method is either an even probability i.e 1/4, or a weighted probabliliity based on the distance from each of the neighbors */ void rZF_nearestneighbor (SDL_Surface *src, SDL_Surface *dst, int use_weight) { int x, y; Uint32 p00, p01, p10, p11; Uint32 *yptr, *y1ptr, *dstptr; UBYTE rand2; UWORD prob_even[] = {64, 128, 192}; UWORD prob_weight[] = { 256, 256, 256, 144, 178, 127, 88, 127, 215, 48, 76, 220, 144, 192, 226, 114, 165, 216, 79, 127, 206, 51, 89, 203, 88, 176, 215, 79, 158, 206, 64, 128, 192, 48, 96, 175, 48, 192, 220, 51, 165, 203, 48, 127, 175, 38, 89, 140 }; UWORD *pry = prob_weight, *pr; if (!use_weight) pr = prob_even; yptr = src->pixels; y1ptr= yptr + src->w; dstptr = dst->pixels; for (y = 0; y < dst->h; y++) { if (y) { if (!(y & 0x03)) { yptr += src->w; if (y >> 2 < src->h - 1) y1ptr += src->w; if (use_weight) pry = prob_weight; } else if (use_weight) pry += 12; } for (x = 0; x < dst->w; x++) { Uint32 p; if (! (x & 0x03)) { int x0 = x >> 2; p00 = *(yptr + x0); p01 = *(y1ptr + x0); if(x0 < src->w - 1) { p10 = *(yptr + x0 + 1); p11 = *(y1ptr + x0 + 1); } else { p10 = *yptr; p11 = *y1ptr; } if (use_weight) pr = pry; } else { if (use_weight) pr += 3; } rand2 = rand() & 0xff; if (rand2 < pr[0]) p =p00; else if (rand2 < pr[1]) p = p01; else if (rand2 < pr[2]) p = p10; else p = p11; *dstptr++ = p; } } } /* the rZF_continuous method fills the 'dst' image with the 'src' image (performing a 16x zoom). The interior points are generated by randomly choosing the color of one of the 4 nearest neighbors. However, it is gauranteed that there will bbe a path of constant color from the current pixel to the nearest-neighbor that was chosen. The randomization function is biased by the pixel's distance fromit's neighbors */ void rZF_continuous (SDL_Surface *src, SDL_Surface *dst) { int rnd[] = {192, 171, 128, 0}; GetPixelFn getpix; PutPixelFn putpix; int rand2, dx, dy; Uint32 pnew; int x, y, x1, y1; Uint32 p01, p10, p11; int rand1; getpix = getpixel_for (src); putpix = putpixel_for (dst); putpix (dst, 0, 0, getpix (src, 0, 0)); for (y = 0; y < src->h; y++) { p10 = getpix (src, 0, y); if (y == src->h - 1) p11 = getpix (src, 0, y); else p11 = getpix (src, 0, y + 1); for (y1 = 0; y1 < 4; y1++) { dy = (y << 2) + y1; rand1 = rand () & 0xff; if (rand1 < rnd[y1]) pnew = p10; else { pnew = p11; p10 = p11; } putpix (dst, 0, dy, pnew); } } for (x = 0; x < src->w; x++) { p10 = getpix (src, x, 0); if (x == src->w - 1) p11 = getpix (src, 0, 0); else p11 = getpix (src, x + 1, 0); for (x1 = 0; x1 < 4; x1++) { dx = (x << 2) + x1; rand1 = rand () & 0xff; if (rand1 < rnd[x1]) pnew = p10; else { pnew = p11; p10 = p11; } putpix (dst, dx, 0, pnew); } } for (y = 1; y <= src->h; y++) { int fromy, fromy4; if (y == src->h) fromy = y - 1; else fromy = y; fromy4 = fromy << 2; for(x = 1; x <= src->w; x++) { int fromx, fromx4; int dy1; Uint32 p00; char cpl[3][3] = {{0,0,0},{0,0,0},{0,0,0}}; if (x == src->w) fromx = 0; else fromx = x; fromx4 = fromx << 2; dx = x << 2; p00 = getpix (src, x - 1, y - 1); p10 = getpix (src, fromx, y - 1); p01 = getpix (src, x - 1, fromy); p11 = getpix (src, fromx, fromy); if (x != src->w) { for (y1 = 0; y1 < 4; y1++) { if (y == src->h && y1 == 3) continue; dy = ((y - 1) << 2) + y1 + 1; rand1 = rand () & 0xff; if (rand1 < rnd[y1]) pnew = p01; else { pnew = p11; p01 = p11; } putpix (dst, dx, dy, pnew); } } if (y != src->h) { dy = y << 2; for (x1 = 0; x1 < 3; x1++) { dx = ((x - 1) << 2) + x1 + 1; rand1 = rand () & 0xff; if (rand1 < rnd[x1]) pnew = p10; else { pnew = p11; p10 = p11; } putpix (dst, dx, dy, pnew); } } for (y1 = 0; y1 < 3; y1++) { for (x1 = 0; x1 < 3; x1++) { int dxx, dyy; if (cpl[x1][y1]) continue; dyy=dy = ((y - 1) << 2) + y1 + 1; dxx=dx = ((x - 1) << 2) + x1 + 1; rand1 = rand () & 0xff; rand2 = rand () & 0xff; if (rand1 < 128) { if (rand2 < rnd[x1]) { putpix (dst, dx, dy, getpix (dst, dx - 1, dy)); } else { p00 = getpix (dst, fromx4, dy); while (dx < x <<2) { putpix (dst, dx, dy, p00); dx++; x1++; } } } else { if (rand2 < rnd[y1]) { putpix (dst, dx, dy, getpix (dst, dx, dy - 1)); } else { p00 = getpix (dst, dx, fromy4); dy1 = y1; while (dy < y << 2) { putpix (dst, dx, dy, p00); dy++; cpl[x1][dy1] = 1; dy1++; } } } if(getpix(dst,dxx,dyy) == 0) printf ("wtf\n"); } } } } } /* perform a 16x zoom, and then apply a blur filter to the result */ void random16xZoomSurfaceRGBA (SDL_Surface *src, SDL_Surface *dst) { /* * Alloc space to completely contain the zoomed surface */ SDL_LockSurface (src); SDL_LockSurface (dst); #if RANDOM_METHOD == 0 zoomSurfaceRGBA (src, dst, 0); #elif RANDOM_METHOD == 1 zoomSurfaceRGBA (src, dst, 1); #elif RANDOM_METHOD == 2 rZF_nearestneighbor (src, dst, 0); #elif RANDOM_METHOD == 3 rZF_nearestneighbor (src, dst, 1); #else rZF_continuous(src, dst); #endif SDL_UnlockSurface (src); SDL_UnlockSurface (dst); SDL_SetAlpha(dst, SDL_SRCALPHA, 255); blurSurface32 (dst); } FRAMEPTR scale16xRandomizeFrame (FRAMEPTR NewFrame, FRAMEPTR FramePtr) { TFB_Image *origImg, *newImg; CREATE_FLAGS flags; if (NewFrame == NULL) { flags = GetFrameParentDrawable (FramePtr)->Flags; NewFrame = CaptureDrawable ( CreateDrawable (flags, GetFrameWidth (FramePtr) << 2, GetFrameHeight (FramePtr) << 2, 1)); } newImg = NewFrame->image; origImg = FramePtr->image; LockMutex (origImg->mutex); random16xZoomSurfaceRGBA (origImg->NormalImg, newImg->NormalImg); UnlockMutex (origImg->mutex); return (NewFrame); } #endif uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/scalers.h0000644000175000017500000000172710552135701020745 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef SCALERS_H_ #define SCALERS_H_ void Scale_Init (void); typedef void (* TFB_ScaleFunc) (SDL_Surface *src, SDL_Surface *dst, SDL_Rect *r); TFB_ScaleFunc Scale_PrepPlatform (int flags, const SDL_PixelFormat* fmt); #endif /* SCALERS_H_ */ uqm-0.6.2/sc2/src/sc2code/libs/graphics/sdl/rotozoom.h0000600000175000017500000000420710543202053021160 0ustar joeyjoey/* rotozoom.h - rotozoomer for 32bit or 8bit surfaces LGPL (c) A. Schiffler Note by sc2 developers: Taken from SDL_gfx library and modified, original code can be downloaded from http://www.ferzkopp.net/Software/SDL_gfx-2.0/ */ #ifndef ROTOZOOM_H #define ROTOZOOM_H #include #ifndef M_PI #define M_PI 3.141592654 #endif #include "port.h" #include SDL_INCLUDE(SDL.h) /* ---- Defines */ #define SMOOTHING_OFF 0 #define SMOOTHING_ON 1 /* ---- Structures */ typedef struct tColorRGBA { Uint8 r; Uint8 g; Uint8 b; Uint8 a; } tColorRGBA; typedef struct tColorY { Uint8 y; } tColorY; /* ---- Prototypes */ /* zoomSurfaceRGBA() Zoom the src surface into dst. The zoom amount is determined by the dimensions of src and dst */ int zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int smooth); /* rotozoomSurface() Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. 'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1 then the destination 32bit surface is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. */ SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth); int rotateSurface(SDL_Surface * src, SDL_Surface * dst, double angle, int smooth); /* Returns the size of the target surface for a rotozoomSurface() call */ void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight); /* zoomSurface() Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1 then the destination 32bit surface is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. */ SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth); /* Returns the size of the target surface for a zoomSurface() call */ void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight); #endif uqm-0.6.2/sc2/src/sc2code/libs/time/0000755000175000017500000000000010552600274015507 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/time/timecommon.h0000600000175000017500000000163510543202043020014 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Serge van den Boom, 2002-09-12 */ #ifndef _TIMECOMMON_H #define _TIMECOMMON_H #if TIMELIB == SDL #include "sdl/sdltime.h" #endif /* TIMELIB == SDL */ #endif /* _TIMECOMMON_H */ uqm-0.6.2/sc2/src/sc2code/libs/time/timecommon.c0000600000175000017500000000201310543202043017776 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Serge van den Boom, 2002-09-12 */ #include #include "libs/timelib.h" #include "timecommon.h" void InitTimeSystem (void) { NativeInitTimeSystem (); } void UnInitTimeSystem (void) { NativeUnInitTimeSystem (); } TimeCount GetTimeCounter (void) { return NativeGetTimeCounter (); } uqm-0.6.2/sc2/src/sc2code/libs/time/Makeinfo0000600000175000017500000000005410543202043017142 0ustar joeyjoeyuqm_SUBDIRS="sdl" uqm_CFILES="timecommon.c" uqm-0.6.2/sc2/src/sc2code/libs/time/sdl/0000755000175000017500000000000010552600274016271 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/time/sdl/sdltime.h0000600000175000017500000000210410543202042020057 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Serge van den Boom, 2002-09-12 */ #ifndef _SDLTIME_H #define _SDLTIME_H #include "port.h" #include SDL_INCLUDE(SDL.h) #include "../timecommon.h" #define NativeInitTimeSystem() #define NativeUnInitTimeSystem() extern Uint32 SDLWrapper_GetTimeCounter (void); #define NativeGetTimeCounter() \ SDLWrapper_GetTimeCounter () #endif /* _SDLTIME_H */ uqm-0.6.2/sc2/src/sc2code/libs/time/sdl/Makeinfo0000600000175000017500000000002710543202042017723 0ustar joeyjoeyuqm_CFILES="sdltime.c" uqm-0.6.2/sc2/src/sc2code/libs/time/sdl/sdltime.c0000600000175000017500000000206710543202042020062 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Serge van den Boom */ #include "sdltime.h" #include "libs/timelib.h" Uint32 SDLWrapper_GetTimeCounter (void) { Uint32 ticks = SDL_GetTicks (); return (ticks / 1000) * ONE_SECOND + ((ticks % 1000) * ONE_SECOND / 1000); // Use the following instead when confirming "random" lockup bugs (see #668) //return ticks * ONE_SECOND / 1000; } uqm-0.6.2/sc2/src/sc2code/libs/misc.h0000600000175000017500000000246210543202055015644 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // This file includes some misc things, previously in SDL_wrapper.h // before modularization. -Mika #ifndef MISC_H #define MISC_H #include #include #include "port.h" extern void *HMalloc (int size); extern void HFree (void *p); extern void *HCalloc (int size); extern void *HRealloc (void *p, int size); extern int TFB_DEBUG_HALT; static inline void explode (void) _NORETURN; static inline void explode (void) { #ifdef DEBUG // give debugger a chance to hook abort (); #else exit (EXIT_FAILURE); #endif } #endif uqm-0.6.2/sc2/src/sc2code/libs/mikmod/0000755000175000017500000000000010552600274016031 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/mikmod/mmio.c0000600000175000017500000002705610543202047017134 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mmio.c 2421 2006-08-19 00:36:21Z avolkov $ Portable file I/O routines ==============================================================================*/ /* The way this module works: - _mm_fopen will call the errorhandler [see mmerror.c] in addition to setting _mm_errno on exit. - _mm_iobase is for internal use. It is used by Player_LoadFP to ensure that it works properly with wad files. - _mm_read_I_* and _mm_read_M_* differ : the first is for reading data written by a little endian (intel) machine, and the second is for reading big endian (Mac, RISC, Alpha) machine data. - _mm_write functions work the same as the _mm_read functions. - _mm_read_string is for reading binary strings. It is basically the same as an fread of bytes. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #include #include //#include "mikmod.h" #include "mikmod_internals.h" #ifdef SUNOS extern int fclose(FILE *); extern int fgetc(FILE *); extern int fputc(int, FILE *); extern size_t fread(void *, size_t, size_t, FILE *); extern int fseek(FILE *, long, int); extern size_t fwrite(const void *, size_t, size_t, FILE *); #endif #define COPY_BUFSIZE 1024 /* some prototypes */ static BOOL _mm_MemReader_Eof(MREADER* reader); static BOOL _mm_MemReader_Read(MREADER* reader,void* ptr,size_t size); static int _mm_MemReader_Get(MREADER* reader); static BOOL _mm_MemReader_Seek(MREADER* reader,long offset,int whence); static long _mm_MemReader_Tell(MREADER* reader); FILE* _mm_fopen(CHAR* fname,CHAR* attrib) { FILE *fp; if(!(fp=fopen(fname,attrib))) { _mm_errno = MMERR_OPENING_FILE; if(_mm_errorhandler) _mm_errorhandler(); } return fp; } BOOL _mm_FileExists(CHAR* fname) { FILE *fp; if(!(fp=fopen(fname,"r"))) return 0; fclose(fp); return 1; } int _mm_fclose(FILE *fp) { return fclose(fp); } /* Sets the current file-position as the new iobase */ void _mm_iobase_setcur(MREADER* reader) { reader->prev_iobase=reader->iobase; /* store old value in case of revert */ reader->iobase=reader->Tell(reader); } /* Reverts to the last known iobase value. */ void _mm_iobase_revert(MREADER* reader) { reader->iobase=reader->prev_iobase; } /*========== File Reader */ typedef struct MFILEREADER { MREADER core; FILE* file; } MFILEREADER; static BOOL _mm_FileReader_Eof(MREADER* reader) { return feof(((MFILEREADER*)reader)->file); } static BOOL _mm_FileReader_Read(MREADER* reader,void* ptr,size_t size) { return !!fread(ptr,size,1,((MFILEREADER*)reader)->file); } static int _mm_FileReader_Get(MREADER* reader) { return fgetc(((MFILEREADER*)reader)->file); } static BOOL _mm_FileReader_Seek(MREADER* reader,long offset,int whence) { return fseek(((MFILEREADER*)reader)->file, (whence==SEEK_SET)?offset+reader->iobase:offset,whence); } static long _mm_FileReader_Tell(MREADER* reader) { return ftell(((MFILEREADER*)reader)->file)-reader->iobase; } MREADER *_mm_new_file_reader(FILE* fp) { MFILEREADER* reader=(MFILEREADER*)MikMod_malloc(sizeof(MFILEREADER)); if (reader) { reader->core.Eof =&_mm_FileReader_Eof; reader->core.Read=&_mm_FileReader_Read; reader->core.Get =&_mm_FileReader_Get; reader->core.Seek=&_mm_FileReader_Seek; reader->core.Tell=&_mm_FileReader_Tell; reader->file=fp; } return (MREADER*)reader; } void _mm_delete_file_reader (MREADER* reader) { if(reader) MikMod_free(reader); } /*========== File Writer */ typedef struct MFILEWRITER { MWRITER core; FILE* file; } MFILEWRITER; static BOOL _mm_FileWriter_Seek(MWRITER* writer,long offset,int whence) { return fseek(((MFILEWRITER*)writer)->file,offset,whence); } static long _mm_FileWriter_Tell(MWRITER* writer) { return ftell(((MFILEWRITER*)writer)->file); } static BOOL _mm_FileWriter_Write(MWRITER* writer,void* ptr,size_t size) { return (fwrite(ptr,size,1,((MFILEWRITER*)writer)->file)==size); } static BOOL _mm_FileWriter_Put(MWRITER* writer,int value) { return fputc(value,((MFILEWRITER*)writer)->file); } MWRITER *_mm_new_file_writer(FILE* fp) { MFILEWRITER* writer=(MFILEWRITER*)MikMod_malloc(sizeof(MFILEWRITER)); if (writer) { writer->core.Seek =&_mm_FileWriter_Seek; writer->core.Tell =&_mm_FileWriter_Tell; writer->core.Write=&_mm_FileWriter_Write; writer->core.Put =&_mm_FileWriter_Put; writer->file=fp; } return (MWRITER*) writer; } void _mm_delete_file_writer (MWRITER* writer) { if(writer) MikMod_free (writer); } /*========== Memory Reader */ typedef struct MMEMREADER { MREADER core; const void *buffer; long len; long pos; } MMEMREADER; void _mm_delete_mem_reader(MREADER* reader) { if (reader) { MikMod_free(reader); } } MREADER *_mm_new_mem_reader(const void *buffer, int len) { MMEMREADER* reader=(MMEMREADER*)MikMod_malloc(sizeof(MMEMREADER)); if (reader) { reader->core.Eof =&_mm_MemReader_Eof; reader->core.Read=&_mm_MemReader_Read; reader->core.Get =&_mm_MemReader_Get; reader->core.Seek=&_mm_MemReader_Seek; reader->core.Tell=&_mm_MemReader_Tell; reader->buffer = buffer; reader->len = len; reader->pos = 0; } return (MREADER*)reader; } static BOOL _mm_MemReader_Eof(MREADER* reader) { if (!reader) { return 1; } if ( ((MMEMREADER*)reader)->pos > ((MMEMREADER*)reader)->len ) { return 1; } return 0; } static BOOL _mm_MemReader_Read(MREADER* reader,void* ptr,size_t size) { unsigned char *d=ptr; const unsigned char *s; if (!reader) { return 0; } if (reader->Eof(reader)) { return 0; } s = ((MMEMREADER*)reader)->buffer; s += ((MMEMREADER*)reader)->pos; if ( ((MMEMREADER*)reader)->pos + (long)size > ((MMEMREADER*)reader)->len) { ((MMEMREADER*)reader)->pos = ((MMEMREADER*)reader)->len; return 0; /* not enough remaining bytes */ } ((MMEMREADER*)reader)->pos += (long)size; while (size--) { *d = *s; s++; d++; } return 1; } static int _mm_MemReader_Get(MREADER* reader) { int pos; if (reader->Eof(reader)) { return 0; } pos = ((MMEMREADER*)reader)->pos; ((MMEMREADER*)reader)->pos++; return ((unsigned char*)(((MMEMREADER*)reader)->buffer))[pos]; } static BOOL _mm_MemReader_Seek(MREADER* reader,long offset,int whence) { if (!reader) { return -1; } switch(whence) { case SEEK_CUR: ((MMEMREADER*)reader)->pos += offset; break; case SEEK_SET: ((MMEMREADER*)reader)->pos = offset; break; case SEEK_END: ((MMEMREADER*)reader)->pos = ((MMEMREADER*)reader)->len - offset - 1; break; } if ( ((MMEMREADER*)reader)->pos < 0) { ((MMEMREADER*)reader)->pos = 0; } if ( ((MMEMREADER*)reader)->pos > ((MMEMREADER*)reader)->len ) { ((MMEMREADER*)reader)->pos = ((MMEMREADER*)reader)->len; } return 0; } static long _mm_MemReader_Tell(MREADER* reader) { if (reader) { return ((MMEMREADER*)reader)->pos; } return 0; } /*========== Write functions */ void _mm_write_string(CHAR* data,MWRITER* writer) { if(data) _mm_write_UBYTES(data,strlen(data),writer); } void _mm_write_M_UWORD(UWORD data,MWRITER* writer) { _mm_write_UBYTE(data>>8,writer); _mm_write_UBYTE(data&0xff,writer); } void _mm_write_I_UWORD(UWORD data,MWRITER* writer) { _mm_write_UBYTE(data&0xff,writer); _mm_write_UBYTE(data>>8,writer); } void _mm_write_M_ULONG(ULONG data,MWRITER* writer) { _mm_write_M_UWORD(data>>16,writer); _mm_write_M_UWORD(data&0xffff,writer); } void _mm_write_I_ULONG(ULONG data,MWRITER* writer) { _mm_write_I_UWORD(data&0xffff,writer); _mm_write_I_UWORD(data>>16,writer); } void _mm_write_M_SWORD(SWORD data,MWRITER* writer) { _mm_write_M_UWORD((UWORD)data,writer); } void _mm_write_I_SWORD(SWORD data,MWRITER* writer) { _mm_write_I_UWORD((UWORD)data,writer); } void _mm_write_M_SLONG(SLONG data,MWRITER* writer) { _mm_write_M_ULONG((ULONG)data,writer); } void _mm_write_I_SLONG(SLONG data,MWRITER* writer) { _mm_write_I_ULONG((ULONG)data,writer); } #if defined __STDC__ || defined _MSC_VER || defined MPW_C #define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \ void _mm_write_##type_name##S (type *buffer,int number,MWRITER* writer) \ { \ while(number-->0) \ _mm_write_##type_name(*(buffer++),writer); \ } #else #define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \ void _mm_write_/**/type_name/**/S (type *buffer,int number,MWRITER* writer) \ { \ while(number-->0) \ _mm_write_/**/type_name(*(buffer++),writer); \ } #endif DEFINE_MULTIPLE_WRITE_FUNCTION(M_SWORD,SWORD) DEFINE_MULTIPLE_WRITE_FUNCTION(M_UWORD,UWORD) DEFINE_MULTIPLE_WRITE_FUNCTION(I_SWORD,SWORD) DEFINE_MULTIPLE_WRITE_FUNCTION(I_UWORD,UWORD) DEFINE_MULTIPLE_WRITE_FUNCTION(M_SLONG,SLONG) DEFINE_MULTIPLE_WRITE_FUNCTION(M_ULONG,ULONG) DEFINE_MULTIPLE_WRITE_FUNCTION(I_SLONG,SLONG) DEFINE_MULTIPLE_WRITE_FUNCTION(I_ULONG,ULONG) /*========== Read functions */ int _mm_read_string(CHAR* buffer,int number,MREADER* reader) { return reader->Read(reader,buffer,number); } UWORD _mm_read_M_UWORD(MREADER* reader) { UWORD result=((UWORD)_mm_read_UBYTE(reader))<<8; result|=_mm_read_UBYTE(reader); return result; } UWORD _mm_read_I_UWORD(MREADER* reader) { UWORD result=_mm_read_UBYTE(reader); result|=((UWORD)_mm_read_UBYTE(reader))<<8; return result; } ULONG _mm_read_M_ULONG(MREADER* reader) { ULONG result=((ULONG)_mm_read_M_UWORD(reader))<<16; result|=_mm_read_M_UWORD(reader); return result; } ULONG _mm_read_I_ULONG(MREADER* reader) { ULONG result=_mm_read_I_UWORD(reader); result|=((ULONG)_mm_read_I_UWORD(reader))<<16; return result; } SWORD _mm_read_M_SWORD(MREADER* reader) { return((SWORD)_mm_read_M_UWORD(reader)); } SWORD _mm_read_I_SWORD(MREADER* reader) { return((SWORD)_mm_read_I_UWORD(reader)); } SLONG _mm_read_M_SLONG(MREADER* reader) { return((SLONG)_mm_read_M_ULONG(reader)); } SLONG _mm_read_I_SLONG(MREADER* reader) { return((SLONG)_mm_read_I_ULONG(reader)); } #if defined __STDC__ || defined _MSC_VER || defined MPW_C #define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \ int _mm_read_##type_name##S (type *buffer,int number,MREADER* reader) \ { \ while(number-->0) \ *(buffer++)=_mm_read_##type_name(reader); \ return !reader->Eof(reader); \ } #else #define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \ int _mm_read_/**/type_name/**/S (type *buffer,int number,MREADER* reader) \ { \ while(number-->0) \ *(buffer++)=_mm_read_/**/type_name(reader); \ return !reader->Eof(reader); \ } #endif DEFINE_MULTIPLE_READ_FUNCTION(M_SWORD,SWORD) DEFINE_MULTIPLE_READ_FUNCTION(M_UWORD,UWORD) DEFINE_MULTIPLE_READ_FUNCTION(I_SWORD,SWORD) DEFINE_MULTIPLE_READ_FUNCTION(I_UWORD,UWORD) DEFINE_MULTIPLE_READ_FUNCTION(M_SLONG,SLONG) DEFINE_MULTIPLE_READ_FUNCTION(M_ULONG,ULONG) DEFINE_MULTIPLE_READ_FUNCTION(I_SLONG,SLONG) DEFINE_MULTIPLE_READ_FUNCTION(I_ULONG,ULONG) /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mdreg.c0000600000175000017500000000256710543202047017271 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mdreg.c 2412 2006-08-18 18:37:39Z avolkov $ Routine for registering all drivers in libmikmod for the current platform. ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mikmod_internals.h" void _mm_registeralldrivers(void) { _mm_registerdriver(&drv_nos); } void MikMod_RegisterAllDrivers(void) { MUTEX_LOCK(lists); _mm_registeralldrivers(); MUTEX_UNLOCK(lists); } /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/load_mod.c0000600000175000017500000003054410543202047017745 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: load_mod.c 2421 2006-08-19 00:36:21Z avolkov $ Generic MOD loader (Protracker, StarTracker, FastTracker, etc) ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #ifdef HAVE_MEMORY_H #include #endif #include #include "mikmod_internals.h" #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); #endif /*========== Module structure */ typedef struct MSAMPINFO { CHAR samplename[23]; /* 22 in module, 23 in memory */ UWORD length; UBYTE finetune; UBYTE volume; UWORD reppos; UWORD replen; } MSAMPINFO; typedef struct MODULEHEADER { CHAR songname[21]; /* the songname.. 20 in module, 21 in memory */ MSAMPINFO samples[31]; /* all sampleinfo */ UBYTE songlength; /* number of patterns used */ UBYTE magic1; /* should be 127 */ UBYTE positions[128]; /* which pattern to play at pos */ UBYTE magic2[4]; /* string "M.K." or "FLT4" or "FLT8" */ } MODULEHEADER; typedef struct MODTYPE { CHAR id[5]; UBYTE channels; CHAR *name; } MODTYPE; typedef struct MODNOTE { UBYTE a, b, c, d; } MODNOTE; /*========== Loader variables */ #define MODULEHEADERSIZE 0x438 static CHAR protracker[] = "Protracker"; static CHAR startrekker[] = "Startrekker"; static CHAR fasttracker[] = "Fasttracker"; static CHAR oktalyser[] = "Oktalyser"; static CHAR oktalyzer[] = "Oktalyzer"; static CHAR taketracker[] = "TakeTracker"; static CHAR orpheus[] = "Imago Orpheus (MOD format)"; static MODULEHEADER *mh = NULL; static MODNOTE *patbuf = NULL; static int modtype, trekker; /*========== Loader code */ /* given the module ID, determine the number of channels and the tracker description ; also alters modtype */ static BOOL MOD_CheckType(UBYTE *id, UBYTE *numchn, CHAR **descr) { modtype = trekker = 0; /* Protracker and variants */ if ((!memcmp(id, "M.K.", 4)) || (!memcmp(id, "M!K!", 4))) { *descr = protracker; modtype = 0; *numchn = 4; return 1; } /* Star Tracker */ if (((!memcmp(id, "FLT", 3)) || (!memcmp(id, "EXO", 3))) && (isdigit(id[3]))) { *descr = startrekker; modtype = trekker = 1; *numchn = id[3] - '0'; if (*numchn == 4 || *numchn == 8) return 1; #ifdef MIKMOD_DEBUG else fprintf(stderr, "\rUnknown FLT%d module type\n", *numchn); #endif return 0; } /* Oktalyzer (Amiga) */ if (!memcmp(id, "OKTA", 4)) { *descr = oktalyzer; modtype = 1; *numchn = 8; return 1; } /* Oktalyser (Atari) */ if (!memcmp(id, "CD81", 4)) { *descr = oktalyser; modtype = 1; *numchn = 8; return 1; } /* Fasttracker */ if ((!memcmp(id + 1, "CHN", 3)) && (isdigit(id[0]))) { *descr = fasttracker; modtype = 1; *numchn = id[0] - '0'; return 1; } /* Fasttracker or Taketracker */ if (((!memcmp(id + 2, "CH", 2)) || (!memcmp(id + 2, "CN", 2))) && (isdigit(id[0])) && (isdigit(id[1]))) { if (id[3] == 'H') { *descr = fasttracker; modtype = 2; /* this can also be Imago Orpheus */ } else { *descr = taketracker; modtype = 1; } *numchn = (id[0] - '0') * 10 + (id[1] - '0'); return 1; } return 0; } static BOOL MOD_Test(void) { UBYTE id[4], numchn; CHAR *descr; _mm_fseek(modreader, MODULEHEADERSIZE, SEEK_SET); if (!_mm_read_UBYTES(id, 4, modreader)) return 0; if (MOD_CheckType(id, &numchn, &descr)) return 1; return 0; } static BOOL MOD_Init(void) { if (!(mh = (MODULEHEADER *)MikMod_malloc(sizeof(MODULEHEADER)))) return 0; return 1; } static void MOD_Cleanup(void) { MikMod_free(mh); MikMod_free(patbuf); } /* Old (amiga) noteinfo: _____byte 1_____ byte2_ _____byte 3_____ byte4_ / \ / \ / \ / \ 0000 0000-00000000 0000 0000-00000000 Upper four 12 bits for Lower four Effect command. bits of sam- note period. bits of sam- ple number. ple number. */ static UBYTE ConvertNote(MODNOTE *n, UBYTE lasteffect) { UBYTE instrument, effect, effdat, note; UWORD period; UBYTE lastnote = 0; /* extract the various information from the 4 bytes that make up a note */ instrument = (n->a & 0x10) | (n->c >> 4); period = (((UWORD)n->a & 0xf) << 8) + n->b; effect = n->c & 0xf; effdat = n->d; /* Convert the period to a note number */ note = 0; if (period) { for (note = 0; note < 7 * OCTAVE; note++) if (period >= npertab[note]) break; if (note == 7 * OCTAVE) note = 0; else note++; } if (instrument) { /* if instrument does not exist, note cut */ if ((instrument > 31) || (!mh->samples[instrument - 1].length)) { UniPTEffect(0xc, 0); if (effect == 0xc) effect = effdat = 0; } else { /* Protracker handling */ if (!modtype) { /* if we had a note, then change instrument... */ if (note) UniInstrument(instrument - 1); /* ...otherwise, only adjust volume... */ else { /* ...unless an effect was specified, which forces a new note to be played */ if (effect || effdat) { UniInstrument(instrument - 1); note = lastnote; } else UniPTEffect(0xc, mh->samples[instrument - 1].volume & 0x7f); } } else { /* Fasttracker handling */ UniInstrument(instrument - 1); if (!note) note = lastnote; } } } if (note) { UniNote(note + 2 * OCTAVE - 1); lastnote = note; } /* Convert pattern jump from Dec to Hex */ if (effect == 0xd) effdat = (((effdat & 0xf0) >> 4) * 10) + (effdat & 0xf); /* Volume slide, up has priority */ if ((effect == 0xa) && (effdat & 0xf) && (effdat & 0xf0)) effdat &= 0xf0; /* Handle ``heavy'' volumes correctly */ if ((effect == 0xc) && (effdat > 0x40)) effdat = 0x40; /* An isolated 100, 200 or 300 effect should be ignored (no "standalone" porta memory in mod files). However, a sequence such as 1XX, 100, 100, 100 is fine. */ if ((!effdat) && ((effect == 1)||(effect == 2)||(effect ==3)) && (lasteffect < 0x10) && (effect != lasteffect)) effect = 0; UniPTEffect(effect, effdat); if (effect == 8) of.flags |= UF_PANNING; return effect; } static UBYTE *ConvertTrack(MODNOTE *n, int numchn) { int t; UBYTE lasteffect = 0x10; /* non existant effect */ UniReset(); for (t = 0; t < 64; t++) { lasteffect = ConvertNote(n,lasteffect); UniNewline(); n += numchn; } return UniDup(); } /* Loads all patterns of a modfile and converts them into the 3 byte format. */ static BOOL ML_LoadPatterns(void) { int t, s, tracks = 0; if (!AllocPatterns()) return 0; if (!AllocTracks()) return 0; /* Allocate temporary buffer for loading and converting the patterns */ if (!(patbuf = (MODNOTE *)MikMod_calloc(64U * of.numchn, sizeof(MODNOTE)))) return 0; if (trekker && of.numchn == 8) { /* Startrekker module dual pattern */ for (t = 0; t < of.numpat; t++) { for (s = 0; s < (64 * 4); s++) { patbuf[s].a = _mm_read_UBYTE(modreader); patbuf[s].b = _mm_read_UBYTE(modreader); patbuf[s].c = _mm_read_UBYTE(modreader); patbuf[s].d = _mm_read_UBYTE(modreader); } for (s = 0; s < 4; s++) if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s, 4))) return 0; for (s = 0; s < (64 * 4); s++) { patbuf[s].a = _mm_read_UBYTE(modreader); patbuf[s].b = _mm_read_UBYTE(modreader); patbuf[s].c = _mm_read_UBYTE(modreader); patbuf[s].d = _mm_read_UBYTE(modreader); } for (s = 0; s < 4; s++) if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s, 4))) return 0; } } else { /* Generic module pattern */ for (t = 0; t < of.numpat; t++) { /* Load the pattern into the temp buffer and convert it */ for (s = 0; s < (64 * of.numchn); s++) { patbuf[s].a = _mm_read_UBYTE(modreader); patbuf[s].b = _mm_read_UBYTE(modreader); patbuf[s].c = _mm_read_UBYTE(modreader); patbuf[s].d = _mm_read_UBYTE(modreader); } for (s = 0; s < of.numchn; s++) if (!(of.tracks[tracks++] = ConvertTrack(patbuf + s, of.numchn))) return 0; } } return 1; } static BOOL MOD_Load(BOOL curious) { int t, scan; SAMPLE *q; MSAMPINFO *s; CHAR *descr; /* try to read module header */ _mm_read_string((CHAR *)mh->songname, 20, modreader); mh->songname[20] = 0; /* just in case */ for (t = 0; t < 31; t++) { s = &mh->samples[t]; _mm_read_string(s->samplename, 22, modreader); s->samplename[22] = 0; /* just in case */ s->length = _mm_read_M_UWORD(modreader); s->finetune = _mm_read_UBYTE(modreader); s->volume = _mm_read_UBYTE(modreader); s->reppos = _mm_read_M_UWORD(modreader); s->replen = _mm_read_M_UWORD(modreader); } mh->songlength = _mm_read_UBYTE(modreader); /* this fixes mods which declare more than 128 positions. * eg: beatwave.mod */ if (mh->songlength > 128) { mh->songlength = 128; } mh->magic1 = _mm_read_UBYTE(modreader); _mm_read_UBYTES(mh->positions, 128, modreader); _mm_read_UBYTES(mh->magic2, 4, modreader); if (_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } /* set module variables */ of.initspeed = 6; of.inittempo = 125; if (!(MOD_CheckType(mh->magic2, &of.numchn, &descr))) { _mm_errno = MMERR_NOT_A_MODULE; return 0; } if (trekker && of.numchn == 8) for (t = 0; t < 128; t++) /* if module pretends to be FLT8, yet the order table contains odd numbers, chances are it's a lying FLT4... */ if (mh->positions[t] & 1) { of.numchn = 4; break; } if (trekker && of.numchn == 8) for (t = 0; t < 128; t++) mh->positions[t] >>= 1; of.songname = DupStr(mh->songname, 21, 1); of.numpos = mh->songlength; of.reppos = 0; /* Count the number of patterns */ of.numpat = 0; for (t = 0; t < of.numpos; t++) if (mh->positions[t] > of.numpat) of.numpat = mh->positions[t]; /* since some old modules embed extra patterns, we have to check the whole list to get the samples' file offsets right - however we can find garbage here, so check carefully */ scan = 1; for (t = of.numpos; t < 128; t++) if (mh->positions[t] >= 0x80) scan = 0; if (scan) for (t = of.numpos; t < 128; t++) { if (mh->positions[t] > of.numpat) of.numpat = mh->positions[t]; if ((curious) && (mh->positions[t])) of.numpos = t + 1; } of.numpat++; of.numtrk = of.numpat * of.numchn; if (!AllocPositions(of.numpos)) return 0; for (t = 0; t < of.numpos; t++) of.positions[t] = mh->positions[t]; /* Finally, init the sampleinfo structures */ of.numins = of.numsmp = 31; if (!AllocSamples()) return 0; s = mh->samples; q = of.samples; for (t = 0; t < of.numins; t++) { /* convert the samplename */ q->samplename = DupStr(s->samplename, 23, 1); /* init the sampleinfo variables and convert the size pointers */ q->speed = finetune[s->finetune & 0xf]; q->volume = s->volume & 0x7f; q->loopstart = (ULONG)s->reppos << 1; q->loopend = q->loopstart + ((ULONG)s->replen << 1); q->length = (ULONG)s->length << 1; q->flags = SF_SIGNED; /* Imago Orpheus creates MODs with 16 bit samples, check */ if ((modtype == 2) && (s->volume & 0x80)) { q->flags |= SF_16BITS; descr = orpheus; } if (s->replen > 2) q->flags |= SF_LOOP; s++; q++; } of.modtype = strdup(descr); if (!ML_LoadPatterns()) return 0; return 1; } static CHAR *MOD_LoadTitle(void) { CHAR s[21]; _mm_fseek(modreader, 0, SEEK_SET); if (!_mm_read_UBYTES(s, 20, modreader)) return NULL; s[20] = 0; /* just in case */ return (DupStr(s, 21, 1)); } /*========== Loader information */ MIKMODAPI MLOADER load_mod = { NULL, "Standard module", "MOD (31 instruments)", MOD_Init, MOD_Test, MOD_Load, MOD_Cleanup, MOD_LoadTitle }; /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mdriver.c0000600000175000017500000005053010543202047017634 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mdriver.c 2412 2006-08-18 18:37:39Z avolkov $ These routines are used to access the available soundcard drivers. ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #if defined unix || (defined __APPLE__ && defined __MACH__) #include #include #endif #include #ifdef HAVE_STRINGS_H #include #endif #include "mikmod_internals.h" #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); #endif static MDRIVER *firstdriver=NULL; MIKMODAPI MDRIVER *md_driver=NULL; extern MODULE *pf; /* modfile being played */ /* Initial global settings */ MIKMODAPI UWORD md_device = 0; /* autodetect */ MIKMODAPI UWORD md_mixfreq = 44100; MIKMODAPI UWORD md_mode = DMODE_STEREO | DMODE_16BITS | DMODE_SURROUND |DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX; MIKMODAPI UBYTE md_pansep = 128; /* 128 == 100% (full left/right) */ MIKMODAPI UBYTE md_reverb = 0; /* no reverb */ MIKMODAPI UBYTE md_volume = 128; /* global sound volume (0-128) */ MIKMODAPI UBYTE md_musicvolume = 128; /* volume of song */ MIKMODAPI UBYTE md_sndfxvolume = 128; /* volume of sound effects */ UWORD md_bpm = 125; /* tempo */ /* Do not modify the numchn variables yourself! use MD_SetVoices() */ UBYTE md_numchn=0,md_sngchn=0,md_sfxchn=0; UBYTE md_hardchn=0,md_softchn=0; void (*md_player)(void) = Player_HandleTick; static BOOL isplaying=0, initialized = 0; static UBYTE *sfxinfo; static int sfxpool; static SAMPLE **md_sample = NULL; /* Previous driver in use */ static SWORD olddevice = -1; /* Limits the number of hardware voices to the specified amount. This function should only be used by the low-level drivers. */ static void LimitHardVoices(int limit) { int t=0; if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>limit)) md_sfxchn=limit; if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>limit)) md_sngchn=limit; if (!(md_mode & DMODE_SOFT_SNDFX)) md_hardchn=md_sfxchn; else md_hardchn=0; if (!(md_mode & DMODE_SOFT_MUSIC)) md_hardchn += md_sngchn; while (md_hardchn>limit) { if (++t & 1) { if (!(md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>4)) md_sfxchn--; } else { if (!(md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>8)) md_sngchn--; } if (!(md_mode & DMODE_SOFT_SNDFX)) md_hardchn=md_sfxchn; else md_hardchn=0; if (!(md_mode & DMODE_SOFT_MUSIC)) md_hardchn+=md_sngchn; } md_numchn=md_hardchn+md_softchn; } /* Limits the number of hardware voices to the specified amount. This function should only be used by the low-level drivers. */ static void LimitSoftVoices(int limit) { int t=0; if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>limit)) md_sfxchn=limit; if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>limit)) md_sngchn=limit; if (md_mode & DMODE_SOFT_SNDFX) md_softchn=md_sfxchn; else md_softchn=0; if (md_mode & DMODE_SOFT_MUSIC) md_softchn+=md_sngchn; while (md_softchn>limit) { if (++t & 1) { if ((md_mode & DMODE_SOFT_SNDFX) && (md_sfxchn>4)) md_sfxchn--; } else { if ((md_mode & DMODE_SOFT_MUSIC) && (md_sngchn>8)) md_sngchn--; } if (!(md_mode & DMODE_SOFT_SNDFX)) md_softchn=md_sfxchn; else md_softchn=0; if (!(md_mode & DMODE_SOFT_MUSIC)) md_softchn+=md_sngchn; } md_numchn=md_hardchn+md_softchn; } /* Note: 'type' indicates whether the returned value should be for music or for sound effects. */ ULONG MD_SampleSpace(int type) { if(type==MD_MUSIC) type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE; else if(type==MD_SNDFX) type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE; return md_driver->FreeSampleSpace(type); } ULONG MD_SampleLength(int type,SAMPLE* s) { if(type==MD_MUSIC) type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE; else if(type==MD_SNDFX) type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE; return md_driver->RealSampleLength(type,s); } MIKMODAPI CHAR* MikMod_InfoDriver(void) { int t; size_t len=0; MDRIVER *l; CHAR *list=NULL; MUTEX_LOCK(lists); /* compute size of buffer */ for(l=firstdriver;l;l=l->next) len+=4+(l->next?1:0)+strlen(l->Version); if(len) if((list=MikMod_malloc(len*sizeof(CHAR)))) { list[0]=0; /* list all registered device drivers : */ for(t=1,l=firstdriver;l;l=l->next,t++) sprintf(list,(l->next)?"%s%2d %s\n":"%s%2d %s", list,t,l->Version); } MUTEX_UNLOCK(lists); return list; } void _mm_registerdriver(struct MDRIVER* drv) { MDRIVER *cruise = firstdriver; /* don't register a MISSING() driver */ if ((drv->Name) && (drv->Version)) { if (cruise) { while (cruise->next) cruise = cruise->next; cruise->next = drv; } else firstdriver = drv; } } MIKMODAPI void MikMod_RegisterDriver(struct MDRIVER* drv) { /* if we try to register an invalid driver, or an already registered driver, ignore this attempt */ if ((!drv)||(drv->next)||(!drv->Name)) return; MUTEX_LOCK(lists); _mm_registerdriver(drv); MUTEX_UNLOCK(lists); } MIKMODAPI int MikMod_DriverFromAlias(CHAR *alias) { int rank=1; MDRIVER *cruise; MUTEX_LOCK(lists); cruise=firstdriver; while(cruise) { if (cruise->Alias) { if (!(strcasecmp(alias,cruise->Alias))) break; rank++; } cruise=cruise->next; } if(!cruise) rank=0; MUTEX_UNLOCK(lists); return rank; } SWORD MD_SampleLoad(SAMPLOAD* s, int type) { SWORD result; if(type==MD_MUSIC) type=(md_mode & DMODE_SOFT_MUSIC)?MD_SOFTWARE:MD_HARDWARE; else if(type==MD_SNDFX) type=(md_mode & DMODE_SOFT_SNDFX)?MD_SOFTWARE:MD_HARDWARE; SL_Init(s); result=md_driver->SampleLoad(s,type); SL_Exit(s); return result; } void MD_SampleUnload(SWORD handle) { md_driver->SampleUnload(handle); } MIKMODAPI MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t player) { MikMod_player_t result; MUTEX_LOCK(vars); result=md_player; md_player=player; MUTEX_UNLOCK(vars); return result; } MIKMODAPI void MikMod_Update(void) { MUTEX_LOCK(vars); if(isplaying) { if((!pf)||(!pf->forbid)) md_driver->Update(); else { if (md_driver->Pause) md_driver->Pause(); } } MUTEX_UNLOCK(vars); } void Voice_SetVolume_internal(SBYTE voice,UWORD vol) { ULONG tmp; if((voice<0)||(voice>=md_numchn)) return; /* range checks */ if(md_musicvolume>128) md_musicvolume=128; if(md_sndfxvolume>128) md_sndfxvolume=128; if(md_volume>128) md_volume=128; tmp=(ULONG)vol*(ULONG)md_volume* ((voiceVoiceSetVolume(voice,tmp/16384UL); } MIKMODAPI void Voice_SetVolume(SBYTE voice,UWORD vol) { MUTEX_LOCK(vars); Voice_SetVolume_internal(voice,vol); MUTEX_UNLOCK(vars); } MIKMODAPI UWORD Voice_GetVolume(SBYTE voice) { UWORD result=0; MUTEX_LOCK(vars); if((voice>=0)&&(voiceVoiceGetVolume(voice); MUTEX_UNLOCK(vars); return result; } void Voice_SetFrequency_internal(SBYTE voice,ULONG frq) { if((voice<0)||(voice>=md_numchn)) return; if((md_sample[voice])&&(md_sample[voice]->divfactor)) frq/=md_sample[voice]->divfactor; md_driver->VoiceSetFrequency(voice,frq); } MIKMODAPI void Voice_SetFrequency(SBYTE voice,ULONG frq) { MUTEX_LOCK(vars); Voice_SetFrequency_internal(voice,frq); MUTEX_UNLOCK(vars); } MIKMODAPI ULONG Voice_GetFrequency(SBYTE voice) { ULONG result=0; MUTEX_LOCK(vars); if((voice>=0)&&(voiceVoiceGetFrequency(voice); MUTEX_UNLOCK(vars); return result; } void Voice_SetPanning_internal(SBYTE voice,ULONG pan) { if((voice<0)||(voice>=md_numchn)) return; if(pan!=PAN_SURROUND) { if(md_pansep>128) md_pansep=128; if(md_mode & DMODE_REVERSE) pan=255-pan; pan = (((SWORD)(pan-128)*md_pansep)/128)+128; } md_driver->VoiceSetPanning(voice, pan); } MIKMODAPI void Voice_SetPanning(SBYTE voice,ULONG pan) { #ifdef MIKMOD_DEBUG if((pan!=PAN_SURROUND)&&((pan<0)||(pan>255))) fprintf(stderr,"\rVoice_SetPanning called with pan=%ld\n",(long)pan); #endif MUTEX_LOCK(vars); Voice_SetPanning_internal(voice,pan); MUTEX_UNLOCK(vars); } MIKMODAPI ULONG Voice_GetPanning(SBYTE voice) { ULONG result=PAN_CENTER; MUTEX_LOCK(vars); if((voice>=0)&&(voiceVoiceGetPanning(voice); MUTEX_UNLOCK(vars); return result; } void Voice_Play_internal(SBYTE voice,SAMPLE* s,ULONG start) { ULONG repend; if((voice<0)||(voice>=md_numchn)) return; md_sample[voice]=s; repend=s->loopend; if(s->flags&SF_LOOP) /* repend can't be bigger than size */ if(repend>s->length) repend=s->length; md_driver->VoicePlay(voice,s->handle,start,s->length,s->loopstart,repend,s->flags); } MIKMODAPI void Voice_Play(SBYTE voice,SAMPLE* s,ULONG start) { if(start>s->length) return; MUTEX_LOCK(vars); Voice_Play_internal(voice,s,start); MUTEX_UNLOCK(vars); } void Voice_Stop_internal(SBYTE voice) { if((voice<0)||(voice>=md_numchn)) return; if(voice>=md_sngchn) /* It is a sound effects channel, so flag the voice as non-critical! */ sfxinfo[voice-md_sngchn]=0; md_driver->VoiceStop(voice); } MIKMODAPI void Voice_Stop(SBYTE voice) { MUTEX_LOCK(vars); Voice_Stop_internal(voice); MUTEX_UNLOCK(vars); } BOOL Voice_Stopped_internal(SBYTE voice) { if((voice<0)||(voice>=md_numchn)) return 0; return(md_driver->VoiceStopped(voice)); } MIKMODAPI BOOL Voice_Stopped(SBYTE voice) { BOOL result; MUTEX_LOCK(vars); result=Voice_Stopped_internal(voice); MUTEX_UNLOCK(vars); return result; } MIKMODAPI SLONG Voice_GetPosition(SBYTE voice) { SLONG result=0; MUTEX_LOCK(vars); if((voice>=0)&&(voiceVoiceGetPosition) result=(md_driver->VoiceGetPosition(voice)); else result=-1; } MUTEX_UNLOCK(vars); return result; } MIKMODAPI ULONG Voice_RealVolume(SBYTE voice) { ULONG result=0; MUTEX_LOCK(vars); if((voice>=0)&&(voiceVoiceRealVolume) result=(md_driver->VoiceRealVolume(voice)); MUTEX_UNLOCK(vars); return result; } static BOOL _mm_init(CHAR *cmdline) { UWORD t; _mm_critical = 1; /* if md_device==0, try to find a device number */ if(!md_device) { cmdline=NULL; for(t=1,md_driver=firstdriver;md_driver;md_driver=md_driver->next,t++) if(md_driver->IsPresent()) break; if(!md_driver) { _mm_errno = MMERR_DETECTING_DEVICE; if(_mm_errorhandler) _mm_errorhandler(); md_driver = &drv_nos; return 1; } md_device = t; } else { /* if n>0, use that driver */ for(t=1,md_driver=firstdriver;(md_driver)&&(t!=md_device);md_driver=md_driver->next) t++; if(!md_driver) { _mm_errno = MMERR_INVALID_DEVICE; if(_mm_errorhandler) _mm_errorhandler(); md_driver = &drv_nos; return 1; } /* arguments here might be necessary for the presence check to succeed */ if(cmdline&&(md_driver->CommandLine)) md_driver->CommandLine(cmdline); if(!md_driver->IsPresent()) { _mm_errno = MMERR_DETECTING_DEVICE; if(_mm_errorhandler) _mm_errorhandler(); md_driver = &drv_nos; return 1; } } olddevice = md_device; if(md_driver->Init()) { MikMod_Exit_internal(); if(_mm_errorhandler) _mm_errorhandler(); return 1; } initialized=1; _mm_critical=0; return 0; } MIKMODAPI BOOL MikMod_Init(CHAR *cmdline) { BOOL result; MUTEX_LOCK(vars); MUTEX_LOCK(lists); result=_mm_init(cmdline); MUTEX_UNLOCK(lists); MUTEX_UNLOCK(vars); return result; } void MikMod_Exit_internal(void) { MikMod_DisableOutput_internal(); md_driver->Exit(); md_numchn = md_sfxchn = md_sngchn = 0; md_driver = &drv_nos; if(sfxinfo) MikMod_free(sfxinfo); if(md_sample) MikMod_free(md_sample); md_sample = NULL; sfxinfo = NULL; initialized = 0; } MIKMODAPI void MikMod_Exit(void) { MUTEX_LOCK(vars); MUTEX_LOCK(lists); MikMod_Exit_internal(); MUTEX_UNLOCK(lists); MUTEX_UNLOCK(vars); } /* Reset the driver using the new global variable settings. If the driver has not been initialized, it will be now. */ static BOOL _mm_reset(CHAR *cmdline) { BOOL wasplaying = 0; if(!initialized) return _mm_init(cmdline); if (isplaying) { wasplaying = 1; md_driver->PlayStop(); } if((!md_driver->Reset)||(md_device != olddevice)) { /* md_driver->Reset was NULL, or md_device was changed, so do a full reset of the driver. */ md_driver->Exit(); if(_mm_init(cmdline)) { MikMod_Exit_internal(); if(_mm_errno) if(_mm_errorhandler) _mm_errorhandler(); return 1; } } else { if(md_driver->Reset()) { MikMod_Exit_internal(); if(_mm_errno) if(_mm_errorhandler) _mm_errorhandler(); return 1; } } if (wasplaying) md_driver->PlayStart(); return 0; } MIKMODAPI BOOL MikMod_Reset(CHAR *cmdline) { BOOL result; MUTEX_LOCK(vars); MUTEX_LOCK(lists); result=_mm_reset(cmdline); MUTEX_UNLOCK(lists); MUTEX_UNLOCK(vars); return result; } /* If either parameter is -1, the current set value will be retained. */ BOOL MikMod_SetNumVoices_internal(int music, int sfx) { BOOL resume = 0; int t, oldchn = 0; if((!music)&&(!sfx)) return 1; _mm_critical = 1; if(isplaying) { MikMod_DisableOutput_internal(); oldchn = md_numchn; resume = 1; } if(sfxinfo) MikMod_free(sfxinfo); if(md_sample) MikMod_free(md_sample); md_sample = NULL; sfxinfo = NULL; if(music!=-1) md_sngchn = music; if(sfx!=-1) md_sfxchn = sfx; md_numchn = md_sngchn + md_sfxchn; LimitHardVoices(md_driver->HardVoiceLimit); LimitSoftVoices(md_driver->SoftVoiceLimit); if(md_driver->SetNumVoices()) { MikMod_Exit_internal(); if(_mm_errno) if(_mm_errorhandler!=NULL) _mm_errorhandler(); md_numchn = md_softchn = md_hardchn = md_sfxchn = md_sngchn = 0; return 1; } if(md_sngchn+md_sfxchn) md_sample=(SAMPLE**)MikMod_calloc(md_sngchn+md_sfxchn,sizeof(SAMPLE*)); if(md_sfxchn) sfxinfo = (UBYTE *)MikMod_calloc(md_sfxchn,sizeof(UBYTE)); /* make sure the player doesn't start with garbage */ for(t=oldchn;tPlayStart()) return 1; isplaying = 1; } _mm_critical = 0; return 0; } MIKMODAPI BOOL MikMod_EnableOutput(void) { BOOL result; MUTEX_LOCK(vars); result=MikMod_EnableOutput_internal(); MUTEX_UNLOCK(vars); return result; } void MikMod_DisableOutput_internal(void) { if(isplaying && md_driver) { isplaying = 0; md_driver->PlayStop(); } } MIKMODAPI void MikMod_DisableOutput(void) { MUTEX_LOCK(vars); MikMod_DisableOutput_internal(); MUTEX_UNLOCK(vars); } BOOL MikMod_Active_internal(void) { return isplaying; } MIKMODAPI BOOL MikMod_Active(void) { BOOL result; MUTEX_LOCK(vars); result=MikMod_Active_internal(); MUTEX_UNLOCK(vars); return result; } /* Plays a sound effects sample. Picks a voice from the number of voices allocated for use as sound effects (loops through voices, skipping all active criticals). Returns the voice that the sound is being played on. */ SBYTE Sample_Play_internal(SAMPLE *s,ULONG start,UBYTE flags) { int orig=sfxpool;/* for cases where all channels are critical */ int c; if(!md_sfxchn) return -1; if(s->volume>64) s->volume = 64; /* check the first location after sfxpool */ do { if(sfxinfo[sfxpool]&SFX_CRITICAL) { if(md_driver->VoiceStopped(c=sfxpool+md_sngchn)) { sfxinfo[sfxpool]=flags; Voice_Play_internal(c,s,start); md_driver->VoiceSetVolume(c,s->volume<<2); Voice_SetPanning_internal(c,s->panning); md_driver->VoiceSetFrequency(c,s->speed); sfxpool++; if(sfxpool>=md_sfxchn) sfxpool=0; return c; } } else { sfxinfo[sfxpool]=flags; Voice_Play_internal(c=sfxpool+md_sngchn,s,start); md_driver->VoiceSetVolume(c,s->volume<<2); Voice_SetPanning_internal(c,s->panning); md_driver->VoiceSetFrequency(c,s->speed); sfxpool++; if(sfxpool>=md_sfxchn) sfxpool=0; return c; } sfxpool++; if(sfxpool>=md_sfxchn) sfxpool = 0; } while(sfxpool!=orig); return -1; } MIKMODAPI SBYTE Sample_Play(SAMPLE *s,ULONG start,UBYTE flags) { SBYTE result; MUTEX_LOCK(vars); result=Sample_Play_internal(s,start,flags); MUTEX_UNLOCK(vars); return result; } MIKMODAPI long MikMod_GetVersion(void) { return LIBMIKMOD_VERSION; } /*========== MT-safe stuff */ #ifdef HAVE_PTHREAD #define INIT_MUTEX(name) \ pthread_mutex_t _mm_mutex_##name=PTHREAD_MUTEX_INITIALIZER #elif defined(__OS2__)||defined(__EMX__) #define INIT_MUTEX(name) \ HMTX _mm_mutex_##name #elif defined(WIN32) #define INIT_MUTEX(name) \ HANDLE _mm_mutex_##name #else #define INIT_MUTEX(name) \ void *_mm_mutex_##name = NULL #endif INIT_MUTEX(vars); INIT_MUTEX(lists); MIKMODAPI BOOL MikMod_InitThreads(void) { static int firstcall=1; static int result=0; if (firstcall) { firstcall=0; #ifdef HAVE_PTHREAD result=1; #elif defined(__OS2__)||defined(__EMX__) if(DosCreateMutexSem((PSZ)NULL,&_mm_mutex_lists,0,0) || DosCreateMutexSem((PSZ)NULL,&_mm_mutex_vars,0,0)) { _mm_mutex_lists=_mm_mutex_vars=(HMTX)NULL; result=0; } else result=1; #elif defined(WIN32) if((!(_mm_mutex_lists=CreateMutex(NULL,FALSE,"libmikmod(lists)")))|| (!(_mm_mutex_vars=CreateMutex(NULL,FALSE,"libmikmod(vars)")))) result=0; else result=1; #endif } return result; } MIKMODAPI void MikMod_Unlock(void) { MUTEX_UNLOCK(lists); MUTEX_UNLOCK(vars); } MIKMODAPI void MikMod_Lock(void) { MUTEX_LOCK(vars); MUTEX_LOCK(lists); } /*========== Parameter extraction helper */ CHAR *MD_GetAtom(CHAR *atomname,CHAR *cmdline,BOOL implicit) { CHAR *ret=NULL; if(cmdline) { CHAR *buf=strstr(cmdline,atomname); if((buf)&&((buf==cmdline)||(*(buf-1)==','))) { CHAR *ptr=buf+strlen(atomname); if(*ptr=='=') { for(buf=++ptr;(*ptr)&&((*ptr)!=',');ptr++); ret=MikMod_malloc((1+ptr-buf)*sizeof(CHAR)); if(ret) strncpy(ret,buf,ptr-buf); } else if((*ptr==',')||(!*ptr)) { if(implicit) { ret=MikMod_malloc((1+ptr-buf)*sizeof(CHAR)); if(ret) strncpy(ret,buf,ptr-buf); } } } } return ret; } #if defined unix || (defined __APPLE__ && defined __MACH__) /*========== Posix helper functions */ /* Check if the file is a regular or nonexistant file (or a link to a such a file), and that, should the calling program be setuid, the access rights are reasonable. Returns 1 if it is safe to rewrite the file, 0 otherwise. The goal is to prevent a setuid root libmikmod application from overriding files like /etc/passwd with digital sound... */ BOOL MD_Access(CHAR *filename) { struct stat buf; if(!stat(filename,&buf)) { /* not a regular file ? */ if(!S_ISREG(buf.st_mode)) return 0; /* more than one hard link to the file ? */ if(buf.st_nlink>1) return 0; /* check access rights with the real user and group id */ if(getuid()==buf.st_uid) { if(!(buf.st_mode&S_IWUSR)) return 0; } else if(getgid()==buf.st_gid) { if(!(buf.st_mode&S_IWGRP)) return 0; } else if(!(buf.st_mode&S_IWOTH)) return 0; } return 1; } /* Drop all root privileges we might have */ BOOL MD_DropPrivileges(void) { if(!geteuid()) { if(getuid()) { /* we are setuid root -> drop setuid to become the real user */ if(setuid(getuid())) return 1; } else { /* we are run as root -> drop all and become user 'nobody' */ struct passwd *nobody; int uid; if(!(nobody=getpwnam("nobody"))) return 1; /* no such user ? */ uid=nobody->pw_uid; if (!uid) /* user 'nobody' has root privileges ? weird... */ return 1; if (setuid(uid)) return 1; } } return 0; } #endif /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mplayer.c0000600000175000017500000024110710543202047017637 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mplayer.c 2421 2006-08-19 00:36:21Z avolkov $ The Protracker Player Driver The protracker driver supports all base Protracker 3.x commands and features. ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #ifdef SRANDOM_IN_MATH_H #include #else #include #endif #include "mikmod_internals.h" #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); extern long int random(void); #endif /* The currently playing module */ /* This variable should better be static, but it would break the ABI, so this will wait */ /*static*/ MODULE *pf = NULL; #define HIGH_OCTAVE 2 /* number of above-range octaves */ static UWORD oldperiods[OCTAVE*2]={ 0x6b00, 0x6800, 0x6500, 0x6220, 0x5f50, 0x5c80, 0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0, 0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160, 0x3f90, 0x3dc0, 0x3c10, 0x3a40, 0x38b0, 0x3700 }; static UBYTE VibratoTable[32]={ 0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253, 255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24 }; static UBYTE avibtab[128]={ 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23, 24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44, 45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58, 59,59,60,60,61,61,62,62,62,63,63,63,63,63,63,63, 64,63,63,63,63,63,63,63,62,62,62,61,61,60,60,59, 59,58,57,57,56,55,54,54,53,52,51,50,49,48,47,46, 45,44,42,41,40,39,38,36,35,34,32,31,30,28,27,25, 24,23,21,20,18,17,15,14,12,10, 9, 7, 6, 4, 3, 1 }; /* Triton's linear periods to frequency translation table (for XM modules) */ static ULONG lintab[768]={ 535232,534749,534266,533784,533303,532822,532341,531861, 531381,530902,530423,529944,529466,528988,528511,528034, 527558,527082,526607,526131,525657,525183,524709,524236, 523763,523290,522818,522346,521875,521404,520934,520464, 519994,519525,519057,518588,518121,517653,517186,516720, 516253,515788,515322,514858,514393,513929,513465,513002, 512539,512077,511615,511154,510692,510232,509771,509312, 508852,508393,507934,507476,507018,506561,506104,505647, 505191,504735,504280,503825,503371,502917,502463,502010, 501557,501104,500652,500201,499749,499298,498848,498398, 497948,497499,497050,496602,496154,495706,495259,494812, 494366,493920,493474,493029,492585,492140,491696,491253, 490809,490367,489924,489482,489041,488600,488159,487718, 487278,486839,486400,485961,485522,485084,484647,484210, 483773,483336,482900,482465,482029,481595,481160,480726, 480292,479859,479426,478994,478562,478130,477699,477268, 476837,476407,475977,475548,475119,474690,474262,473834, 473407,472979,472553,472126,471701,471275,470850,470425, 470001,469577,469153,468730,468307,467884,467462,467041, 466619,466198,465778,465358,464938,464518,464099,463681, 463262,462844,462427,462010,461593,461177,460760,460345, 459930,459515,459100,458686,458272,457859,457446,457033, 456621,456209,455797,455386,454975,454565,454155,453745, 453336,452927,452518,452110,451702,451294,450887,450481, 450074,449668,449262,448857,448452,448048,447644,447240, 446836,446433,446030,445628,445226,444824,444423,444022, 443622,443221,442821,442422,442023,441624,441226,440828, 440430,440033,439636,439239,438843,438447,438051,437656, 437261,436867,436473,436079,435686,435293,434900,434508, 434116,433724,433333,432942,432551,432161,431771,431382, 430992,430604,430215,429827,429439,429052,428665,428278, 427892,427506,427120,426735,426350,425965,425581,425197, 424813,424430,424047,423665,423283,422901,422519,422138, 421757,421377,420997,420617,420237,419858,419479,419101, 418723,418345,417968,417591,417214,416838,416462,416086, 415711,415336,414961,414586,414212,413839,413465,413092, 412720,412347,411975,411604,411232,410862,410491,410121, 409751,409381,409012,408643,408274,407906,407538,407170, 406803,406436,406069,405703,405337,404971,404606,404241, 403876,403512,403148,402784,402421,402058,401695,401333, 400970,400609,400247,399886,399525,399165,398805,398445, 398086,397727,397368,397009,396651,396293,395936,395579, 395222,394865,394509,394153,393798,393442,393087,392733, 392378,392024,391671,391317,390964,390612,390259,389907, 389556,389204,388853,388502,388152,387802,387452,387102, 386753,386404,386056,385707,385359,385012,384664,384317, 383971,383624,383278,382932,382587,382242,381897,381552, 381208,380864,380521,380177,379834,379492,379149,378807, 378466,378124,377783,377442,377102,376762,376422,376082, 375743,375404,375065,374727,374389,374051,373714,373377, 373040,372703,372367,372031,371695,371360,371025,370690, 370356,370022,369688,369355,369021,368688,368356,368023, 367691,367360,367028,366697,366366,366036,365706,365376, 365046,364717,364388,364059,363731,363403,363075,362747, 362420,362093,361766,361440,361114,360788,360463,360137, 359813,359488,359164,358840,358516,358193,357869,357547, 357224,356902,356580,356258,355937,355616,355295,354974, 354654,354334,354014,353695,353376,353057,352739,352420, 352103,351785,351468,351150,350834,350517,350201,349885, 349569,349254,348939,348624,348310,347995,347682,347368, 347055,346741,346429,346116,345804,345492,345180,344869, 344558,344247,343936,343626,343316,343006,342697,342388, 342079,341770,341462,341154,340846,340539,340231,339924, 339618,339311,339005,338700,338394,338089,337784,337479, 337175,336870,336566,336263,335959,335656,335354,335051, 334749,334447,334145,333844,333542,333242,332941,332641, 332341,332041,331741,331442,331143,330844,330546,330247, 329950,329652,329355,329057,328761,328464,328168,327872, 327576,327280,326985,326690,326395,326101,325807,325513, 325219,324926,324633,324340,324047,323755,323463,323171, 322879,322588,322297,322006,321716,321426,321136,320846, 320557,320267,319978,319690,319401,319113,318825,318538, 318250,317963,317676,317390,317103,316817,316532,316246, 315961,315676,315391,315106,314822,314538,314254,313971, 313688,313405,313122,312839,312557,312275,311994,311712, 311431,311150,310869,310589,310309,310029,309749,309470, 309190,308911,308633,308354,308076,307798,307521,307243, 306966,306689,306412,306136,305860,305584,305308,305033, 304758,304483,304208,303934,303659,303385,303112,302838, 302565,302292,302019,301747,301475,301203,300931,300660, 300388,300117,299847,299576,299306,299036,298766,298497, 298227,297958,297689,297421,297153,296884,296617,296349, 296082,295815,295548,295281,295015,294749,294483,294217, 293952,293686,293421,293157,292892,292628,292364,292100, 291837,291574,291311,291048,290785,290523,290261,289999, 289737,289476,289215,288954,288693,288433,288173,287913, 287653,287393,287134,286875,286616,286358,286099,285841, 285583,285326,285068,284811,284554,284298,284041,283785, 283529,283273,283017,282762,282507,282252,281998,281743, 281489,281235,280981,280728,280475,280222,279969,279716, 279464,279212,278960,278708,278457,278206,277955,277704, 277453,277203,276953,276703,276453,276204,275955,275706, 275457,275209,274960,274712,274465,274217,273970,273722, 273476,273229,272982,272736,272490,272244,271999,271753, 271508,271263,271018,270774,270530,270286,270042,269798, 269555,269312,269069,268826,268583,268341,268099,267857 }; #define LOGFAC 2*16 static UWORD logtab[104]={ LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887, LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862, LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838, LOGFAC*832,LOGFAC*826,LOGFAC*820,LOGFAC*814, LOGFAC*808,LOGFAC*802,LOGFAC*796,LOGFAC*791, LOGFAC*785,LOGFAC*779,LOGFAC*774,LOGFAC*768, LOGFAC*762,LOGFAC*757,LOGFAC*752,LOGFAC*746, LOGFAC*741,LOGFAC*736,LOGFAC*730,LOGFAC*725, LOGFAC*720,LOGFAC*715,LOGFAC*709,LOGFAC*704, LOGFAC*699,LOGFAC*694,LOGFAC*689,LOGFAC*684, LOGFAC*678,LOGFAC*675,LOGFAC*670,LOGFAC*665, LOGFAC*660,LOGFAC*655,LOGFAC*651,LOGFAC*646, LOGFAC*640,LOGFAC*636,LOGFAC*632,LOGFAC*628, LOGFAC*623,LOGFAC*619,LOGFAC*614,LOGFAC*610, LOGFAC*604,LOGFAC*601,LOGFAC*597,LOGFAC*592, LOGFAC*588,LOGFAC*584,LOGFAC*580,LOGFAC*575, LOGFAC*570,LOGFAC*567,LOGFAC*563,LOGFAC*559, LOGFAC*555,LOGFAC*551,LOGFAC*547,LOGFAC*543, LOGFAC*538,LOGFAC*535,LOGFAC*532,LOGFAC*528, LOGFAC*524,LOGFAC*520,LOGFAC*516,LOGFAC*513, LOGFAC*508,LOGFAC*505,LOGFAC*502,LOGFAC*498, LOGFAC*494,LOGFAC*491,LOGFAC*487,LOGFAC*484, LOGFAC*480,LOGFAC*477,LOGFAC*474,LOGFAC*470, LOGFAC*467,LOGFAC*463,LOGFAC*460,LOGFAC*457, LOGFAC*453,LOGFAC*450,LOGFAC*447,LOGFAC*443, LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431 }; static SBYTE PanbrelloTable[256]={ 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23, 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60, 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26, 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2, 0,- 2,- 3,- 5,- 6,- 8,- 9,-11,-12,-14,-16,-17,-19,-20,-22,-23, -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44, -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59, -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64, -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60, -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46, -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26, -24,-23,-22,-20,-19,-17,-16,-14,-12,-11,- 9,- 8,- 6,- 5,- 3,- 2 }; /* returns a random value between 0 and ceil-1, ceil must be a power of two */ static int getrandom(int ceil) { #ifdef HAVE_SRANDOM return random()&(ceil-1); #else return (rand()*ceil)/(RAND_MAX+1.0); #endif } /* New Note Action Scoring System : -------------------------------- 1) total-volume (fadevol, chanvol, volume) is the main scorer. 2) a looping sample is a bonus x2 3) a foreground channel is a bonus x4 4) an active envelope with keyoff is a handicap -x2 */ static int MP_FindEmptyChannel(MODULE *mod) { MP_VOICE *a; ULONG t,k,tvol,pp; for (t=0;tvoice[t].main.kick==KICK_ABSENT)|| (mod->voice[t].main.kick==KICK_ENV))&& Voice_Stopped_internal(t)) return t; tvol=0xffffffUL;t=-1;a=mod->voice; for (k=0;kmain.s) return k; if ((a->main.kick==KICK_ABSENT)||(a->main.kick==KICK_ENV)) { pp=a->totalvol<<((a->main.s->flags&SF_LOOP)?1:0); if ((a->master)&&(a==a->master->slave)) pp<<=2; if (pp8000*7) return -1; return t; } static SWORD Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2) { if ((p1==p2)||(p==p1)) return v1; return v1+((SLONG)((p-p1)*(v2-v1))/(p2-p1)); } UWORD getlinearperiod(UWORD note,ULONG fine) { UWORD t; t=((20L+2*HIGH_OCTAVE)*OCTAVE+2-note)*32L-(fine>>1); return t; } static UWORD getlogperiod(UWORD note,ULONG fine) { UWORD n,o; UWORD p1,p2; ULONG i; n=note%(2*OCTAVE); o=note/(2*OCTAVE); i=(n<<2)+(fine>>4); /* n*8 + fine/16 */ p1=logtab[i]; p2=logtab[i+1]; return (Interpolate(fine>>4,0,15,p1,p2)>>o); } static UWORD getoldperiod(UWORD note,ULONG speed) { UWORD n,o; /* This happens sometimes on badly converted AMF, and old MOD */ if (!speed) { #ifdef MIKMOD_DEBUG fprintf(stderr,"\rmplayer: getoldperiod() called with note=%d, speed=0 !\n",note); #endif return 4242; /* <- prevent divide overflow.. (42 hehe) */ } n=note%(2*OCTAVE); o=note/(2*OCTAVE); return ((8363L*(ULONG)oldperiods[n])>>o)/speed; } static UWORD GetPeriod(UWORD flags, UWORD note, ULONG speed) { if (flags & UF_XMPERIODS) { if (flags & UF_LINEAR) return getlinearperiod(note, speed); else return getlogperiod(note, speed); } else return getoldperiod(note, speed); } static SWORD InterpolateEnv(SWORD p,ENVPT *a,ENVPT *b) { return (Interpolate(p,a->pos,b->pos,a->val,b->val)); } static SWORD DoPan(SWORD envpan,SWORD pan) { int newpan; newpan=pan+(((envpan-PAN_CENTER)*(128-abs(pan-PAN_CENTER)))/128); return (newpanPAN_RIGHT?PAN_RIGHT:newpan); } static SWORD StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susend,UBYTE beg,UBYTE end,ENVPT *p,UBYTE keyoff) { t->flg=flg; t->pts=pts; t->susbeg=susbeg; t->susend=susend; t->beg=beg; t->end=end; t->env=p; t->p=0; t->a=0; t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1; /* Imago Orpheus sometimes stores an extra initial point in the envelope */ if ((t->pts>=2)&&(t->env[0].pos==t->env[1].pos)) { t->a++;t->b++; } /* Fit in the envelope, still */ if (t->a >= t->pts) t->a = t->pts - 1; if (t->b >= t->pts) t->b = t->pts-1; return t->env[t->a].val; } /* This procedure processes all envelope types, include volume, pitch, and panning. Envelopes are defined by a set of points, each with a magnitude [relating either to volume, panning position, or pitch modifier] and a tick position. Envelopes work in the following manner: (a) Each tick the envelope is moved a point further in its progression. For an accurate progression, magnitudes between two envelope points are interpolated. (b) When progression reaches a defined point on the envelope, values are shifted to interpolate between this point and the next, and checks for loops or envelope end are done. Misc: Sustain loops are loops that are only active as long as the keyoff flag is clear. When a volume envelope terminates, so does the current fadeout. */ static SWORD ProcessEnvelope(MP_VOICE *aout, ENVPR *t, SWORD v) { if (t->flg & EF_ON) { UBYTE a, b; /* actual points in the envelope */ UWORD p; /* the 'tick counter' - real point being played */ a = t->a; b = t->b; p = t->p; /* * Sustain loop on one point (XM type). * Not processed if KEYOFF. * Don't move and don't interpolate when the point is reached */ if ((t->flg & EF_SUSTAIN) && t->susbeg == t->susend && (!(aout->main.keyoff & KEY_OFF) && p == t->env[t->susbeg].pos)) { v = t->env[t->susbeg].val; } else { /* * All following situations will require interpolation between * two envelope points. */ /* * Sustain loop between two points (IT type). * Not processed if KEYOFF. */ /* if we were on a loop point, loop now */ if ((t->flg & EF_SUSTAIN) && !(aout->main.keyoff & KEY_OFF) && a >= t->susend) { a = t->susbeg; b = (t->susbeg==t->susend)?a:a+1; p = t->env[a].pos; v = t->env[a].val; } else /* * Regular loop. * Be sure to correctly handle single point loops. */ if ((t->flg & EF_LOOP) && a >= t->end) { a = t->beg; b = t->beg == t->end ? a : a + 1; p = t->env[a].pos; v = t->env[a].val; } else /* * Non looping situations. */ if (a != b) v = InterpolateEnv(p, &t->env[a], &t->env[b]); else v = t->env[a].val; /* * Start to fade if the volume envelope is finished. */ if (p >= t->env[t->pts - 1].pos) { if (t->flg & EF_VOLENV) { aout->main.keyoff |= KEY_FADE; if (!v) aout->main.fadevol = 0; } } else { p++; /* did pointer reach point b? */ if (p >= t->env[b].pos) a = b++; /* shift points a and b */ } t->a = a; t->b = b; t->p = p; } } return v; } /* XM linear period to frequency conversion */ ULONG getfrequency(UWORD flags,ULONG period) { if (flags & UF_LINEAR) { SLONG shift = ((SLONG)period / 768) - HIGH_OCTAVE; if (shift >= 0) return lintab[period % 768] >> shift; else return lintab[period % 768] << (-shift); } else return (8363L*1712L)/(period?period:1); } /*========== Protracker effects */ static void DoArpeggio(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE style) { UBYTE note=a->main.note; if (a->arpmem) { switch (style) { case 0: /* mod style: N, N+x, N+y */ switch (tick % 3) { /* case 0: unchanged */ case 1: note += (a->arpmem >> 4); break; case 2: note += (a->arpmem & 0xf); break; } break; case 3: /* okt arpeggio 3: N-x, N, N+y */ switch (tick % 3) { case 0: note -= (a->arpmem >> 4); break; /* case 1: unchanged */ case 2: note += (a->arpmem & 0xf); break; } break; case 4: /* okt arpeggio 4: N, N+y, N, N-x */ switch (tick % 4) { /* case 0, case 2: unchanged */ case 1: note += (a->arpmem & 0xf); break; case 3: note -= (a->arpmem >> 4); break; } break; case 5: /* okt arpeggio 5: N-x, N+y, N, and nothing at tick 0 */ if (!tick) break; switch (tick % 3) { /* case 0: unchanged */ case 1: note -= (a->arpmem >> 4); break; case 2: note += (a->arpmem & 0xf); break; } break; } a->main.period = GetPeriod(flags, (UWORD)note << 1, a->speed); a->ownper = 1; } } static int DoPTEffect0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat = UniGetByte(); if (!tick) { if (!dat && (flags & UF_ARPMEM)) dat=a->arpmem; else a->arpmem=dat; } if (a->main.period) DoArpeggio(tick, flags, a, 0); return 0; } static int DoPTEffect1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat = UniGetByte(); if (!tick && dat) a->slidespeed = (UWORD)dat << 2; if (a->main.period) if (tick) a->tmpperiod -= a->slidespeed; return 0; } static int DoPTEffect2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat = UniGetByte(); if (!tick && dat) a->slidespeed = (UWORD)dat << 2; if (a->main.period) if (tick) a->tmpperiod += a->slidespeed; return 0; } static void DoToneSlide(UWORD tick, MP_CONTROL *a) { if (!a->main.fadevol) a->main.kick = (a->main.kick == KICK_NOTE)? KICK_NOTE : KICK_KEYOFF; else a->main.kick = (a->main.kick == KICK_NOTE)? KICK_ENV : KICK_ABSENT; if (tick != 0) { int dist; /* We have to slide a->main.period towards a->wantedperiod, so compute the difference between those two values */ dist=a->main.period-a->wantedperiod; /* if they are equal or if portamentospeed is too big ...*/ if (dist == 0 || a->portspeed > abs(dist)) /* ...make tmpperiod equal tperiod */ a->tmpperiod=a->main.period=a->wantedperiod; else if (dist>0) { a->tmpperiod-=a->portspeed; a->main.period-=a->portspeed; /* dist>0, slide up */ } else { a->tmpperiod+=a->portspeed; a->main.period+=a->portspeed; /* dist<0, slide down */ } } else a->tmpperiod=a->main.period; a->ownper = 1; } static int DoPTEffect3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if ((!tick)&&(dat)) a->portspeed=(UWORD)dat<<2; if (a->main.period) DoToneSlide(tick, a); return 0; } static void DoVibrato(UWORD tick, MP_CONTROL *a) { UBYTE q; UWORD temp = 0; /* silence warning */ if (!tick) return; q=(a->vibpos>>2)&0x1f; switch (a->wavecontrol&3) { case 0: /* sine */ temp=VibratoTable[q]; break; case 1: /* ramp down */ q<<=3; if (a->vibpos<0) q=255-q; temp=q; break; case 2: /* square wave */ temp=255; break; case 3: /* random wave */ temp=getrandom(256); break; } temp*=a->vibdepth; temp>>=7;temp<<=2; if (a->vibpos>=0) a->main.period=a->tmpperiod+temp; else a->main.period=a->tmpperiod-temp; a->ownper = 1; if (tick != 0) a->vibpos+=a->vibspd; } static int DoPTEffect4(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (!tick) { if (dat&0x0f) a->vibdepth=dat&0xf; if (dat&0xf0) a->vibspd=(dat&0xf0)>>2; } if (a->main.period) DoVibrato(tick, a); return 0; } static void DoVolSlide(MP_CONTROL *a, UBYTE dat) { if (dat&0xf) { a->tmpvolume-=(dat&0x0f); if (a->tmpvolume<0) a->tmpvolume=0; } else { a->tmpvolume+=(dat>>4); if (a->tmpvolume>64) a->tmpvolume=64; } } static int DoPTEffect5(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (a->main.period) DoToneSlide(tick, a); if (tick) DoVolSlide(a, dat); return 0; } /* DoPTEffect6 after DoPTEffectA */ static int DoPTEffect7(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; UBYTE q; UWORD temp = 0; /* silence warning */ (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (!tick) { if (dat&0x0f) a->trmdepth=dat&0xf; if (dat&0xf0) a->trmspd=(dat&0xf0)>>2; } if (a->main.period) { q=(a->trmpos>>2)&0x1f; switch ((a->wavecontrol>>4)&3) { case 0: /* sine */ temp=VibratoTable[q]; break; case 1: /* ramp down */ q<<=3; if (a->trmpos<0) q=255-q; temp=q; break; case 2: /* square wave */ temp=255; break; case 3: /* random wave */ temp=getrandom(256); break; } temp*=a->trmdepth; temp>>=6; if (a->trmpos>=0) { a->volume=a->tmpvolume+temp; if (a->volume>64) a->volume=64; } else { a->volume=a->tmpvolume-temp; if (a->volume<0) a->volume=0; } a->ownvol = 1; if (tick) a->trmpos+=a->trmspd; } return 0; } static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)tick; /* unused arg */ (void)flags; /* unused arg */ dat = UniGetByte(); if (mod->panflag) a->main.panning = mod->panning[channel] = dat; return 0; } static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (!tick) { if (dat) a->soffset=(UWORD)dat<<8; a->main.start=a->hioffset|a->soffset; if ((a->main.s)&&(a->main.start>a->main.s->length)) a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)? a->main.s->loopstart:a->main.s->length; } return 0; } static int DoPTEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (tick) DoVolSlide(a, dat); return 0; } static int DoPTEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { if (a->main.period) DoVibrato(tick, a); DoPTEffectA(tick, flags, a, mod, channel); return 0; } static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)a; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (tick || mod->patdly2) return 0; /* Vincent Voois uses a nasty trick in "Universal Bolero" */ if (dat == mod->sngpos && mod->patbrk == mod->patpos) return 0; if (!mod->loop && !mod->patbrk && (dat < mod->sngpos || (mod->sngpos == (mod->numpos - 1) && !mod->patbrk) || (dat == mod->sngpos && (flags & UF_NOWRAP)) )) { /* if we don't loop, better not to skip the end of the pattern, after all... so: mod->patbrk=0; */ mod->posjmp=3; } else { /* if we were fading, adjust... */ if (mod->sngpos == (mod->numpos-1)) mod->volume=mod->initvolume>128?128:mod->initvolume; mod->sngpos=dat; mod->posjmp=2; mod->patpos=0; } return 0; } static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (tick) return 0; if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */ else if (dat>64) dat=64; a->tmpvolume=dat; return 0; } static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)a; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if ((tick)||(mod->patdly2)) return 0; if ((mod->positions[mod->sngpos]!=LAST_PATTERN)&& (dat>mod->pattrows[mod->positions[mod->sngpos]])) dat=mod->pattrows[mod->positions[mod->sngpos]]; mod->patbrk=dat; if (!mod->posjmp) { /* don't ask me to explain this code - it makes backwards.s3m and children.xm (heretic's version) play correctly, among others. Take that for granted, or write the page of comments yourself... you might need some aspirin - Miod */ if ((mod->sngpos==mod->numpos-1)&&(dat)&&((mod->loop)|| (mod->positions[mod->sngpos]==(mod->numpat-1) && !(flags&UF_NOWRAP)))) { mod->sngpos=0; mod->posjmp=2; } else mod->posjmp=3; } return 0; } static void DoEEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel, UBYTE dat) { UBYTE nib = dat & 0xf; switch (dat>>4) { case 0x0: /* hardware filter toggle, not supported */ break; case 0x1: /* fineslide up */ if (a->main.period) if (!tick) a->tmpperiod-=(nib<<2); break; case 0x2: /* fineslide dn */ if (a->main.period) if (!tick) a->tmpperiod+=(nib<<2); break; case 0x3: /* glissando ctrl */ a->glissando=nib; break; case 0x4: /* set vibrato waveform */ a->wavecontrol&=0xf0; a->wavecontrol|=nib; break; case 0x5: /* set finetune */ if (a->main.period) { if (flags&UF_XMPERIODS) a->speed=nib+128; else a->speed=finetune[nib]; a->tmpperiod=GetPeriod(flags, (UWORD)a->main.note<<1,a->speed); } break; case 0x6: /* set patternloop */ if (tick) break; if (nib) { /* set reppos or repcnt ? */ /* set repcnt, so check if repcnt already is set, which means we are already looping */ if (a->pat_repcnt) a->pat_repcnt--; /* already looping, decrease counter */ else { #if 0 /* this would make walker.xm, shipped with Xsoundtracker, play correctly, but it's better to remain compatible with FT2 */ if ((!(flags&UF_NOWRAP))||(a->pat_reppos!=POS_NONE)) #endif a->pat_repcnt=nib; /* not yet looping, so set repcnt */ } if (a->pat_repcnt) { /* jump to reppos if repcnt>0 */ if (a->pat_reppos==POS_NONE) a->pat_reppos=mod->patpos-1; if (a->pat_reppos==-1) { mod->pat_repcrazy=1; mod->patpos=0; } else mod->patpos=a->pat_reppos; } else a->pat_reppos=POS_NONE; } else a->pat_reppos=mod->patpos-1; /* set reppos - can be (-1) */ break; case 0x7: /* set tremolo waveform */ a->wavecontrol&=0x0f; a->wavecontrol|=nib<<4; break; case 0x8: /* set panning */ if (mod->panflag) { if (nib<=8) nib<<=4; else nib*=17; a->main.panning=mod->panning[channel]=nib; } break; case 0x9: /* retrig note */ /* do not retrigger on tick 0, until we are emulating FT2 and effect data is zero */ if (!tick && !((flags & UF_FT2QUIRKS) && (!nib))) break; /* only retrigger if data nibble > 0, or if tick 0 (FT2 compat) */ if (nib || !tick) { if (!a->retrig) { /* when retrig counter reaches 0, reset counter and restart the sample */ if (a->main.period) a->main.kick=KICK_NOTE; a->retrig=nib; } a->retrig--; /* countdown */ } break; case 0xa: /* fine volume slide up */ if (tick) break; a->tmpvolume+=nib; if (a->tmpvolume>64) a->tmpvolume=64; break; case 0xb: /* fine volume slide dn */ if (tick) break; a->tmpvolume-=nib; if (a->tmpvolume<0)a->tmpvolume=0; break; case 0xc: /* cut note */ /* When tick reaches the cut-note value, turn the volume to zero (just like on the amiga) */ if (tick>=nib) a->tmpvolume=0; /* just turn the volume down */ break; case 0xd: /* note delay */ /* delay the start of the sample until tick==nib */ if (!tick) a->main.notedelay=nib; else if (a->main.notedelay) a->main.notedelay--; break; case 0xe: /* pattern delay */ if (!tick) if (!mod->patdly2) mod->patdly=nib+1; /* only once, when tick=0 */ break; case 0xf: /* invert loop, not supported */ break; } } static int DoPTEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { DoEEffects(tick, flags, a, mod, channel, UniGetByte()); return 0; } static int DoPTEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)a; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (tick||mod->patdly2) return 0; if (mod->extspd&&(dat>=mod->bpmlimit)) mod->bpm=dat; else if (dat) { mod->sngspd=(dat>=mod->bpmlimit)?mod->bpmlimit-1:dat; mod->vbtick=0; } return 0; } /*========== Scream Tracker effects */ static int DoS3MEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE speed; (void)flags; /* unused arg */ (void)a; /* unused arg */ (void)channel; /* unused arg */ speed = UniGetByte(); if (tick || mod->patdly2) return 0; if (speed > 128) speed -= 128; if (speed) { mod->sngspd = speed; mod->vbtick = 0; } return 0; } static void DoS3MVolSlide(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE inf) { UBYTE lo, hi; if (inf) a->s3mvolslide=inf; else inf=a->s3mvolslide; lo=inf&0xf; hi=inf>>4; if (!lo) { if ((tick)||(flags&UF_S3MSLIDES)) a->tmpvolume+=hi; } else if (!hi) { if ((tick)||(flags&UF_S3MSLIDES)) a->tmpvolume-=lo; } else if (lo==0xf) { if (!tick) a->tmpvolume+=(hi?hi:0xf); } else if (hi==0xf) { if (!tick) a->tmpvolume-=(lo?lo:0xf); } else return; if (a->tmpvolume<0) a->tmpvolume=0; else if (a->tmpvolume>64) a->tmpvolume=64; } static int DoS3MEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { (void)mod; /* unused arg */ (void)channel; /* unused arg */ DoS3MVolSlide(tick, flags, a, UniGetByte()); return 1; } static void DoS3MSlideDn(UWORD tick, MP_CONTROL *a, UBYTE inf) { UBYTE hi,lo; if (inf) a->slidespeed=inf; else inf=a->slidespeed; hi=inf>>4; lo=inf&0xf; if (hi==0xf) { if (!tick) a->tmpperiod+=(UWORD)lo<<2; } else if (hi==0xe) { if (!tick) a->tmpperiod+=lo; } else { if (tick) a->tmpperiod+=(UWORD)inf<<2; } } static int DoS3MEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (a->main.period) DoS3MSlideDn(tick, a,dat); return 0; } static void DoS3MSlideUp(UWORD tick, MP_CONTROL *a, UBYTE inf) { UBYTE hi,lo; if (inf) a->slidespeed=inf; else inf=a->slidespeed; hi=inf>>4; lo=inf&0xf; if (hi==0xf) { if (!tick) a->tmpperiod-=(UWORD)lo<<2; } else if (hi==0xe) { if (!tick) a->tmpperiod-=lo; } else { if (tick) a->tmpperiod-=(UWORD)inf<<2; } } static int DoS3MEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (a->main.period) DoS3MSlideUp(tick, a,dat); return 0; } static int DoS3MEffectI(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE inf, on, off; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ inf = UniGetByte(); if (inf) a->s3mtronof = inf; else { inf = a->s3mtronof; if (!inf) return 0; } if (!tick) return 0; on=(inf>>4)+1; off=(inf&0xf)+1; a->s3mtremor%=(on+off); a->volume=(a->s3mtremortmpvolume:0; a->ownvol=1; a->s3mtremor++; return 0; } static int DoS3MEffectQ(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE inf; (void)mod; /* unused arg */ (void)channel; /* unused arg */ inf = UniGetByte(); if (a->main.period) { if (inf) { a->s3mrtgslide=inf>>4; a->s3mrtgspeed=inf&0xf; } /* only retrigger if low nibble > 0 */ if (a->s3mrtgspeed>0) { if (!a->retrig) { /* when retrig counter reaches 0, reset counter and restart the sample */ if (a->main.kick!=KICK_NOTE) a->main.kick=KICK_KEYOFF; a->retrig=a->s3mrtgspeed; if ((tick)||(flags&UF_S3MSLIDES)) { switch (a->s3mrtgslide) { case 1: case 2: case 3: case 4: case 5: a->tmpvolume-=(1<<(a->s3mrtgslide-1)); break; case 6: a->tmpvolume=(2*a->tmpvolume)/3; break; case 7: a->tmpvolume>>=1; break; case 9: case 0xa: case 0xb: case 0xc: case 0xd: a->tmpvolume+=(1<<(a->s3mrtgslide-9)); break; case 0xe: a->tmpvolume=(3*a->tmpvolume)>>1; break; case 0xf: a->tmpvolume=a->tmpvolume<<1; break; } if (a->tmpvolume<0) a->tmpvolume=0; else if (a->tmpvolume>64) a->tmpvolume=64; } } a->retrig--; /* countdown */ } } return 0; } static int DoS3MEffectR(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat, q; UWORD temp=0; /* silence warning */ (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat = UniGetByte(); if (!tick) { if (dat&0x0f) a->trmdepth=dat&0xf; if (dat&0xf0) a->trmspd=(dat&0xf0)>>2; } q=(a->trmpos>>2)&0x1f; switch ((a->wavecontrol>>4)&3) { case 0: /* sine */ temp=VibratoTable[q]; break; case 1: /* ramp down */ q<<=3; if (a->trmpos<0) q=255-q; temp=q; break; case 2: /* square wave */ temp=255; break; case 3: /* random */ temp=getrandom(256); break; } temp*=a->trmdepth; temp>>=7; if (a->trmpos>=0) { a->volume=a->tmpvolume+temp; if (a->volume>64) a->volume=64; } else { a->volume=a->tmpvolume-temp; if (a->volume<0) a->volume=0; } a->ownvol = 1; if (tick) a->trmpos+=a->trmspd; return 0; } static int DoS3MEffectT(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE tempo; (void)flags; /* unused arg */ (void)a; /* unused arg */ (void)channel; /* unused arg */ tempo = UniGetByte(); if (tick || mod->patdly2) return 0; mod->bpm = (tempo < 32) ? 32 : tempo; return 0; } static int DoS3MEffectU(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat, q; UWORD temp = 0; /* silence warning */ (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat = UniGetByte(); if (!tick) { if (dat&0x0f) a->vibdepth=dat&0xf; if (dat&0xf0) a->vibspd=(dat&0xf0)>>2; } else if (a->main.period) { q=(a->vibpos>>2)&0x1f; switch (a->wavecontrol&3) { case 0: /* sine */ temp=VibratoTable[q]; break; case 1: /* ramp down */ q<<=3; if (a->vibpos<0) q=255-q; temp=q; break; case 2: /* square wave */ temp=255; break; case 3: /* random */ temp=getrandom(256); break; } temp*=a->vibdepth; temp>>=8; if (a->vibpos>=0) a->main.period=a->tmpperiod+temp; else a->main.period=a->tmpperiod-temp; a->ownper = 1; a->vibpos+=a->vibspd; } return 0; } /*========== Envelope helpers */ static int DoKeyOff(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { (void)tick; /* unused arg */ (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ a->main.keyoff|=KEY_OFF; if ((!(a->main.volflg&EF_ON))||(a->main.volflg&EF_LOOP)) a->main.keyoff=KEY_KILL; return 0; } static int DoKeyFade(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if ((tick>=dat)||(tick==mod->sngspd-1)) { a->main.keyoff=KEY_KILL; if (!(a->main.volflg&EF_ON)) a->main.fadevol=0; } return 0; } /*========== Fast Tracker effects */ /* DoXMEffect6 after DoXMEffectA */ static int DoXMEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE inf, lo, hi; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ inf = UniGetByte(); if (inf) a->s3mvolslide = inf; else inf = a->s3mvolslide; if (tick) { lo=inf&0xf; hi=inf>>4; if (!hi) { a->tmpvolume-=lo; if (a->tmpvolume<0) a->tmpvolume=0; } else { a->tmpvolume+=hi; if (a->tmpvolume>64) a->tmpvolume=64; } } return 0; } static int DoXMEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { if (a->main.period) DoVibrato(tick, a); return DoXMEffectA(tick, flags, a, mod, channel); } static int DoXMEffectE1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (!tick) { if (dat) a->fportupspd=dat; if (a->main.period) a->tmpperiod-=(a->fportupspd<<2); } return 0; } static int DoXMEffectE2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (!tick) { if (dat) a->fportdnspd=dat; if (a->main.period) a->tmpperiod+=(a->fportdnspd<<2); } return 0; } static int DoXMEffectEA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (!tick) if (dat) a->fslideupspd=dat; a->tmpvolume+=a->fslideupspd; if (a->tmpvolume>64) a->tmpvolume=64; return 0; } static int DoXMEffectEB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if (!tick) if (dat) a->fslidednspd=dat; a->tmpvolume-=a->fslidednspd; if (a->tmpvolume<0) a->tmpvolume=0; return 0; } static int DoXMEffectG(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { (void)tick; /* unused arg */ (void)flags; /* unused arg */ (void)a; /* unused arg */ (void)channel; /* unused arg */ mod->volume=UniGetByte()<<1; if (mod->volume>128) mod->volume=128; return 0; } static int DoXMEffectH(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE inf; (void)flags; /* unused arg */ (void)a; /* unused arg */ (void)channel; /* unused arg */ inf = UniGetByte(); if (tick) { if (inf) mod->globalslide=inf; else inf=mod->globalslide; if (inf & 0xf0) inf&=0xf0; mod->volume=mod->volume+((inf>>4)-(inf&0xf))*2; if (mod->volume<0) mod->volume=0; else if (mod->volume>128) mod->volume=128; } return 0; } static int DoXMEffectL(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat=UniGetByte(); if ((!tick)&&(a->main.i)) { UWORD points; INSTRUMENT *i=a->main.i; MP_VOICE *aout; if ((aout=a->slave)) { if (aout->venv.env) { points=i->volenv[i->volpts-1].pos; aout->venv.p=aout->venv.env[(dat>points)?points:dat].pos; } if (aout->penv.env) { points=i->panenv[i->panpts-1].pos; aout->penv.p=aout->penv.env[(dat>points)?points:dat].pos; } } } return 0; } static int DoXMEffectP(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE inf, lo, hi; SWORD pan; (void)flags; /* unused arg */ (void)channel; /* unused arg */ inf = UniGetByte(); if (!mod->panflag) return 0; if (inf) a->pansspd = inf; else inf =a->pansspd; if (tick) { lo=inf&0xf; hi=inf>>4; /* slide right has absolute priority */ if (hi) lo = 0; pan=((a->main.panning==PAN_SURROUND)?PAN_CENTER:a->main.panning)+hi-lo; a->main.panning=(panPAN_RIGHT?PAN_RIGHT:pan); } return 0; } static int DoXMEffectX1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat = UniGetByte(); if (dat) a->ffportupspd = dat; else dat = a->ffportupspd; if (a->main.period) if (!tick) { a->main.period-=dat; a->tmpperiod-=dat; a->ownper = 1; } return 0; } static int DoXMEffectX2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat = UniGetByte(); if (dat) a->ffportdnspd=dat; else dat = a->ffportdnspd; if (a->main.period) if (!tick) { a->main.period+=dat; a->tmpperiod+=dat; a->ownper = 1; } return 0; } /*========== Impulse Tracker effects */ static void DoITToneSlide(UWORD tick, MP_CONTROL *a, UBYTE dat) { if (dat) a->portspeed = dat; /* if we don't come from another note, ignore the slide and play the note as is */ if (!a->oldnote || !a->main.period) return; if ((!tick)&&(a->newsamp)){ a->main.kick=KICK_NOTE; a->main.start=-1; } else a->main.kick=(a->main.kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT; if (tick) { int dist; /* We have to slide a->main.period towards a->wantedperiod, compute the difference between those two values */ dist=a->main.period-a->wantedperiod; /* if they are equal or if portamentospeed is too big... */ if ((!dist)||((a->portspeed<<2)>abs(dist))) /* ... make tmpperiod equal tperiod */ a->tmpperiod=a->main.period=a->wantedperiod; else if (dist>0) { a->tmpperiod-=a->portspeed<<2; a->main.period-=a->portspeed<<2; /* dist>0 slide up */ } else { a->tmpperiod+=a->portspeed<<2; a->main.period+=a->portspeed<<2; /* dist<0 slide down */ } } else a->tmpperiod=a->main.period; a->ownper=1; } static int DoITEffectG(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ DoITToneSlide(tick, a, UniGetByte()); return 0; } static void DoITVibrato(UWORD tick, MP_CONTROL *a, UBYTE dat) { UBYTE q; UWORD temp=0; if (!tick) { if (dat&0x0f) a->vibdepth=dat&0xf; if (dat&0xf0) a->vibspd=(dat&0xf0)>>2; } if (!a->main.period) return; q=(a->vibpos>>2)&0x1f; switch (a->wavecontrol&3) { case 0: /* sine */ temp=VibratoTable[q]; break; case 1: /* square wave */ temp=255; break; case 2: /* ramp down */ q<<=3; if (a->vibpos<0) q=255-q; temp=q; break; case 3: /* random */ temp=getrandom(256); break; } temp*=a->vibdepth; temp>>=8; temp<<=2; if (a->vibpos>=0) a->main.period=a->tmpperiod+temp; else a->main.period=a->tmpperiod-temp; a->ownper=1; a->vibpos+=a->vibspd; } static int DoITEffectH(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ DoITVibrato(tick, a, UniGetByte()); return 0; } static int DoITEffectI(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE inf, on, off; (void)tick; /* unused arg */ (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ inf = UniGetByte(); if (inf) a->s3mtronof = inf; else { inf = a->s3mtronof; if (!inf) return 0; } on=(inf>>4); off=(inf&0xf); a->s3mtremor%=(on+off); a->volume=(a->s3mtremortmpvolume:0; a->ownvol = 1; a->s3mtremor++; return 0; } static int DoITEffectM(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { (void)tick; /* unused arg */ (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ a->main.chanvol=UniGetByte(); if (a->main.chanvol>64) a->main.chanvol=64; else if (a->main.chanvol<0) a->main.chanvol=0; return 0; } static int DoITEffectN(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE inf, lo, hi; (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ inf = UniGetByte(); if (inf) a->chanvolslide = inf; else inf = a->chanvolslide; lo=inf&0xf; hi=inf>>4; if (!hi) a->main.chanvol-=lo; else if (!lo) { a->main.chanvol+=hi; } else if (hi==0xf) { if (!tick) a->main.chanvol-=lo; } else if (lo==0xf) { if (!tick) a->main.chanvol+=hi; } if (a->main.chanvol<0) a->main.chanvol=0; else if (a->main.chanvol>64) a->main.chanvol=64; return 0; } static int DoITEffectP(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE inf, lo, hi; SWORD pan; (void)flags; /* unused arg */ (void)channel; /* unused arg */ inf = UniGetByte(); if (inf) a->pansspd = inf; else inf = a->pansspd; if (!mod->panflag) return 0; lo=inf&0xf; hi=inf>>4; pan=(a->main.panning==PAN_SURROUND)?PAN_CENTER:a->main.panning; if (!hi) pan+=lo<<2; else if (!lo) { pan-=hi<<2; } else if (hi==0xf) { if (!tick) pan+=lo<<2; } else if (lo==0xf) { if (!tick) pan-=hi<<2; } a->main.panning= (panPAN_RIGHT?PAN_RIGHT:pan); return 0; } static int DoITEffectT(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE tempo; SWORD temp; (void)tick; /* unused arg */ (void)flags; /* unused arg */ (void)a; /* unused arg */ (void)channel; /* unused arg */ tempo = UniGetByte(); if (mod->patdly2) return 0; temp = mod->bpm; if (tempo & 0x10) temp += (tempo & 0x0f); else temp -= tempo; mod->bpm=(temp>255)?255:(temp<1?1:temp); return 0; } static int DoITEffectU(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat, q; UWORD temp = 0; /* silence warning */ (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat = UniGetByte(); if (!tick) { if (dat&0x0f) a->vibdepth=dat&0xf; if (dat&0xf0) a->vibspd=(dat&0xf0)>>2; } if (a->main.period) { q=(a->vibpos>>2)&0x1f; switch (a->wavecontrol&3) { case 0: /* sine */ temp=VibratoTable[q]; break; case 1: /* square wave */ temp=255; break; case 2: /* ramp down */ q<<=3; if (a->vibpos<0) q=255-q; temp=q; break; case 3: /* random */ temp=getrandom(256); break; } temp*=a->vibdepth; temp>>=8; if (a->vibpos>=0) a->main.period=a->tmpperiod+temp; else a->main.period=a->tmpperiod-temp; a->ownper = 1; a->vibpos+=a->vibspd; } return 0; } static int DoITEffectW(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE inf, lo, hi; (void)flags; /* unused arg */ (void)a; /* unused arg */ (void)channel; /* unused arg */ inf = UniGetByte(); if (inf) mod->globalslide = inf; else inf = mod->globalslide; lo=inf&0xf; hi=inf>>4; if (!lo) { if (tick) mod->volume+=hi; } else if (!hi) { if (tick) mod->volume-=lo; } else if (lo==0xf) { if (!tick) mod->volume+=hi; } else if (hi==0xf) { if (!tick) mod->volume-=lo; } if (mod->volume<0) mod->volume=0; else if (mod->volume>128) mod->volume=128; return 0; } static int DoITEffectY(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat, q; SLONG temp = 0; /* silence warning */ (void)flags; /* unused arg */ dat=UniGetByte(); if (!tick) { if (dat&0x0f) a->panbdepth=(dat&0xf); if (dat&0xf0) a->panbspd=(dat&0xf0)>>4; } if (mod->panflag) { q=a->panbpos; switch (a->panbwave) { case 0: /* sine */ temp=PanbrelloTable[q]; break; case 1: /* square wave */ temp=(q<0x80)?64:0; break; case 2: /* ramp down */ q<<=3; temp=q; break; case 3: /* random */ temp=getrandom(256); break; } temp*=a->panbdepth; temp=(temp/8)+mod->panning[channel]; a->main.panning= (tempPAN_RIGHT?PAN_RIGHT:temp); a->panbpos+=a->panbspd; } return 0; } static void DoNNAEffects(MODULE *, MP_CONTROL *, UBYTE); /* Impulse/Scream Tracker Sxx effects. All Sxx effects share the same memory space. */ static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat, inf, c; dat = UniGetByte(); inf=dat&0xf; c=dat>>4; if (!dat) { c=a->sseffect; inf=a->ssdata; } else { a->sseffect=c; a->ssdata=inf; } switch (c) { case SS_GLISSANDO: /* S1x set glissando voice */ DoEEffects(tick, flags, a, mod, channel, 0x30|inf); break; case SS_FINETUNE: /* S2x set finetune */ DoEEffects(tick, flags, a, mod, channel, 0x50|inf); break; case SS_VIBWAVE: /* S3x set vibrato waveform */ DoEEffects(tick, flags, a, mod, channel, 0x40|inf); break; case SS_TREMWAVE: /* S4x set tremolo waveform */ DoEEffects(tick, flags, a, mod, channel, 0x70|inf); break; case SS_PANWAVE: /* S5x panbrello */ a->panbwave=inf; break; case SS_FRAMEDELAY: /* S6x delay x number of frames (patdly) */ DoEEffects(tick, flags, a, mod, channel, 0xe0|inf); break; case SS_S7EFFECTS: /* S7x instrument / NNA commands */ DoNNAEffects(mod, a, inf); break; case SS_PANNING: /* S8x set panning position */ DoEEffects(tick, flags, a, mod, channel, 0x80 | inf); break; case SS_SURROUND: /* S9x set surround sound */ if (mod->panflag) a->main.panning = mod->panning[channel] = PAN_SURROUND; break; case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */ if (!tick) { a->hioffset=inf<<16; a->main.start=a->hioffset|a->soffset; if ((a->main.s)&&(a->main.start>a->main.s->length)) a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)? a->main.s->loopstart:a->main.s->length; } break; case SS_PATLOOP: /* SBx pattern loop */ DoEEffects(tick, flags, a, mod, channel, 0x60|inf); break; case SS_NOTECUT: /* SCx notecut */ if (!inf) inf = 1; DoEEffects(tick, flags, a, mod, channel, 0xC0|inf); break; case SS_NOTEDELAY: /* SDx notedelay */ DoEEffects(tick, flags, a, mod, channel, 0xD0|inf); break; case SS_PATDELAY: /* SEx patterndelay */ DoEEffects(tick, flags, a, mod, channel, 0xE0|inf); break; } return 0; } /*========== Impulse Tracker Volume/Pan Column effects */ /* * All volume/pan column effects share the same memory space. */ static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE c, inf; (void)channel; /* unused arg */ c = UniGetByte(); inf = UniGetByte(); if ((!c)&&(!inf)) { c=a->voleffect; inf=a->voldata; } else { a->voleffect=c; a->voldata=inf; } if (c) switch (c) { case VOL_VOLUME: if (tick) break; if (inf>64) inf=64; a->tmpvolume=inf; break; case VOL_PANNING: if (mod->panflag) a->main.panning=inf; break; case VOL_VOLSLIDE: DoS3MVolSlide(tick, flags, a, inf); return 1; case VOL_PITCHSLIDEDN: if (a->main.period) DoS3MSlideDn(tick, a, inf); break; case VOL_PITCHSLIDEUP: if (a->main.period) DoS3MSlideUp(tick, a, inf); break; case VOL_PORTAMENTO: DoITToneSlide(tick, a, inf); break; case VOL_VIBRATO: DoITVibrato(tick, a, inf); break; } return 0; } /*========== UltraTracker effects */ static int DoULTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UWORD offset=UniGetWord(); (void)tick; /* unused arg */ (void)flags; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ if (offset) a->ultoffset=offset; a->main.start=a->ultoffset<<2; if ((a->main.s)&&(a->main.start>a->main.s->length)) a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)? a->main.s->loopstart:a->main.s->length; return 0; } /*========== OctaMED effects */ static int DoMEDSpeed(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UWORD speed=UniGetWord(); (void)tick; /* unused arg */ (void)flags; /* unused arg */ (void)a; /* unused arg */ (void)channel; /* unused arg */ mod->bpm=speed; return 0; } static int DoMEDEffectF1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/2)); return 0; } static int DoMEDEffectF2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { DoEEffects(tick, flags, a, mod, channel, 0xd0|(mod->sngspd/2)); return 0; } static int DoMEDEffectF3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/3)); return 0; } /*========== Oktalyzer effects */ static int DoOktArp(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { UBYTE dat, dat2; (void)mod; /* unused arg */ (void)channel; /* unused arg */ dat2 = UniGetByte(); /* arpeggio style */ dat = UniGetByte(); if (!tick) { if (!dat && (flags & UF_ARPMEM)) dat=a->arpmem; else a->arpmem=dat; } if (a->main.period) DoArpeggio(tick, flags, a, dat2); return 0; } /*========== General player functions */ static int DoNothing(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) { (void)tick; /* unused arg */ (void)flags; /* unused arg */ (void)a; /* unused arg */ (void)mod; /* unused arg */ (void)channel; /* unused arg */ UniSkipOpcode(); return 0; } typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD); static effect_func effects[UNI_LAST] = { DoNothing, /* 0 */ DoNothing, /* UNI_NOTE */ DoNothing, /* UNI_INSTRUMENT */ DoPTEffect0, /* UNI_PTEFFECT0 */ DoPTEffect1, /* UNI_PTEFFECT1 */ DoPTEffect2, /* UNI_PTEFFECT2 */ DoPTEffect3, /* UNI_PTEFFECT3 */ DoPTEffect4, /* UNI_PTEFFECT4 */ DoPTEffect5, /* UNI_PTEFFECT5 */ DoPTEffect6, /* UNI_PTEFFECT6 */ DoPTEffect7, /* UNI_PTEFFECT7 */ DoPTEffect8, /* UNI_PTEFFECT8 */ DoPTEffect9, /* UNI_PTEFFECT9 */ DoPTEffectA, /* UNI_PTEFFECTA */ DoPTEffectB, /* UNI_PTEFFECTB */ DoPTEffectC, /* UNI_PTEFFECTC */ DoPTEffectD, /* UNI_PTEFFECTD */ DoPTEffectE, /* UNI_PTEFFECTE */ DoPTEffectF, /* UNI_PTEFFECTF */ DoS3MEffectA, /* UNI_S3MEFFECTA */ DoS3MEffectD, /* UNI_S3MEFFECTD */ DoS3MEffectE, /* UNI_S3MEFFECTE */ DoS3MEffectF, /* UNI_S3MEFFECTF */ DoS3MEffectI, /* UNI_S3MEFFECTI */ DoS3MEffectQ, /* UNI_S3MEFFECTQ */ DoS3MEffectR, /* UNI_S3MEFFECTR */ DoS3MEffectT, /* UNI_S3MEFFECTT */ DoS3MEffectU, /* UNI_S3MEFFECTU */ DoKeyOff, /* UNI_KEYOFF */ DoKeyFade, /* UNI_KEYFADE */ DoVolEffects, /* UNI_VOLEFFECTS */ DoPTEffect4, /* UNI_XMEFFECT4 */ DoXMEffect6, /* UNI_XMEFFECT6 */ DoXMEffectA, /* UNI_XMEFFECTA */ DoXMEffectE1, /* UNI_XMEFFECTE1 */ DoXMEffectE2, /* UNI_XMEFFECTE2 */ DoXMEffectEA, /* UNI_XMEFFECTEA */ DoXMEffectEB, /* UNI_XMEFFECTEB */ DoXMEffectG, /* UNI_XMEFFECTG */ DoXMEffectH, /* UNI_XMEFFECTH */ DoXMEffectL, /* UNI_XMEFFECTL */ DoXMEffectP, /* UNI_XMEFFECTP */ DoXMEffectX1, /* UNI_XMEFFECTX1 */ DoXMEffectX2, /* UNI_XMEFFECTX2 */ DoITEffectG, /* UNI_ITEFFECTG */ DoITEffectH, /* UNI_ITEFFECTH */ DoITEffectI, /* UNI_ITEFFECTI */ DoITEffectM, /* UNI_ITEFFECTM */ DoITEffectN, /* UNI_ITEFFECTN */ DoITEffectP, /* UNI_ITEFFECTP */ DoITEffectT, /* UNI_ITEFFECTT */ DoITEffectU, /* UNI_ITEFFECTU */ DoITEffectW, /* UNI_ITEFFECTW */ DoITEffectY, /* UNI_ITEFFECTY */ DoNothing, /* UNI_ITEFFECTZ */ DoITEffectS0, /* UNI_ITEFFECTS0 */ DoULTEffect9, /* UNI_ULTEFFECT9 */ DoMEDSpeed, /* UNI_MEDSPEED */ DoMEDEffectF1, /* UNI_MEDEFFECTF1 */ DoMEDEffectF2, /* UNI_MEDEFFECTF2 */ DoMEDEffectF3, /* UNI_MEDEFFECTF3 */ DoOktArp, /* UNI_OKTARP */ }; static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a) { UWORD tick = mod->vbtick; UWORD flags = mod->flags; UBYTE c; int explicitslides = 0; effect_func f; while((c=UniGetByte())) { f = effects[c]; if (f != DoNothing) a->sliding = 0; explicitslides |= f(tick, flags, a, mod, channel); } return explicitslides; } static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat) { int t; MP_VOICE *aout; dat&=0xf; aout=(a->slave)?a->slave:NULL; switch (dat) { case 0x0: /* past note cut */ for (t=0;tvoice[t].master==a) mod->voice[t].main.fadevol=0; break; case 0x1: /* past note off */ for (t=0;tvoice[t].master==a) { mod->voice[t].main.keyoff|=KEY_OFF; if ((!(mod->voice[t].venv.flg & EF_ON))|| (mod->voice[t].venv.flg & EF_LOOP)) mod->voice[t].main.keyoff=KEY_KILL; } break; case 0x2: /* past note fade */ for (t=0;tvoice[t].master==a) mod->voice[t].main.keyoff|=KEY_FADE; break; case 0x3: /* set NNA note cut */ a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CUT; break; case 0x4: /* set NNA note continue */ a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CONTINUE; break; case 0x5: /* set NNA note off */ a->main.nna=(a->main.nna&~NNA_MASK)|NNA_OFF; break; case 0x6: /* set NNA note fade */ a->main.nna=(a->main.nna&~NNA_MASK)|NNA_FADE; break; case 0x7: /* disable volume envelope */ if (aout) aout->main.volflg&=~EF_ON; break; case 0x8: /* enable volume envelope */ if (aout) aout->main.volflg|=EF_ON; break; case 0x9: /* disable panning envelope */ if (aout) aout->main.panflg&=~EF_ON; break; case 0xa: /* enable panning envelope */ if (aout) aout->main.panflg|=EF_ON; break; case 0xb: /* disable pitch envelope */ if (aout) aout->main.pitflg&=~EF_ON; break; case 0xc: /* enable pitch envelope */ if (aout) aout->main.pitflg|=EF_ON; break; } } void pt_UpdateVoices(MODULE *mod, int max_volume) { SWORD envpan,envvol,envpit,channel; UWORD playperiod; SLONG vibval,vibdpt; ULONG tmpvol; MP_VOICE *aout; INSTRUMENT *i; SAMPLE *s; mod->totalchn=mod->realchn=0; for (channel=0;channelvoice[channel]; i=aout->main.i; s=aout->main.s; if (!s || !s->length) continue; if (aout->main.period<40) aout->main.period=40; else if (aout->main.period>50000) aout->main.period=50000; if ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_KEYOFF)) { Voice_Play_internal(channel,s,(aout->main.start==-1)? ((s->flags&SF_UST_LOOP)?s->loopstart:0):aout->main.start); aout->main.fadevol=32768; aout->aswppos=0; } envvol = 256; envpan = PAN_CENTER; envpit = 32; if (i && ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_ENV))) { if (aout->main.volflg & EF_ON) envvol = StartEnvelope(&aout->venv,aout->main.volflg, i->volpts,i->volsusbeg,i->volsusend, i->volbeg,i->volend,i->volenv,aout->main.keyoff); if (aout->main.panflg & EF_ON) envpan = StartEnvelope(&aout->penv,aout->main.panflg, i->panpts,i->pansusbeg,i->pansusend, i->panbeg,i->panend,i->panenv,aout->main.keyoff); if (aout->main.pitflg & EF_ON) envpit = StartEnvelope(&aout->cenv,aout->main.pitflg, i->pitpts,i->pitsusbeg,i->pitsusend, i->pitbeg,i->pitend,i->pitenv,aout->main.keyoff); if (aout->cenv.flg & EF_ON) aout->masterperiod=GetPeriod(mod->flags, (UWORD)aout->main.note<<1, aout->master->speed); } else { if (aout->main.volflg & EF_ON) envvol = ProcessEnvelope(aout,&aout->venv,256); if (aout->main.panflg & EF_ON) envpan = ProcessEnvelope(aout,&aout->penv,PAN_CENTER); if (aout->main.pitflg & EF_ON) envpit = ProcessEnvelope(aout,&aout->cenv,32); } aout->main.kick=KICK_ABSENT; tmpvol = aout->main.fadevol; /* max 32768 */ tmpvol *= aout->main.chanvol; /* * max 64 */ tmpvol *= aout->main.outvolume; /* * max 256 */ tmpvol /= (256 * 64); /* tmpvol is max 32768 again */ aout->totalvol = tmpvol >> 2; /* used to determine samplevolume */ tmpvol *= envvol; /* * max 256 */ tmpvol *= mod->volume; /* * max 128 */ tmpvol /= (128 * 256 * 128); /* fade out */ if (mod->sngpos>=mod->numpos) tmpvol=0; else tmpvol=(tmpvol*max_volume)/128; if ((aout->masterchn!=-1)&& mod->control[aout->masterchn].muted) Voice_SetVolume_internal(channel,0); else { Voice_SetVolume_internal(channel,tmpvol); if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout)) mod->realchn++; mod->totalchn++; } if (aout->main.panning==PAN_SURROUND) Voice_SetPanning_internal(channel,PAN_SURROUND); else if ((mod->panflag)&&(aout->penv.flg & EF_ON)) Voice_SetPanning_internal(channel, DoPan(envpan,aout->main.panning)); else Voice_SetPanning_internal(channel,aout->main.panning); if (aout->main.period && s->vibdepth) switch (s->vibtype) { case 0: vibval=avibtab[s->avibpos&127]; if (aout->avibpos & 0x80) vibval=-vibval; break; case 1: vibval=64; if (aout->avibpos & 0x80) vibval=-vibval; break; case 2: vibval=63-(((aout->avibpos+128)&255)>>1); break; default: vibval=(((aout->avibpos+128)&255)>>1)-64; break; } else vibval=0; if (s->vibflags & AV_IT) { if ((aout->aswppos>>8)vibdepth) { aout->aswppos += s->vibsweep; vibdpt=aout->aswppos; } else vibdpt=s->vibdepth<<8; vibval=(vibval*vibdpt)>>16; if (aout->mflag) { if (!(mod->flags&UF_LINEAR)) vibval>>=1; aout->main.period-=vibval; } } else { /* do XM style auto-vibrato */ if (!(aout->main.keyoff & KEY_OFF)) { if (aout->aswpposvibsweep) { vibdpt=(aout->aswppos*s->vibdepth)/s->vibsweep; aout->aswppos++; } else vibdpt=s->vibdepth; } else { /* keyoff -> depth becomes 0 if final depth wasn't reached or stays at final level if depth WAS reached */ if (aout->aswppos>=s->vibsweep) vibdpt=s->vibdepth; else vibdpt=0; } vibval=(vibval*vibdpt)>>8; aout->main.period-=vibval; } /* update vibrato position */ aout->avibpos=(aout->avibpos+s->vibrate)&0xff; /* process pitch envelope */ playperiod=aout->main.period; if ((aout->main.pitflg&EF_ON)&&(envpit!=32)) { long p1; envpit-=32; if ((aout->main.note<<1)+envpit<=0) envpit=-(aout->main.note<<1); p1=GetPeriod(mod->flags, ((UWORD)aout->main.note<<1)+envpit, aout->master->speed)-aout->masterperiod; if (p1>0) { if ((UWORD)(playperiod+p1)<=playperiod) { p1=0; aout->main.keyoff|=KEY_OFF; } } else if (p1<0) { if ((UWORD)(playperiod+p1)>=playperiod) { p1=0; aout->main.keyoff|=KEY_OFF; } } playperiod+=p1; } if (!aout->main.fadevol) { /* check for a dead note (fadevol=0) */ Voice_Stop_internal(channel); mod->totalchn--; if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout)) mod->realchn--; } else { Voice_SetFrequency_internal(channel, getfrequency(mod->flags,playperiod)); /* if keyfade, start substracting fadeoutspeed from fadevol: */ if ((i)&&(aout->main.keyoff&KEY_FADE)) { if (aout->main.fadevol>=i->volfade) aout->main.fadevol-=i->volfade; else aout->main.fadevol=0; } } md_bpm=mod->bpm+mod->relspd; if (md_bpm<32) md_bpm=32; else if ((!(mod->flags&UF_HIGHBPM)) && md_bpm>255) md_bpm=255; } } /* Handles new notes or instruments */ void pt_Notes(MODULE *mod) { SWORD channel; MP_CONTROL *a; UBYTE c,inst; int tr,funky; /* funky is set to indicate note or instrument change */ for (channel=0;channelnumchn;channel++) { a=&mod->control[channel]; if (mod->sngpos>=mod->numpos) { tr=mod->numtrk; mod->numrow=0; } else { tr=mod->patterns[(mod->positions[mod->sngpos]*mod->numchn)+channel]; mod->numrow=mod->pattrows[mod->positions[mod->sngpos]]; } a->row=(trnumtrk)?UniFindRow(mod->tracks[tr],mod->patpos):NULL; a->newsamp=0; if (!mod->vbtick) a->main.notedelay=0; if (!a->row) continue; UniSetRow(a->row); funky=0; while((c=UniGetByte())) switch (c) { case UNI_NOTE: funky|=1; a->oldnote=a->anote,a->anote=UniGetByte(); a->main.kick =KICK_NOTE; a->main.start=-1; a->sliding=0; /* retrig tremolo and vibrato waves ? */ if (!(a->wavecontrol & 0x80)) a->trmpos=0; if (!(a->wavecontrol & 0x08)) a->vibpos=0; if (!a->panbwave) a->panbpos=0; break; case UNI_INSTRUMENT: inst=UniGetByte(); if (inst>=mod->numins) break; /* safety valve */ funky|=2; a->main.i=(mod->flags & UF_INST)?&mod->instruments[inst]:NULL; a->retrig=0; a->s3mtremor=0; a->ultoffset=0; a->main.sample=inst; break; default: UniSkipOpcode(); break; } if (funky) { INSTRUMENT *i; SAMPLE *s; if ((i=a->main.i)) { if (i->samplenumber[a->anote] >= mod->numsmp) continue; s=&mod->samples[i->samplenumber[a->anote]]; a->main.note=i->samplenote[a->anote]; } else { a->main.note=a->anote; s=&mod->samples[a->main.sample]; } if (a->main.s!=s) { a->main.s=s; a->newsamp=a->main.period; } /* channel or instrument determined panning ? */ a->main.panning=mod->panning[channel]; if (s->flags & SF_OWNPAN) a->main.panning=s->panning; else if ((i)&&(i->flags & IF_OWNPAN)) a->main.panning=i->panning; a->main.handle=s->handle; a->speed=s->speed; if (i) { if ((mod->panflag)&&(i->flags & IF_PITCHPAN) &&(a->main.panning!=PAN_SURROUND)){ a->main.panning+= ((a->anote-i->pitpancenter)*i->pitpansep)/8; if (a->main.panningmain.panning=PAN_LEFT; else if (a->main.panning>PAN_RIGHT) a->main.panning=PAN_RIGHT; } a->main.pitflg=i->pitflg; a->main.volflg=i->volflg; a->main.panflg=i->panflg; a->main.nna=i->nnatype; a->dca=i->dca; a->dct=i->dct; } else { a->main.pitflg=a->main.volflg=a->main.panflg=0; a->main.nna=a->dca=0; a->dct=DCT_OFF; } if (funky&2) /* instrument change */ { /* IT random volume variations: 0:8 bit fixed, and one bit for sign. */ a->volume=a->tmpvolume=s->volume; if ((s)&&(i)) { if (i->rvolvar) { a->volume=a->tmpvolume=s->volume+ ((s->volume*((SLONG)i->rvolvar*(SLONG)getrandom(512) ))/25600); if (a->volume<0) a->volume=a->tmpvolume=0; else if (a->volume>64) a->volume=a->tmpvolume=64; } if ((mod->panflag)&&(a->main.panning!=PAN_SURROUND)) { a->main.panning+=((a->main.panning*((SLONG)i->rpanvar* (SLONG)getrandom(512)))/25600); if (a->main.panningmain.panning=PAN_LEFT; else if (a->main.panning>PAN_RIGHT) a->main.panning=PAN_RIGHT; } } } a->wantedperiod=a->tmpperiod= GetPeriod(mod->flags, (UWORD)a->main.note<<1,a->speed); a->main.keyoff=KEY_KICK; } } } /* Handles effects */ void pt_EffectsPass1(MODULE *mod) { SWORD channel; MP_CONTROL *a; MP_VOICE *aout; int explicitslides; for (channel=0;channelnumchn;channel++) { a=&mod->control[channel]; if ((aout=a->slave)) { a->main.fadevol=aout->main.fadevol; a->main.period=aout->main.period; if (a->main.kick==KICK_KEYOFF) a->main.keyoff=aout->main.keyoff; } if (!a->row) continue; UniSetRow(a->row); a->ownper=a->ownvol=0; explicitslides = pt_playeffects(mod, channel, a); /* continue volume slide if necessary for XM and IT */ if (mod->flags&UF_BGSLIDES) { if (!explicitslides && a->sliding) DoS3MVolSlide(mod->vbtick, mod->flags, a, 0); else if (a->tmpvolume) a->sliding = explicitslides; } if (!a->ownper) a->main.period=a->tmpperiod; if (!a->ownvol) a->volume=a->tmpvolume; if (a->main.s) { if (a->main.i) a->main.outvolume= (a->volume*a->main.s->globvol*a->main.i->globvol)>>10; else a->main.outvolume=(a->volume*a->main.s->globvol)>>4; if (a->main.outvolume>256) a->main.outvolume=256; else if (a->main.outvolume<0) a->main.outvolume=0; } } } /* NNA management */ void pt_NNA(MODULE *mod) { SWORD channel; MP_CONTROL *a; for (channel=0;channelnumchn;channel++) { a=&mod->control[channel]; if (a->main.kick==KICK_NOTE) { BOOL kill=0; if (a->slave) { MP_VOICE *aout; aout=a->slave; if (aout->main.nna & NNA_MASK) { /* Make sure the old MP_VOICE channel knows it has no master now ! */ a->slave=NULL; /* assume the channel is taken by NNA */ aout->mflag=0; switch (aout->main.nna) { case NNA_CONTINUE: /* continue note, do nothing */ break; case NNA_OFF: /* note off */ aout->main.keyoff|=KEY_OFF; if ((!(aout->main.volflg & EF_ON))|| (aout->main.volflg & EF_LOOP)) aout->main.keyoff=KEY_KILL; break; case NNA_FADE: aout->main.keyoff |= KEY_FADE; break; } } } if (a->dct!=DCT_OFF) { int t; for (t=0;tvoice[t].masterchn==channel)&& (a->main.sample==mod->voice[t].main.sample)) { kill=0; switch (a->dct) { case DCT_NOTE: if (a->main.note==mod->voice[t].main.note) kill=1; break; case DCT_SAMPLE: if (a->main.handle==mod->voice[t].main.handle) kill=1; break; case DCT_INST: kill=1; break; } if (kill) switch (a->dca) { case DCA_CUT: mod->voice[t].main.fadevol=0; break; case DCA_OFF: mod->voice[t].main.keyoff|=KEY_OFF; if ((!(mod->voice[t].main.volflg&EF_ON))|| (mod->voice[t].main.volflg&EF_LOOP)) mod->voice[t].main.keyoff=KEY_KILL; break; case DCA_FADE: mod->voice[t].main.keyoff|=KEY_FADE; break; } } } } /* if (a->main.kick==KICK_NOTE) */ } } /* Setup module and NNA voices */ void pt_SetupVoices(MODULE *mod) { SWORD channel; MP_CONTROL *a; MP_VOICE *aout; for (channel=0;channelnumchn;channel++) { a=&mod->control[channel]; if (a->main.notedelay) continue; if (a->main.kick==KICK_NOTE) { /* if no channel was cut above, find an empty or quiet channel here */ if (mod->flags&UF_NNA) { if (!a->slave) { int newchn; if ((newchn=MP_FindEmptyChannel(mod))!=-1) a->slave=&mod->voice[a->slavechn=newchn]; } } else a->slave=&mod->voice[a->slavechn=channel]; /* assign parts of MP_VOICE only done for a KICK_NOTE */ if ((aout=a->slave)) { if (aout->mflag && aout->master) aout->master->slave=NULL; aout->master=a; a->slave=aout; aout->masterchn=channel; aout->mflag=1; } } else aout=a->slave; if (aout) aout->main=a->main; a->main.kick=KICK_ABSENT; } } /* second effect pass */ void pt_EffectsPass2(MODULE *mod) { SWORD channel; MP_CONTROL *a; UBYTE c; for (channel=0;channelnumchn;channel++) { a=&mod->control[channel]; if (!a->row) continue; UniSetRow(a->row); while((c=UniGetByte())) if (c==UNI_ITEFFECTS0) { c=UniGetByte(); if ((c>>4)==SS_S7EFFECTS) DoNNAEffects(mod, a, c&0xf); } else UniSkipOpcode(); } } void Player_HandleTick(void) { SWORD channel; int max_volume; #if 0 /* don't handle the very first ticks, this allows the other hardware to settle down so we don't loose any starting notes */ if (isfirst) { isfirst--; return; } #endif if ((!pf)||(pf->forbid)||(pf->sngpos>=pf->numpos)) return; /* update time counter (sngtime is in milliseconds (in fact 2^-10)) */ pf->sngremainder+=(1<<9)*5; /* thus 2.5*(1<<10), since fps=0.4xtempo */ pf->sngtime+=pf->sngremainder/pf->bpm; pf->sngremainder%=pf->bpm; if (++pf->vbtick>=pf->sngspd) { if (pf->pat_repcrazy) pf->pat_repcrazy=0; /* play 2 times row 0 */ else pf->patpos++; pf->vbtick=0; /* process pattern-delay. pf->patdly2 is the counter and pf->patdly is the command memory. */ if (pf->patdly) pf->patdly2=pf->patdly,pf->patdly=0; if (pf->patdly2) { /* patterndelay active */ if (--pf->patdly2) /* so turn back pf->patpos by 1 */ if (pf->patpos) pf->patpos--; } /* do we have to get a new patternpointer ? (when pf->patpos reaches the pattern size, or when a patternbreak is active) */ if (((pf->patpos>=pf->numrow)&&(pf->numrow>0))&&(!pf->posjmp)) pf->posjmp=3; if (pf->posjmp) { pf->patpos=pf->numrow?(pf->patbrk%pf->numrow):0; pf->pat_repcrazy=0; pf->sngpos+=(pf->posjmp-2); for (channel=0;channelnumchn;channel++) pf->control[channel].pat_reppos=-1; pf->patbrk=pf->posjmp=0; /* handle the "---" (end of song) pattern since it can occur *inside* the module in some formats */ if ((pf->sngpos>=pf->numpos)|| (pf->positions[pf->sngpos]==LAST_PATTERN)) { if (!pf->wrap) return; if (!(pf->sngpos=pf->reppos)) { pf->volume=pf->initvolume>128?128:pf->initvolume; if(pf->initspeed!=0) pf->sngspd=pf->initspeed<32?pf->initspeed:32; else pf->sngspd=6; pf->bpm=pf->inittempo<32?32:pf->inittempo; } } if (pf->sngpos<0) pf->sngpos=pf->numpos-1; } if (!pf->patdly2) pt_Notes(pf); } /* Fade global volume if enabled and we're playing the last pattern */ if (((pf->sngpos==pf->numpos-1)|| (pf->positions[pf->sngpos+1]==LAST_PATTERN))&& (pf->fadeout)) max_volume=pf->numrow?((pf->numrow-pf->patpos)*128)/pf->numrow:0; else max_volume=128; pt_EffectsPass1(pf); if (pf->flags&UF_NNA) pt_NNA(pf); pt_SetupVoices(pf); pt_EffectsPass2(pf); /* now set up the actual hardware channel playback information */ pt_UpdateVoices(pf, max_volume); } static void Player_Init_internal(MODULE* mod) { int t; for (t=0;tnumchn;t++) { mod->control[t].main.chanvol=mod->chanvol[t]; mod->control[t].main.panning=mod->panning[t]; } mod->sngtime=0; mod->sngremainder=0; mod->pat_repcrazy=0; mod->sngpos=0; if(mod->initspeed!=0) mod->sngspd=mod->initspeed<32?mod->initspeed:32; else mod->sngspd=6; mod->volume=mod->initvolume>128?128:mod->initvolume; mod->vbtick=mod->sngspd; mod->patdly=0; mod->patdly2=0; mod->bpm=mod->inittempo<32?32:mod->inittempo; mod->realchn=0; mod->patpos=0; mod->posjmp=2; /* make sure the player fetches the first note */ mod->numrow=-1; mod->patbrk=0; } BOOL Player_Init(MODULE* mod) { mod->extspd=1; mod->panflag=1; mod->wrap=0; mod->loop=1; mod->fadeout=0; mod->relspd=0; /* make sure the player doesn't start with garbage */ if (!(mod->control=(MP_CONTROL*)MikMod_calloc(mod->numchn,sizeof(MP_CONTROL)))) return 1; if (!(mod->voice=(MP_VOICE*)MikMod_calloc(md_sngchn,sizeof(MP_VOICE)))) return 1; Player_Init_internal(mod); return 0; } void Player_Exit_internal(MODULE* mod) { if (!mod) return; /* Stop playback if necessary */ if (mod==pf) { Player_Stop_internal(); pf=NULL; } if (mod->control) MikMod_free(mod->control); if (mod->voice) MikMod_free(mod->voice); mod->control=NULL; mod->voice=NULL; } void Player_Exit(MODULE* mod) { MUTEX_LOCK(vars); Player_Exit_internal(mod); MUTEX_UNLOCK(vars); } MIKMODAPI void Player_SetVolume(SWORD volume) { MUTEX_LOCK(vars); if (pf) pf->volume=(volume<0)?0:(volume>128)?128:volume; MUTEX_UNLOCK(vars); } MIKMODAPI MODULE* Player_GetModule(void) { MODULE* result; MUTEX_LOCK(vars); result=pf; MUTEX_UNLOCK(vars); return result; } MIKMODAPI void Player_Start(MODULE *mod) { int t; if (!mod) return; if (!MikMod_Active()) MikMod_EnableOutput(); mod->forbid=0; MUTEX_LOCK(vars); if (pf!=mod) { /* new song is being started, so completely stop out the old one. */ if (pf) pf->forbid=1; for (t=0;tforbid=1; pf=NULL; } MIKMODAPI void Player_Stop(void) { MUTEX_LOCK(vars); Player_Stop_internal(); MUTEX_UNLOCK(vars); } MIKMODAPI BOOL Player_Active(void) { BOOL result=0; MUTEX_LOCK(vars); if (pf) result=(!(pf->sngpos>=pf->numpos)); MUTEX_UNLOCK(vars); return result; } MIKMODAPI void Player_NextPosition(void) { MUTEX_LOCK(vars); if (pf) { int t; pf->forbid=1; pf->posjmp=3; pf->patbrk=0; pf->vbtick=pf->sngspd; for (t=0;tvoice[t].main.i=NULL; pf->voice[t].main.s=NULL; } for (t=0;tnumchn;t++) { pf->control[t].main.i=NULL; pf->control[t].main.s=NULL; } pf->forbid=0; } MUTEX_UNLOCK(vars); } MIKMODAPI void Player_PrevPosition(void) { MUTEX_LOCK(vars); if (pf) { int t; pf->forbid=1; pf->posjmp=1; pf->patbrk=0; pf->vbtick=pf->sngspd; for (t=0;tvoice[t].main.i=NULL; pf->voice[t].main.s=NULL; } for (t=0;tnumchn;t++) { pf->control[t].main.i=NULL; pf->control[t].main.s=NULL; } pf->forbid=0; } MUTEX_UNLOCK(vars); } MIKMODAPI void Player_SetPosition(UWORD pos) { MUTEX_LOCK(vars); if (pf) { int t; pf->forbid=1; if (pos>=pf->numpos) pos=pf->numpos; pf->posjmp=2; pf->patbrk=0; pf->sngpos=pos; pf->vbtick=pf->sngspd; for (t=0;tvoice[t].main.i=NULL; pf->voice[t].main.s=NULL; } for (t=0;tnumchn;t++) { pf->control[t].main.i=NULL; pf->control[t].main.s=NULL; } pf->forbid=0; if (!pos) Player_Init_internal(pf); } MUTEX_UNLOCK(vars); } static void Player_Unmute_internal(SLONG arg1,va_list ap) { SLONG t,arg2,arg3=0; if (pf) { switch (arg1) { case MUTE_INCLUSIVE: if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))|| (arg2>arg3)||(arg3>=pf->numchn)) return; for (;arg2numchn && arg2<=arg3;arg2++) pf->control[arg2].muted=0; break; case MUTE_EXCLUSIVE: if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))|| (arg2>arg3)||(arg3>=pf->numchn)) return; for (t=0;tnumchn;t++) { if ((t>=arg2) && (t<=arg3)) continue; pf->control[t].muted=0; } break; default: if (arg1numchn) pf->control[arg1].muted=0; break; } } } MIKMODAPI void Player_Unmute(SLONG arg1, ...) { va_list args; va_start(args,arg1); MUTEX_LOCK(vars); Player_Unmute_internal(arg1,args); MUTEX_UNLOCK(vars); va_end(args); } static void Player_Mute_internal(SLONG arg1,va_list ap) { SLONG t,arg2,arg3=0; if (pf) { switch (arg1) { case MUTE_INCLUSIVE: if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))|| (arg2>arg3)||(arg3>=pf->numchn)) return; for (;arg2numchn && arg2<=arg3;arg2++) pf->control[arg2].muted=1; break; case MUTE_EXCLUSIVE: if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))|| (arg2>arg3)||(arg3>=pf->numchn)) return; for (t=0;tnumchn;t++) { if ((t>=arg2) && (t<=arg3)) continue; pf->control[t].muted=1; } break; default: if (arg1numchn) pf->control[arg1].muted=1; break; } } } MIKMODAPI void Player_Mute(SLONG arg1,...) { va_list args; va_start(args,arg1); MUTEX_LOCK(vars); Player_Mute_internal(arg1,args); MUTEX_UNLOCK(vars); va_end(args); } static void Player_ToggleMute_internal(SLONG arg1,va_list ap) { SLONG arg2,arg3=0; SLONG t; if (pf) { switch (arg1) { case MUTE_INCLUSIVE: if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))|| (arg2>arg3)||(arg3>=pf->numchn)) return; for (;arg2numchn && arg2<=arg3;arg2++) pf->control[arg2].muted=1-pf->control[arg2].muted; break; case MUTE_EXCLUSIVE: if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))|| (arg2>arg3)||(arg3>=pf->numchn)) return; for (t=0;tnumchn;t++) { if ((t>=arg2) && (t<=arg3)) continue; pf->control[t].muted=1-pf->control[t].muted; } break; default: if (arg1numchn) pf->control[arg1].muted=1-pf->control[arg1].muted; break; } } } MIKMODAPI void Player_ToggleMute(SLONG arg1,...) { va_list args; va_start(args,arg1); MUTEX_LOCK(vars); Player_ToggleMute_internal(arg1,args); MUTEX_UNLOCK(vars); va_end(args); } MIKMODAPI BOOL Player_Muted(UBYTE chan) { BOOL result=1; MUTEX_LOCK(vars); if (pf) result=(channumchn)?pf->control[chan].muted:1; MUTEX_UNLOCK(vars); return result; } MIKMODAPI int Player_GetChannelVoice(UBYTE chan) { int result=0; MUTEX_LOCK(vars); if (pf) result=(channumchn)?pf->control[chan].slavechn:-1; MUTEX_UNLOCK(vars); return result; } MIKMODAPI UWORD Player_GetChannelPeriod(UBYTE chan) { UWORD result=0; MUTEX_LOCK(vars); if (pf) result=(channumchn)?pf->control[chan].main.period:0; MUTEX_UNLOCK(vars); return result; } BOOL Player_Paused_internal(void) { return pf?pf->forbid:1; } MIKMODAPI BOOL Player_Paused(void) { BOOL result; MUTEX_LOCK(vars); result=Player_Paused_internal(); MUTEX_UNLOCK(vars); return result; } MIKMODAPI void Player_TogglePause(void) { MUTEX_LOCK(vars); if (pf) pf->forbid=1-pf->forbid; MUTEX_UNLOCK(vars); } MIKMODAPI void Player_SetSpeed(UWORD speed) { MUTEX_LOCK(vars); if (pf) pf->sngspd=speed?(speed<32?speed:32):1; MUTEX_UNLOCK(vars); } MIKMODAPI void Player_SetTempo(UWORD tempo) { if (tempo<32) tempo=32; MUTEX_LOCK(vars); if (pf) { if ((!(pf->flags&UF_HIGHBPM))&&(tempo>255)) tempo=255; pf->bpm=tempo; } MUTEX_UNLOCK(vars); } /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/virtch.c0000600000175000017500000006170410543202047017470 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: virtch.c 2421 2006-08-19 00:36:21Z avolkov $ Sample mixing routines, using a 32 bits mixing buffer. ==============================================================================*/ /* Optional features include: (a) 4-step reverb (for 16 bit output only) (b) Interpolation of sample data during mixing (c) Dolby Surround Sound */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #ifdef HAVE_MEMORY_H #include #endif #include #include "mikmod_internals.h" /* Constant definitions ==================== BITSHIFT Controls the maximum volume of the sound output. All data is shifted right by BITSHIFT after being mixed. Higher values result in quieter sound and less chance of distortion. REVERBERATION Controls the duration of the reverb. Larger values represent a shorter reverb loop. Smaller values extend the reverb but can result in more of an echo-ish sound. */ #define BITSHIFT 9 #define REVERBERATION 110000L #define FRACBITS 11 #define FRACMASK ((1L< sample has to be restarted */ UBYTE active; /* =1 -> sample is playing */ UWORD flags; /* 16/8 bits looping/one-shot */ SWORD handle; /* identifies the sample */ ULONG start; /* start index */ ULONG size; /* samplesize */ ULONG reppos; /* loop start */ ULONG repend; /* loop end */ ULONG frq; /* current frequency */ int vol; /* current volume */ int pan; /* current panning position */ int rampvol; int lvolsel,rvolsel; /* Volume factor in range 0-255 */ int oldlvol,oldrvol; SLONGLONG current; /* current index in the sample */ SLONGLONG increment; /* increment value */ } VINFO; static SWORD **Samples; static VINFO *vinf=NULL,*vnf; static long tickleft,samplesthatfit,vc_memory=0; static int vc_softchn; static SLONGLONG idxsize,idxlpos,idxlend; static SLONG *vc_tickbuf=NULL; static UWORD vc_mode; /* Reverb control variables */ static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8; static ULONG RVRindex; /* For Mono or Left Channel */ static SLONG *RVbufL1=NULL,*RVbufL2=NULL,*RVbufL3=NULL,*RVbufL4=NULL, *RVbufL5=NULL,*RVbufL6=NULL,*RVbufL7=NULL,*RVbufL8=NULL; /* For Stereo only (Right Channel) */ static SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL, *RVbufR5=NULL,*RVbufR6=NULL,*RVbufR7=NULL,*RVbufR8=NULL; #ifdef NATIVE_64BIT_INT #define NATIVE SLONGLONG #else #define NATIVE SLONG #endif /*========== 32 bit sample mixers - only for 32 bit platforms */ #ifndef NATIVE_64BIT_INT static SLONG Mix32MonoNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) { SWORD sample; SLONG lvolsel = vnf->lvolsel; while(todo--) { sample = srce[index >> FRACBITS]; index += increment; *dest++ += lvolsel * sample; } return index; } static SLONG Mix32StereoNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) { SWORD sample; SLONG lvolsel = vnf->lvolsel; SLONG rvolsel = vnf->rvolsel; while(todo--) { sample=srce[index >> FRACBITS]; index += increment; *dest++ += lvolsel * sample; *dest++ += rvolsel * sample; } return index; } static SLONG Mix32SurroundNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) { SWORD sample; SLONG lvolsel = vnf->lvolsel; SLONG rvolsel = vnf->rvolsel; if (lvolsel>=rvolsel) { while(todo--) { sample = srce[index >> FRACBITS]; index += increment; *dest++ += lvolsel*sample; *dest++ -= lvolsel*sample; } } else { while(todo--) { sample = srce[index >> FRACBITS]; index += increment; *dest++ -= rvolsel*sample; *dest++ += rvolsel*sample; } } return index; } static SLONG Mix32MonoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) { SLONG sample; SLONG lvolsel = vnf->lvolsel; SLONG rampvol = vnf->rampvol; if (rampvol) { SLONG oldlvol = vnf->oldlvol - lvolsel; while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) * sample >> CLICK_SHIFT; if (!--rampvol) break; } vnf->rampvol = rampvol; if (todo < 0) return index; } while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; *dest++ += lvolsel * sample; } return index; } static SLONG Mix32StereoInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) { SLONG sample; SLONG lvolsel = vnf->lvolsel; SLONG rvolsel = vnf->rvolsel; SLONG rampvol = vnf->rampvol; if (rampvol) { SLONG oldlvol = vnf->oldlvol - lvolsel; SLONG oldrvol = vnf->oldrvol - rvolsel; while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) * sample >> CLICK_SHIFT; *dest++ += ((rvolsel << CLICK_SHIFT) + oldrvol * rampvol) * sample >> CLICK_SHIFT; if (!--rampvol) break; } vnf->rampvol = rampvol; if (todo < 0) return index; } while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; *dest++ += lvolsel * sample; *dest++ += rvolsel * sample; } return index; } static SLONG Mix32SurroundInterp(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) { SLONG sample; SLONG lvolsel = vnf->lvolsel; SLONG rvolsel = vnf->rvolsel; SLONG rampvol = vnf->rampvol; SLONG oldvol, vol; if (lvolsel >= rvolsel) { vol = lvolsel; oldvol = vnf->oldlvol; } else { vol = rvolsel; oldvol = vnf->oldrvol; } if (rampvol) { oldvol -= vol; while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; sample=((vol << CLICK_SHIFT) + oldvol * rampvol) * sample >> CLICK_SHIFT; *dest++ += sample; *dest++ -= sample; if (!--rampvol) break; } vnf->rampvol = rampvol; if (todo < 0) return index; } while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; *dest++ += vol*sample; *dest++ -= vol*sample; } return index; } #endif /*========== 64 bit sample mixers - all platforms */ static SLONGLONG MixMonoNormal(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) { SWORD sample; SLONG lvolsel = vnf->lvolsel; while(todo--) { sample = srce[index >> FRACBITS]; index += increment; *dest++ += lvolsel * sample; } return index; } static SLONGLONG MixStereoNormal(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) { SWORD sample; SLONG lvolsel = vnf->lvolsel; SLONG rvolsel = vnf->rvolsel; while(todo--) { sample=srce[index >> FRACBITS]; index += increment; *dest++ += lvolsel * sample; *dest++ += rvolsel * sample; } return index; } static SLONGLONG MixSurroundNormal(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) { SWORD sample; SLONG lvolsel = vnf->lvolsel; SLONG rvolsel = vnf->rvolsel; if(vnf->lvolsel>=vnf->rvolsel) { while(todo--) { sample = srce[index >> FRACBITS]; index += increment; *dest++ += lvolsel*sample; *dest++ -= lvolsel*sample; } } else { while(todo--) { sample = srce[index >> FRACBITS]; index += increment; *dest++ -= rvolsel*sample; *dest++ += rvolsel*sample; } } return index; } static SLONGLONG MixMonoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) { SLONG sample; SLONG lvolsel = vnf->lvolsel; SLONG rampvol = vnf->rampvol; if (rampvol) { SLONG oldlvol = vnf->oldlvol - lvolsel; while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; *dest++ += ((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) * sample >> CLICK_SHIFT; if (!--rampvol) break; } vnf->rampvol = rampvol; if (todo < 0) return index; } while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; *dest++ += lvolsel * sample; } return index; } static SLONGLONG MixStereoInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) { SLONG sample; SLONG lvolsel = vnf->lvolsel; SLONG rvolsel = vnf->rvolsel; SLONG rampvol = vnf->rampvol; if (rampvol) { SLONG oldlvol = vnf->oldlvol - lvolsel; SLONG oldrvol = vnf->oldrvol - rvolsel; while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; *dest++ +=((lvolsel << CLICK_SHIFT) + oldlvol * rampvol) * sample >> CLICK_SHIFT; *dest++ +=((rvolsel << CLICK_SHIFT) + oldrvol * rampvol) * sample >> CLICK_SHIFT; if (!--rampvol) break; } vnf->rampvol = rampvol; if (todo < 0) return index; } while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; *dest++ += lvolsel * sample; *dest++ += rvolsel * sample; } return index; } static SLONGLONG MixSurroundInterp(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) { SLONG sample; SLONG lvolsel = vnf->lvolsel; SLONG rvolsel = vnf->rvolsel; SLONG rampvol = vnf->rampvol; SLONG oldvol, vol; if (lvolsel >= rvolsel) { vol = lvolsel; oldvol = vnf->oldlvol; } else { vol = rvolsel; oldvol = vnf->oldrvol; } if (rampvol) { oldvol -= vol; while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; sample=((vol << CLICK_SHIFT) + oldvol * rampvol) * sample >> CLICK_SHIFT; *dest++ += sample; *dest++ -= sample; if (!--rampvol) break; } vnf->rampvol = rampvol; if (todo < 0) return index; } while(todo--) { sample=(SLONG)srce[index>>FRACBITS]+ ((SLONG)(srce[(index>>FRACBITS)+1]-srce[index>>FRACBITS]) *(index&FRACMASK)>>FRACBITS); index += increment; *dest++ += vol*sample; *dest++ -= vol*sample; } return index; } static void (*MixReverb)(SLONG* srce,NATIVE count); /* Reverb macros */ #define COMPUTE_LOC(n) loc##n = RVRindex % RVc##n #define COMPUTE_LECHO(n) RVbufL##n [loc##n ]=speedup+((ReverbPct*RVbufL##n [loc##n ])>>7) #define COMPUTE_RECHO(n) RVbufR##n [loc##n ]=speedup+((ReverbPct*RVbufR##n [loc##n ])>>7) static void MixReverb_Normal(SLONG* srce,NATIVE count) { unsigned int speedup; int ReverbPct; unsigned int loc1,loc2,loc3,loc4; unsigned int loc5,loc6,loc7,loc8; ReverbPct=58+(md_reverb<<2); COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); while(count--) { /* Compute the left channel echo buffers */ speedup = *srce >> 3; COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4); COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8); /* Prepare to compute actual finalized data */ RVRindex++; COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); /* left channel */ *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; } } static void MixReverb_Stereo(SLONG* srce,NATIVE count) { unsigned int speedup; int ReverbPct; unsigned int loc1, loc2, loc3, loc4; unsigned int loc5, loc6, loc7, loc8; ReverbPct = 92+(md_reverb<<1); COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); while(count--) { /* Compute the left channel echo buffers */ speedup = *srce >> 3; COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4); COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8); /* Compute the right channel echo buffers */ speedup = srce[1] >> 3; COMPUTE_RECHO(1); COMPUTE_RECHO(2); COMPUTE_RECHO(3); COMPUTE_RECHO(4); COMPUTE_RECHO(5); COMPUTE_RECHO(6); COMPUTE_RECHO(7); COMPUTE_RECHO(8); /* Prepare to compute actual finalized data */ RVRindex++; COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); /* left channel then right channel */ *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+ RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8]; } } /* Mixing macros */ #define EXTRACT_SAMPLE(var,size) var=*srce++>>(BITSHIFT+16-size) #define CHECK_SAMPLE(var,bound) var=(var>=bound)?bound-1:(var<-bound)?-bound:var #define PUT_SAMPLE(var) *dste++=var static void Mix32To16(SWORD* dste,const SLONG* srce,NATIVE count) { SLONG x1,x2,x3,x4; int remain; remain=count&3; for(count>>=2;count;count--) { EXTRACT_SAMPLE(x1,16); EXTRACT_SAMPLE(x2,16); EXTRACT_SAMPLE(x3,16); EXTRACT_SAMPLE(x4,16); CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768); CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768); PUT_SAMPLE(x1); PUT_SAMPLE(x2); PUT_SAMPLE(x3); PUT_SAMPLE(x4); } while(remain--) { EXTRACT_SAMPLE(x1,16); CHECK_SAMPLE(x1,32768); PUT_SAMPLE(x1); } } static void Mix32To8(SBYTE* dste,const SLONG* srce,NATIVE count) { SWORD x1,x2,x3,x4; int remain; remain=count&3; for(count>>=2;count;count--) { EXTRACT_SAMPLE(x1,8); EXTRACT_SAMPLE(x2,8); EXTRACT_SAMPLE(x3,8); EXTRACT_SAMPLE(x4,8); CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128); CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128); PUT_SAMPLE(x1+128); PUT_SAMPLE(x2+128); PUT_SAMPLE(x3+128); PUT_SAMPLE(x4+128); } while(remain--) { EXTRACT_SAMPLE(x1,8); CHECK_SAMPLE(x1,128); PUT_SAMPLE(x1+128); } } static void AddChannel(SLONG* ptr,NATIVE todo) { SLONGLONG end,done; SWORD *s; if(!(s=Samples[vnf->handle])) { vnf->current = vnf->active = 0; return; } /* update the 'current' index so the sample loops, or stops playing if it reached the end of the sample */ while(todo>0) { SLONGLONG endpos; if(vnf->flags & SF_REVERSE) { /* The sample is playing in reverse */ if((vnf->flags&SF_LOOP)&&(vnf->currentflags & SF_BIDI) { /* sample is doing bidirectional loops, so 'bounce' the current index against the idxlpos */ vnf->current = idxlpos+(idxlpos-vnf->current); vnf->flags &= ~SF_REVERSE; vnf->increment = -vnf->increment; } else /* normal backwards looping, so set the current position to loopend index */ vnf->current=idxlend-(idxlpos-vnf->current); } else { /* the sample is not looping, so check if it reached index 0 */ if(vnf->current < 0) { /* playing index reached 0, so stop playing this sample */ vnf->current = vnf->active = 0; break; } } } else { /* The sample is playing forward */ if((vnf->flags & SF_LOOP) && (vnf->current >= idxlend)) { /* the sample is looping, check the loopend index */ if(vnf->flags & SF_BIDI) { /* sample is doing bidirectional loops, so 'bounce' the current index against the idxlend */ vnf->flags |= SF_REVERSE; vnf->increment = -vnf->increment; vnf->current = idxlend-(vnf->current-idxlend); } else /* normal backwards looping, so set the current position to loopend index */ vnf->current=idxlpos+(vnf->current-idxlend); } else { /* sample is not looping, so check if it reached the last position */ if(vnf->current >= idxsize) { /* yes, so stop playing this sample */ vnf->current = vnf->active = 0; break; } } } end=(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0: (vnf->flags&SF_LOOP)?idxlend:idxsize; /* if the sample is not blocked... */ if((end==vnf->current)||(!vnf->increment)) done=0; else { done=MIN((end-vnf->current)/vnf->increment+1,todo); if(done<0) done=0; } if(!done) { vnf->active = 0; break; } endpos=vnf->current+done*vnf->increment; if(vnf->vol) { #ifndef NATIVE_64BIT_INT /* use the 32 bit mixers as often as we can (they're much faster) */ if((vnf->current<0x7fffffff)&&(endpos<0x7fffffff)) { if((md_mode & DMODE_INTERP)) { if(vc_mode & DMODE_STEREO) { if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND)) vnf->current=Mix32SurroundInterp (s,ptr,vnf->current,vnf->increment,done); else vnf->current=Mix32StereoInterp (s,ptr,vnf->current,vnf->increment,done); } else vnf->current=Mix32MonoInterp (s,ptr,vnf->current,vnf->increment,done); } else if(vc_mode & DMODE_STEREO) { if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND)) vnf->current=Mix32SurroundNormal (s,ptr,vnf->current,vnf->increment,done); else vnf->current=Mix32StereoNormal (s,ptr,vnf->current,vnf->increment,done); } else vnf->current=Mix32MonoNormal (s,ptr,vnf->current,vnf->increment,done); } else #endif { if((md_mode & DMODE_INTERP)) { if(vc_mode & DMODE_STEREO) { if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND)) vnf->current=MixSurroundInterp (s,ptr,vnf->current,vnf->increment,done); else vnf->current=MixStereoInterp (s,ptr,vnf->current,vnf->increment,done); } else vnf->current=MixMonoInterp (s,ptr,vnf->current,vnf->increment,done); } else if(vc_mode & DMODE_STEREO) { if((vnf->pan==PAN_SURROUND)&&(md_mode&DMODE_SURROUND)) vnf->current=MixSurroundNormal (s,ptr,vnf->current,vnf->increment,done); else vnf->current=MixStereoNormal (s,ptr,vnf->current,vnf->increment,done); } else vnf->current=MixMonoNormal (s,ptr,vnf->current,vnf->increment,done); } } else /* update sample position */ vnf->current=endpos; todo-=done; ptr +=(vc_mode & DMODE_STEREO)?(done<<1):done; } } #define _IN_VIRTCH_ #include "virtch_common.c" #undef _IN_VIRTCH_ void VC1_WriteSamples(SBYTE* buf,ULONG todo) { int left,portion=0,count; SBYTE *buffer; int t, pan, vol; while(todo) { if(!tickleft) { if(vc_mode & DMODE_SOFT_MUSIC) md_player(); tickleft=(md_mixfreq*125L)/(md_bpm*50L); } left = MIN(tickleft, (long)todo); buffer = buf; tickleft -= left; todo -= left; buf += samples2bytes(left); while(left) { portion = MIN(left, samplesthatfit); count = (vc_mode & DMODE_STEREO)?(portion<<1):portion; memset(vc_tickbuf, 0, count<<2); for(t=0;tkick) { vnf->current=((SLONGLONG)vnf->start)<kick =0; vnf->active =1; } if(!vnf->frq) vnf->active = 0; if(vnf->active) { vnf->increment=((SLONGLONG)(vnf->frq<flags&SF_REVERSE) vnf->increment=-vnf->increment; vol = vnf->vol; pan = vnf->pan; vnf->oldlvol=vnf->lvolsel;vnf->oldrvol=vnf->rvolsel; if(vc_mode & DMODE_STEREO) { if(pan != PAN_SURROUND) { vnf->lvolsel=(vol*(PAN_RIGHT-pan))>>8; vnf->rvolsel=(vol*pan)>>8; } else vnf->lvolsel=vnf->rvolsel=vol/2; } else vnf->lvolsel=vol; idxsize = (vnf->size)? ((SLONGLONG)vnf->size << FRACBITS)-1 : 0; idxlend = (vnf->repend)? ((SLONGLONG)vnf->repend << FRACBITS)-1 : 0; idxlpos = (SLONGLONG)vnf->reppos << FRACBITS; AddChannel(vc_tickbuf, portion); } } if(md_reverb) { if(md_reverb>15) md_reverb=15; MixReverb(vc_tickbuf, portion); } if(vc_mode & DMODE_16BITS) Mix32To16((SWORD*) buffer, vc_tickbuf, count); else Mix32To8((SBYTE*) buffer, vc_tickbuf, count); buffer += samples2bytes(portion); left -= portion; } } } BOOL VC1_Init(void) { VC_SetupPointers(); if (md_mode&DMODE_HQMIXER) return VC2_Init(); if(!(Samples=(SWORD**)MikMod_calloc(MAXSAMPLEHANDLES,sizeof(SWORD*)))) { _mm_errno = MMERR_INITIALIZING_MIXER; return 1; } if(!vc_tickbuf) if(!(vc_tickbuf=(SLONG*)MikMod_malloc((TICKLSIZE+32)*sizeof(SLONG)))) { _mm_errno = MMERR_INITIALIZING_MIXER; return 1; } MixReverb=(md_mode&DMODE_STEREO)?MixReverb_Stereo:MixReverb_Normal; vc_mode = md_mode; return 0; } BOOL VC1_PlayStart(void) { samplesthatfit=TICKLSIZE; if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1; tickleft = 0; RVc1 = (5000L * md_mixfreq) / REVERBERATION; RVc2 = (5078L * md_mixfreq) / REVERBERATION; RVc3 = (5313L * md_mixfreq) / REVERBERATION; RVc4 = (5703L * md_mixfreq) / REVERBERATION; RVc5 = (6250L * md_mixfreq) / REVERBERATION; RVc6 = (6953L * md_mixfreq) / REVERBERATION; RVc7 = (7813L * md_mixfreq) / REVERBERATION; RVc8 = (8828L * md_mixfreq) / REVERBERATION; if(!(RVbufL1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1; if(!(RVbufL2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; if(!(RVbufL3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; if(!(RVbufL4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; if(!(RVbufL5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1; if(!(RVbufL6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1; if(!(RVbufL7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; if(!(RVbufL8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; if(!(RVbufR1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1; if(!(RVbufR2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; if(!(RVbufR3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; if(!(RVbufR4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; if(!(RVbufR5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1; if(!(RVbufR6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1; if(!(RVbufR7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; if(!(RVbufR8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; RVRindex = 0; return 0; } void VC1_PlayStop(void) { if(RVbufL1) MikMod_free(RVbufL1); if(RVbufL2) MikMod_free(RVbufL2); if(RVbufL3) MikMod_free(RVbufL3); if(RVbufL4) MikMod_free(RVbufL4); if(RVbufL5) MikMod_free(RVbufL5); if(RVbufL6) MikMod_free(RVbufL6); if(RVbufL7) MikMod_free(RVbufL7); if(RVbufL8) MikMod_free(RVbufL8); RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL; if(RVbufR1) MikMod_free(RVbufR1); if(RVbufR2) MikMod_free(RVbufR2); if(RVbufR3) MikMod_free(RVbufR3); if(RVbufR4) MikMod_free(RVbufR4); if(RVbufR5) MikMod_free(RVbufR5); if(RVbufR6) MikMod_free(RVbufR6); if(RVbufR7) MikMod_free(RVbufR7); if(RVbufR8) MikMod_free(RVbufR8); RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL; } BOOL VC1_SetNumVoices(void) { int t; if(!(vc_softchn=md_softchn)) return 0; if(vinf) MikMod_free(vinf); if(!(vinf= MikMod_calloc(sizeof(VINFO),vc_softchn))) return 1; for(t=0;t */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #include "mikmod_internals.h" #define ZEROLEN 32768 static SBYTE *zerobuf=NULL; static BOOL NS_IsThere(void) { return 1; } static BOOL NS_Init(void) { zerobuf=(SBYTE*)MikMod_malloc(ZEROLEN); return VC_Init(); } static void NS_Exit(void) { VC_Exit(); MikMod_free(zerobuf); } static void NS_Update(void) { if (zerobuf) VC_WriteBytes(zerobuf,ZEROLEN); } MIKMODAPI MDRIVER drv_nos={ NULL, "No Sound", "Nosound Driver v3.0", 255,255, "nosound", NULL, NS_IsThere, VC_SampleLoad, VC_SampleUnload, VC_SampleSpace, VC_SampleLength, NS_Init, NS_Exit, NULL, VC_SetNumVoices, VC_PlayStart, VC_PlayStop, NS_Update, NULL, VC_VoiceSetVolume, VC_VoiceGetVolume, VC_VoiceSetFrequency, VC_VoiceGetFrequency, VC_VoiceSetPanning, VC_VoiceGetPanning, VC_VoicePlay, VC_VoiceStop, VC_VoiceStopped, VC_VoiceGetPosition, VC_VoiceRealVolume }; /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/load_xm.c0000600000175000017500000005562010543202047017614 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: load_xm.c 2421 2006-08-19 00:36:21Z avolkov $ Fasttracker (XM) module loader ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #include #ifdef HAVE_MEMORY_H #include #endif #include #include "mikmod_internals.h" #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); #endif /*========== Module structure */ typedef struct XMHEADER { CHAR id[17]; /* ID text: 'Extended module: ' */ CHAR songname[21]; /* Module name */ CHAR trackername[20]; /* Tracker name */ UWORD version; /* Version number */ ULONG headersize; /* Header size */ UWORD songlength; /* Song length (in patten order table) */ UWORD restart; /* Restart position */ UWORD numchn; /* Number of channels (2,4,6,8,10,...,32) */ UWORD numpat; /* Number of patterns (max 256) */ UWORD numins; /* Number of instruments (max 128) */ UWORD flags; UWORD tempo; /* Default tempo */ UWORD bpm; /* Default BPM */ UBYTE orders[256]; /* Pattern order table */ } XMHEADER; typedef struct XMINSTHEADER { ULONG size; /* Instrument size */ CHAR name[22]; /* Instrument name */ UBYTE type; /* Instrument type (always 0) */ UWORD numsmp; /* Number of samples in instrument */ ULONG ssize; } XMINSTHEADER; #define XMENVCNT (12*2) #define XMNOTECNT (8*OCTAVE) typedef struct XMPATCHHEADER { UBYTE what[XMNOTECNT]; /* Sample number for all notes */ UWORD volenv[XMENVCNT]; /* Points for volume envelope */ UWORD panenv[XMENVCNT]; /* Points for panning envelope */ UBYTE volpts; /* Number of volume points */ UBYTE panpts; /* Number of panning points */ UBYTE volsus; /* Volume sustain point */ UBYTE volbeg; /* Volume loop start point */ UBYTE volend; /* Volume loop end point */ UBYTE pansus; /* Panning sustain point */ UBYTE panbeg; /* Panning loop start point */ UBYTE panend; /* Panning loop end point */ UBYTE volflg; /* Volume type: bit 0: On; 1: Sustain; 2: Loop */ UBYTE panflg; /* Panning type: bit 0: On; 1: Sustain; 2: Loop */ UBYTE vibflg; /* Vibrato type */ UBYTE vibsweep; /* Vibrato sweep */ UBYTE vibdepth; /* Vibrato depth */ UBYTE vibrate; /* Vibrato rate */ UWORD volfade; /* Volume fadeout */ } XMPATCHHEADER; typedef struct XMWAVHEADER { ULONG length; /* Sample length */ ULONG loopstart; /* Sample loop start */ ULONG looplength; /* Sample loop length */ UBYTE volume; /* Volume */ SBYTE finetune; /* Finetune (signed byte -128..+127) */ UBYTE type; /* Loop type */ UBYTE panning; /* Panning (0-255) */ SBYTE relnote; /* Relative note number (signed byte) */ UBYTE reserved; CHAR samplename[22]; /* Sample name */ UBYTE vibtype; /* Vibrato type */ UBYTE vibsweep; /* Vibrato sweep */ UBYTE vibdepth; /* Vibrato depth */ UBYTE vibrate; /* Vibrato rate */ } XMWAVHEADER; typedef struct XMPATHEADER { ULONG size; /* Pattern header length */ UBYTE packing; /* Packing type (always 0) */ UWORD numrows; /* Number of rows in pattern (1..256) */ SWORD packsize; /* Packed patterndata size */ } XMPATHEADER; typedef struct XMNOTE { UBYTE note,ins,vol,eff,dat; } XMNOTE; /*========== Loader variables */ static XMNOTE *xmpat=NULL; static XMHEADER *mh=NULL; /* increment unit for sample array reallocation */ #define XM_SMPINCR 64 static ULONG *nextwav=NULL; static XMWAVHEADER *wh=NULL,*s=NULL; /*========== Loader code */ BOOL XM_Test(void) { UBYTE id[38]; if(!_mm_read_UBYTES(id,38,modreader)) return 0; if(memcmp(id,"Extended Module: ",17)) return 0; if(id[37]==0x1a) return 1; return 0; } BOOL XM_Init(void) { if(!(mh=(XMHEADER *)MikMod_malloc(sizeof(XMHEADER)))) return 0; return 1; } void XM_Cleanup(void) { MikMod_free(mh); } static int XM_ReadNote(XMNOTE* n) { UBYTE cmp,result=1; memset(n,0,sizeof(XMNOTE)); cmp=_mm_read_UBYTE(modreader); if(cmp&0x80) { if(cmp&1) { result++;n->note = _mm_read_UBYTE(modreader); } if(cmp&2) { result++;n->ins = _mm_read_UBYTE(modreader); } if(cmp&4) { result++;n->vol = _mm_read_UBYTE(modreader); } if(cmp&8) { result++;n->eff = _mm_read_UBYTE(modreader); } if(cmp&16) { result++;n->dat = _mm_read_UBYTE(modreader); } } else { n->note = cmp; n->ins = _mm_read_UBYTE(modreader); n->vol = _mm_read_UBYTE(modreader); n->eff = _mm_read_UBYTE(modreader); n->dat = _mm_read_UBYTE(modreader); result += 4; } return result; } static UBYTE* XM_Convert(XMNOTE* xmtrack,UWORD rows) { int t; UBYTE note,ins,vol,eff,dat; UniReset(); for(t=0;tnote; ins = xmtrack->ins; vol = xmtrack->vol; eff = xmtrack->eff; dat = xmtrack->dat; if(note) { if(note>XMNOTECNT) UniEffect(UNI_KEYFADE,0); else UniNote(note-1); } if(ins) UniInstrument(ins-1); switch(vol>>4) { case 0x6: /* volslide down */ if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol&0xf); break; case 0x7: /* volslide up */ if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol<<4); break; /* volume-row fine volume slide is compatible with protracker EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as opposed to 'take the last sliding value'. */ case 0x8: /* finevol down */ UniPTEffect(0xe,0xb0|(vol&0xf)); break; case 0x9: /* finevol up */ UniPTEffect(0xe,0xa0|(vol&0xf)); break; case 0xa: /* set vibrato speed */ UniEffect(UNI_XMEFFECT4,vol<<4); break; case 0xb: /* vibrato */ UniEffect(UNI_XMEFFECT4,vol&0xf); break; case 0xc: /* set panning */ UniPTEffect(0x8,vol<<4); break; case 0xd: /* panning slide left (only slide when data not zero) */ if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol&0xf); break; case 0xe: /* panning slide right (only slide when data not zero) */ if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol<<4); break; case 0xf: /* tone porta */ UniPTEffect(0x3,vol<<4); break; default: if((vol>=0x10)&&(vol<=0x50)) UniPTEffect(0xc,vol-0x10); } switch(eff) { case 0x4: UniEffect(UNI_XMEFFECT4,dat); break; case 0x6: UniEffect(UNI_XMEFFECT6,dat); break; case 0xa: UniEffect(UNI_XMEFFECTA,dat); break; case 0xe: /* Extended effects */ switch(dat>>4) { case 0x1: /* XM fine porta up */ UniEffect(UNI_XMEFFECTE1,dat&0xf); break; case 0x2: /* XM fine porta down */ UniEffect(UNI_XMEFFECTE2,dat&0xf); break; case 0xa: /* XM fine volume up */ UniEffect(UNI_XMEFFECTEA,dat&0xf); break; case 0xb: /* XM fine volume down */ UniEffect(UNI_XMEFFECTEB,dat&0xf); break; default: UniPTEffect(eff,dat); } break; case 'G'-55: /* G - set global volume */ UniEffect(UNI_XMEFFECTG,dat>64?128:dat<<1); break; case 'H'-55: /* H - global volume slide */ UniEffect(UNI_XMEFFECTH,dat); break; case 'K'-55: /* K - keyOff and KeyFade */ UniEffect(UNI_KEYFADE,dat); break; case 'L'-55: /* L - set envelope position */ UniEffect(UNI_XMEFFECTL,dat); break; case 'P'-55: /* P - panning slide */ UniEffect(UNI_XMEFFECTP,dat); break; case 'R'-55: /* R - multi retrig note */ UniEffect(UNI_S3MEFFECTQ,dat); break; case 'T'-55: /* T - Tremor */ UniEffect(UNI_S3MEFFECTI,dat); break; case 'X'-55: switch(dat>>4) { case 1: /* X1 - Extra Fine Porta up */ UniEffect(UNI_XMEFFECTX1,dat&0xf); break; case 2: /* X2 - Extra Fine Porta down */ UniEffect(UNI_XMEFFECTX2,dat&0xf); break; } break; default: if(eff<=0xf) { /* the pattern jump destination is written in decimal, but it seems some poor tracker software writes them in hexadecimal... (sigh) */ if (eff==0xd) /* don't change anything if we're sure it's in hexa */ if ((((dat&0xf0)>>4)<=9)&&((dat&0xf)<=9)) /* otherwise, convert from dec to hex */ dat=(((dat&0xf0)>>4)*10)+(dat&0xf); UniPTEffect(eff,dat); } break; } UniNewline(); xmtrack++; } return UniDup(); } static BOOL LoadPatterns(BOOL dummypat) { int t,u,v,numtrk; if(!AllocTracks()) return 0; if(!AllocPatterns()) return 0; numtrk=0; for(t=0;tnumpat;t++) { XMPATHEADER ph; ph.size =_mm_read_I_ULONG(modreader); if (ph.size<(mh->version==0x0102?8:9)) { _mm_errno=MMERR_LOADING_PATTERN; return 0; } ph.packing =_mm_read_UBYTE(modreader); if(ph.packing) { _mm_errno=MMERR_LOADING_PATTERN; return 0; } if(mh->version==0x0102) ph.numrows =_mm_read_UBYTE(modreader)+1; else ph.numrows =_mm_read_I_UWORD(modreader); ph.packsize =_mm_read_I_UWORD(modreader); ph.size-=(mh->version==0x0102?8:9); if(ph.size) _mm_fseek(modreader,ph.size,SEEK_CUR); of.pattrows[t]=ph.numrows; if(ph.numrows) { if(!(xmpat=(XMNOTE*)MikMod_calloc(ph.numrows*of.numchn,sizeof(XMNOTE)))) return 0; /* when packsize is 0, don't try to load a pattern.. it's empty. */ if(ph.packsize) for(u=0;upos; for (u = 1; u < pts; u++, prev++, cur++) { if (cur->pos < prev->pos) { if (cur->pos < 0x100) { if (cur->pos > old) /* same hex century */ tmp = cur->pos + (prev->pos - old); else tmp = cur->pos | ((prev->pos + 0x100) & 0xff00); old = cur->pos; cur->pos = tmp; #ifdef MIKMOD_DEBUG fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d -> %d\n", u, pts, prev->pos, old, cur->pos); #endif } else { #ifdef MIKMOD_DEBUG /* different brokenness style... fix unknown */ fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d\n", u, pts, old, cur->pos); #endif old = cur->pos; } } else old = cur->pos; } } static BOOL LoadInstruments(void) { int t,u; INSTRUMENT *d; ULONG next=0; UWORD wavcnt=0; if(!AllocInstruments()) return 0; d=of.instruments; for(t=0;tsamplenumber,0xff,INSTNOTES*sizeof(UWORD)); /* read instrument header */ headend = _mm_ftell(modreader); ih.size = _mm_read_I_ULONG(modreader); headend += ih.size; _mm_read_string(ih.name, 22, modreader); ih.type = _mm_read_UBYTE(modreader); ih.numsmp = _mm_read_I_UWORD(modreader); d->insname = DupStr(ih.name,22,1); if((SWORD)ih.size>29) { ih.ssize = _mm_read_I_ULONG(modreader); if(((SWORD)ih.numsmp>0)&&(ih.numsmp<=XMNOTECNT)) { XMPATCHHEADER pth; int p; _mm_read_UBYTES (pth.what,XMNOTECNT,modreader); _mm_read_I_UWORDS (pth.volenv, XMENVCNT, modreader); _mm_read_I_UWORDS (pth.panenv, XMENVCNT, modreader); pth.volpts = _mm_read_UBYTE(modreader); pth.panpts = _mm_read_UBYTE(modreader); pth.volsus = _mm_read_UBYTE(modreader); pth.volbeg = _mm_read_UBYTE(modreader); pth.volend = _mm_read_UBYTE(modreader); pth.pansus = _mm_read_UBYTE(modreader); pth.panbeg = _mm_read_UBYTE(modreader); pth.panend = _mm_read_UBYTE(modreader); pth.volflg = _mm_read_UBYTE(modreader); pth.panflg = _mm_read_UBYTE(modreader); pth.vibflg = _mm_read_UBYTE(modreader); pth.vibsweep = _mm_read_UBYTE(modreader); pth.vibdepth = _mm_read_UBYTE(modreader); pth.vibrate = _mm_read_UBYTE(modreader); pth.volfade = _mm_read_I_UWORD(modreader); /* read the remainder of the header (2 bytes for 1.03, 22 for 1.04) */ for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader); /* we can't trust the envelope point count here, as some modules have incorrect values (K_OSPACE.XM reports 32 volume points, for example). */ if(pth.volpts>XMENVCNT/2) pth.volpts=XMENVCNT/2; if(pth.panpts>XMENVCNT/2) pth.panpts=XMENVCNT/2; if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) { if(nextwav) { MikMod_free(nextwav);nextwav=NULL; } if(wh) { MikMod_free(wh);wh=NULL; } _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } for(u=0;usamplenumber[u]=pth.what[u]+of.numsmp; d->volfade = pth.volfade; #if defined __STDC__ || defined _MSC_VER || defined MPW_C #define XM_ProcessEnvelope(name) \ for (u = 0; u < (XMENVCNT >> 1); u++) { \ d-> name##env[u].pos = pth. name##env[u << 1]; \ d-> name##env[u].val = pth. name##env[(u << 1)+ 1]; \ } \ if (pth. name##flg&1) d-> name##flg|=EF_ON; \ if (pth. name##flg&2) d-> name##flg|=EF_SUSTAIN; \ if (pth. name##flg&4) d-> name##flg|=EF_LOOP; \ d-> name##susbeg=d-> name##susend=pth. name##sus; \ d-> name##beg=pth. name##beg; \ d-> name##end=pth. name##end; \ d-> name##pts=pth. name##pts; \ \ /* scale envelope */ \ for (p=0;p name##env[p].val<<=2; \ \ if ((d-> name##flg&EF_ON)&&(d-> name##pts<2)) \ d-> name##flg&=~EF_ON #else #define XM_ProcessEnvelope(name) \ for (u = 0; u < (XMENVCNT >> 1); u++) { \ d-> name/**/env[u].pos = pth. name/**/env[u << 1]; \ d-> name/**/env[u].val = pth. name/**/env[(u << 1)+ 1]; \ } \ if (pth. name/**/flg&1) d-> name/**/flg|=EF_ON; \ if (pth. name/**/flg&2) d-> name/**/flg|=EF_SUSTAIN; \ if (pth. name/**/flg&4) d-> name/**/flg|=EF_LOOP; \ d-> name/**/susbeg=d-> name/**/susend= \ pth. name/**/sus; \ d-> name/**/beg=pth. name/**/beg; \ d-> name/**/end=pth. name/**/end; \ d-> name/**/pts=pth. name/**/pts; \ \ /* scale envelope */ \ for (p=0;p name/**/env[p].val<<=2; \ \ if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \ d-> name/**/flg&=~EF_ON #endif XM_ProcessEnvelope(vol); XM_ProcessEnvelope(pan); #undef XM_ProcessEnvelope if (d->volflg & EF_ON) FixEnvelope(d->volenv, d->volpts); if (d->panflg & EF_ON) FixEnvelope(d->panenv, d->panpts); /* Samples are stored outside the instrument struct now, so we have to load them all into a temp area, count the of.numsmp along the way and then do an AllocSamples() and move everything over */ if(mh->version>0x0103) next = 0; for(u=0;ulength =_mm_read_I_ULONG (modreader); s->loopstart =_mm_read_I_ULONG (modreader); s->looplength =_mm_read_I_ULONG (modreader); s->volume =_mm_read_UBYTE (modreader); s->finetune =_mm_read_SBYTE (modreader); s->type =_mm_read_UBYTE (modreader); s->panning =_mm_read_UBYTE (modreader); s->relnote =_mm_read_SBYTE (modreader); s->vibtype = pth.vibflg; s->vibsweep = pth.vibsweep; s->vibdepth = pth.vibdepth*4; s->vibrate = pth.vibrate; s->reserved =_mm_read_UBYTE (modreader); _mm_read_string(s->samplename, 22, modreader); nextwav[of.numsmp+u]=next; next+=s->length; if(_mm_eof(modreader)) { MikMod_free(nextwav);MikMod_free(wh); nextwav=NULL;wh=NULL; _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } } if(mh->version>0x0103) { for(u=0;uid,17,modreader); _mm_read_string(mh->songname,21,modreader); _mm_read_string(mh->trackername,20,modreader); mh->version =_mm_read_I_UWORD(modreader); if((mh->version<0x102)||(mh->version>0x104)) { _mm_errno=MMERR_NOT_A_MODULE; return 0; } mh->headersize =_mm_read_I_ULONG(modreader); mh->songlength =_mm_read_I_UWORD(modreader); mh->restart =_mm_read_I_UWORD(modreader); mh->numchn =_mm_read_I_UWORD(modreader); mh->numpat =_mm_read_I_UWORD(modreader); mh->numins =_mm_read_I_UWORD(modreader); mh->flags =_mm_read_I_UWORD(modreader); mh->tempo =_mm_read_I_UWORD(modreader); mh->bpm =_mm_read_I_UWORD(modreader); if(!mh->bpm) { _mm_errno=MMERR_NOT_A_MODULE; return 0; } _mm_read_UBYTES(mh->orders,256,modreader); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } /* set module variables */ of.initspeed = mh->tempo; of.inittempo = mh->bpm; strncpy(tracker,mh->trackername,20);tracker[20]=0; for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0; /* some modules have the tracker name empty */ if (!tracker[0]) strcpy(tracker,"Unknown tracker"); #ifdef HAVE_SNPRINTF snprintf(modtype,60,"%s (XM format %d.%02d)", tracker,mh->version>>8,mh->version&0xff); #else sprintf(modtype,"%s (XM format %d.%02d)", tracker,mh->version>>8,mh->version&0xff); #endif of.modtype = strdup(modtype); of.numchn = mh->numchn; of.numpat = mh->numpat; of.numtrk = (UWORD)of.numpat*of.numchn; /* get number of channels */ of.songname = DupStr(mh->songname,20,1); of.numpos = mh->songlength; /* copy the songlength */ of.reppos = mh->restartsonglength?mh->restart:0; of.numins = mh->numins; of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS | UF_PANNING; if(mh->flags&1) of.flags |= UF_LINEAR; of.bpmlimit = 32; memset(of.chanvol,64,of.numchn); /* store channel volumes */ if(!AllocPositions(of.numpos+1)) return 0; for(t=0;torders[t]; /* We have to check for any pattern numbers in the order list greater than the number of patterns total. If one or more is found, we set it equal to the pattern total and make a dummy pattern to workaround the problem */ for(t=0;t=of.numpat) { of.positions[t]=of.numpat; dummypat=1; } } if(dummypat) { of.numpat++;of.numtrk+=of.numchn; } if(mh->version<0x0104) { if(!LoadInstruments()) return 0; if(!LoadPatterns(dummypat)) return 0; for(t=0;tsamplename = DupStr(s->samplename,22,1); q->length = s->length; q->loopstart = s->loopstart; q->loopend = s->loopstart+s->looplength; q->volume = s->volume; q->speed = s->finetune+128; q->panning = s->panning; q->seekpos = nextwav[u]; q->vibtype = s->vibtype; q->vibsweep = s->vibsweep; q->vibdepth = s->vibdepth; q->vibrate = s->vibrate; if(s->type & 0x10) { q->length >>= 1; q->loopstart >>= 1; q->loopend >>= 1; } q->flags|=SF_OWNPAN|SF_DELTA|SF_SIGNED; if(s->type&0x3) q->flags|=SF_LOOP; if(s->type&0x2) q->flags|=SF_BIDI; if(s->type&0x10) q->flags|=SF_16BITS; } d=of.instruments; s=wh; for(u=0;usamplenumber[t]>=of.numsmp) d->samplenote[t]=255; else { int note=t+s[d->samplenumber[t]].relnote; d->samplenote[t]=(note<0)?0:note; } } MikMod_free(wh);MikMod_free(nextwav); wh=NULL;nextwav=NULL; return 1; } CHAR *XM_LoadTitle(void) { CHAR s[21]; _mm_fseek(modreader,17,SEEK_SET); if(!_mm_read_UBYTES(s,21,modreader)) return NULL; return(DupStr(s,21,1)); } /*========== Loader information */ MIKMODAPI MLOADER load_xm={ NULL, "XM", "XM (FastTracker 2)", XM_Init, XM_Test, XM_Load, XM_Cleanup, XM_LoadTitle }; /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mwav.c0000600000175000017500000001146510543202047017142 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mwav.c 2412 2006-08-18 18:37:39Z avolkov $ WAV sample loader ==============================================================================*/ /* FIXME: Stereo .WAV files are not yet supported as samples. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #include #include "mikmod_internals.h" #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); #endif typedef struct WAV { CHAR rID[4]; ULONG rLen; CHAR wID[4]; CHAR fID[4]; ULONG fLen; UWORD wFormatTag; UWORD nChannels; ULONG nSamplesPerSec; ULONG nAvgBytesPerSec; UWORD nBlockAlign; UWORD nFormatSpecific; } WAV; SAMPLE* Sample_LoadGeneric_internal(MREADER* reader) { SAMPLE *si=NULL; WAV wh; BOOL have_fmt=0; /* read wav header */ _mm_read_string(wh.rID,4,reader); wh.rLen = _mm_read_I_ULONG(reader); _mm_read_string(wh.wID,4,reader); /* check for correct header */ if(_mm_eof(reader)|| memcmp(wh.rID,"RIFF",4) || memcmp(wh.wID,"WAVE",4)) { _mm_errno = MMERR_UNKNOWN_WAVE_TYPE; return NULL; } /* scan all RIFF blocks until we find the sample data */ for(;;) { CHAR dID[4]; ULONG len,start; _mm_read_string(dID,4,reader); len = _mm_read_I_ULONG(reader); /* truncated file ? */ if (_mm_eof(reader)) { _mm_errno=MMERR_UNKNOWN_WAVE_TYPE; return NULL; } start = _mm_ftell(reader); /* sample format block should be present only once and before a data block */ if(!memcmp(dID,"fmt ",4)) { wh.wFormatTag = _mm_read_I_UWORD(reader); wh.nChannels = _mm_read_I_UWORD(reader); wh.nSamplesPerSec = _mm_read_I_ULONG(reader); wh.nAvgBytesPerSec = _mm_read_I_ULONG(reader); wh.nBlockAlign = _mm_read_I_UWORD(reader); wh.nFormatSpecific = _mm_read_I_UWORD(reader); #ifdef MIKMOD_DEBUG fprintf(stderr,"\rwavloader : wFormatTag=%04x blockalign=%04x nFormatSpc=%04x\n", wh.wFormatTag,wh.nBlockAlign,wh.nFormatSpecific); #endif if((have_fmt)||(wh.nChannels>1)) { _mm_errno=MMERR_UNKNOWN_WAVE_TYPE; return NULL; } have_fmt=1; } else /* sample data block should be present only once and after a format block */ if(!memcmp(dID,"data",4)) { if(!have_fmt) { _mm_errno=MMERR_UNKNOWN_WAVE_TYPE; return NULL; } if(!(si=(SAMPLE*)MikMod_malloc(sizeof(SAMPLE)))) return NULL; si->speed = wh.nSamplesPerSec/wh.nChannels; si->volume = 64; si->length = len; if(wh.nBlockAlign == 2) { si->flags = SF_16BITS | SF_SIGNED; si->length >>= 1; } si->inflags = si->flags; SL_RegisterSample(si,MD_SNDFX,reader); SL_LoadSamples(); /* skip any other remaining blocks - so in case of repeated sample fragments, we'll return the first anyway instead of an error */ break; } /* onto next block */ _mm_fseek(reader,start+len,SEEK_SET); if (_mm_eof(reader)) break; } return si; } MIKMODAPI SAMPLE* Sample_LoadGeneric(MREADER* reader) { SAMPLE* result; MUTEX_LOCK(vars); result=Sample_LoadGeneric_internal(reader); MUTEX_UNLOCK(vars); return result; } MIKMODAPI extern SAMPLE *Sample_LoadMem(const char *buf, int len) { SAMPLE* result=NULL; MREADER* reader; if ((reader=_mm_new_mem_reader(buf, len))) { result=Sample_LoadGeneric(reader); _mm_delete_mem_reader(reader); } return result; } MIKMODAPI SAMPLE* Sample_LoadFP(FILE *fp) { SAMPLE* result=NULL; MREADER* reader; if((reader=_mm_new_file_reader(fp))) { result=Sample_LoadGeneric(reader); _mm_delete_file_reader(reader); } return result; } MIKMODAPI SAMPLE* Sample_Load(CHAR* filename) { FILE *fp; SAMPLE *si=NULL; if(!(md_mode & DMODE_SOFT_SNDFX)) return NULL; if((fp=_mm_fopen(filename,"rb"))) { si = Sample_LoadFP(fp); _mm_fclose(fp); } return si; } MIKMODAPI void Sample_Free(SAMPLE* si) { if(si) { MD_SampleUnload(si->handle); MikMod_free(si); } } void Sample_Free_internal(SAMPLE *si) { MUTEX_LOCK(vars); Sample_Free(si); MUTEX_UNLOCK(vars); } /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mlutil.c0000600000175000017500000002122210543202047017466 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mlutil.c 2421 2006-08-19 00:36:21Z avolkov $ Utility functions for the module loader ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MEMORY_H #include #endif #include #include "mikmod_internals.h" #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); #endif /*========== Shared tracker identifiers */ CHAR *STM_Signatures[STM_NTRACKERS] = { "!Scream!", "BMOD2STM", "WUZAMOD!" }; CHAR *STM_Version[STM_NTRACKERS] = { "Screamtracker 2", "Converted by MOD2STM (STM format)", "Wuzamod (STM format)" }; /*========== Shared loader variables */ SBYTE remap[UF_MAXCHAN]; /* for removing empty channels */ UBYTE* poslookup=NULL; /* lookup table for pattern jumps after blank pattern removal */ UBYTE poslookupcnt; UWORD* origpositions=NULL; BOOL filters; /* resonant filters in use */ UBYTE activemacro; /* active midi macro number for Sxx,xx<80h */ UBYTE filtermacros[UF_MAXMACRO]; /* midi macro settings */ FILTER filtersettings[UF_MAXFILTER]; /* computed filter settings */ /*========== Linear periods stuff */ int* noteindex=NULL; /* remap value for linear period modules */ static int noteindexcount=0; int *AllocLinear(void) { if(of.numsmp>noteindexcount) { noteindexcount=of.numsmp; noteindex=realloc(noteindex,noteindexcount*sizeof(int)); } return noteindex; } void FreeLinear(void) { if(noteindex) { MikMod_free(noteindex); noteindex=NULL; } noteindexcount=0; } int speed_to_finetune(ULONG speed,int sample) { int note=1,finetune=0; ULONG ctmp=0,tmp; speed>>=1; while((tmp=getfrequency(of.flags,getlinearperiod(note<<1,0)))speed) tmp=getfrequency(of.flags,getlinearperiod(note<<1,--finetune)); else { note--; while(ctmp>4; /* process S3M / IT specific command structure */ if(cmd!=255) { switch(cmd) { case 1: /* Axx set speed to xx */ UniEffect(UNI_S3MEFFECTA,inf); break; case 2: /* Bxx position jump */ if (inf>4)*10+(inf&0xf)); else UniPTEffect(0xd,inf); break; case 4: /* Dxy volumeslide */ UniEffect(UNI_S3MEFFECTD,inf); break; case 5: /* Exy toneslide down */ UniEffect(UNI_S3MEFFECTE,inf); break; case 6: /* Fxy toneslide up */ UniEffect(UNI_S3MEFFECTF,inf); break; case 7: /* Gxx Tone portamento, speed xx */ if (flags & S3MIT_OLDSTYLE) UniPTEffect(0x3,inf); else UniEffect(UNI_ITEFFECTG,inf); break; case 8: /* Hxy vibrato */ if (flags & S3MIT_OLDSTYLE) UniPTEffect(0x4,inf); else UniEffect(UNI_ITEFFECTH,inf); break; case 9: /* Ixy tremor, ontime x, offtime y */ if (flags & S3MIT_OLDSTYLE) UniEffect(UNI_S3MEFFECTI,inf); else UniEffect(UNI_ITEFFECTI,inf); break; case 0xa: /* Jxy arpeggio */ UniPTEffect(0x0,inf); break; case 0xb: /* Kxy Dual command H00 & Dxy */ if (flags & S3MIT_OLDSTYLE) UniPTEffect(0x4,0); else UniEffect(UNI_ITEFFECTH,0); UniEffect(UNI_S3MEFFECTD,inf); break; case 0xc: /* Lxy Dual command G00 & Dxy */ if (flags & S3MIT_OLDSTYLE) UniPTEffect(0x3,0); else UniEffect(UNI_ITEFFECTG,0); UniEffect(UNI_S3MEFFECTD,inf); break; case 0xd: /* Mxx Set Channel Volume */ UniEffect(UNI_ITEFFECTM,inf); break; case 0xe: /* Nxy Slide Channel Volume */ UniEffect(UNI_ITEFFECTN,inf); break; case 0xf: /* Oxx set sampleoffset xx00h */ UniPTEffect(0x9,inf); break; case 0x10: /* Pxy Slide Panning Commands */ UniEffect(UNI_ITEFFECTP,inf); break; case 0x11: /* Qxy Retrig (+volumeslide) */ UniWriteByte(UNI_S3MEFFECTQ); if(inf && !lo && !(flags & S3MIT_OLDSTYLE)) UniWriteByte(1); else UniWriteByte(inf); break; case 0x12: /* Rxy tremolo speed x, depth y */ UniEffect(UNI_S3MEFFECTR,inf); break; case 0x13: /* Sxx special commands */ if (inf>=0xf0) { /* change resonant filter settings if necessary */ if((filters)&&((inf&0xf)!=activemacro)) { activemacro=inf&0xf; for(inf=0;inf<0x80;inf++) filtersettings[inf].filter=filtermacros[activemacro]; } } else { /* Scream Tracker does not have samples larger than 64 Kb, thus doesn't need the SAx effect */ if ((flags & S3MIT_SCREAM) && ((inf & 0xf0) == 0xa0)) break; UniEffect(UNI_ITEFFECTS0,inf); } break; case 0x14: /* Txx tempo */ if(inf>=0x20) UniEffect(UNI_S3MEFFECTT,inf); else { if(!(flags & S3MIT_OLDSTYLE)) /* IT Tempo slide */ UniEffect(UNI_ITEFFECTT,inf); } break; case 0x15: /* Uxy Fine Vibrato speed x, depth y */ if(flags & S3MIT_OLDSTYLE) UniEffect(UNI_S3MEFFECTU,inf); else UniEffect(UNI_ITEFFECTU,inf); break; case 0x16: /* Vxx Set Global Volume */ UniEffect(UNI_XMEFFECTG,inf); break; case 0x17: /* Wxy Global Volume Slide */ UniEffect(UNI_ITEFFECTW,inf); break; case 0x18: /* Xxx amiga command 8xx */ if(flags & S3MIT_OLDSTYLE) { if(inf>128) UniEffect(UNI_ITEFFECTS0,0x91); /* surround */ else UniPTEffect(0x8,(inf==128)?255:(inf<<1)); } else UniPTEffect(0x8,inf); break; case 0x19: /* Yxy Panbrello speed x, depth y */ UniEffect(UNI_ITEFFECTY,inf); break; case 0x1a: /* Zxx midi/resonant filters */ if(filtersettings[inf].filter) { UniWriteByte(UNI_ITEFFECTZ); UniWriteByte(filtersettings[inf].filter); UniWriteByte(filtersettings[inf].inf); } break; } } } /*========== Unitrk stuff */ /* Generic effect writing routine */ void UniEffect(UWORD eff,UWORD dat) { if((!eff)||(eff>=UNI_LAST)) return; UniWriteByte(eff); if(unioperands[eff]==2) UniWriteWord(dat); else UniWriteByte(dat); } /* Appends UNI_PTEFFECTX opcode to the unitrk stream. */ void UniPTEffect(UBYTE eff, UBYTE dat) { #ifdef MIKMOD_DEBUG if (eff>=0x10) fprintf(stderr,"UniPTEffect called with incorrect eff value %d\n",eff); else #endif if((eff)||(dat)||(of.flags&UF_ARPMEM)) UniEffect(UNI_PTEFFECT0+eff,dat); } /* Appends UNI_VOLEFFECT + effect/dat to unistream. */ void UniVolEffect(UWORD eff,UBYTE dat) { if((eff)||(dat)) { /* don't write empty effect */ UniWriteByte(UNI_VOLEFFECTS); UniWriteByte(eff);UniWriteByte(dat); } } /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/README0000600000175000017500000000043510543202047016677 0ustar joeyjoeyNOTE by UQM developers: this is a modified version of libmikmod. This version of the library is based on the official libmikmod library version 3.1.11a with some internal and API changes backported from v3.2.2. The official library is found at http://sourceforge.net/projects/mikmod. uqm-0.6.2/sc2/src/sc2code/libs/mikmod/load_s3m.c0000600000175000017500000002716510543202047017675 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: load_s3m.c 2412 2006-08-18 18:37:39Z avolkov $ Screamtracker (S3M) module loader ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #include #ifdef HAVE_MEMORY_H #include #endif #include #include "mikmod_internals.h" #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); #endif /*========== Module structure */ /* header */ typedef struct S3MHEADER { CHAR songname[28]; UBYTE t1a; UBYTE type; UBYTE unused1[2]; UWORD ordnum; UWORD insnum; UWORD patnum; UWORD flags; UWORD tracker; UWORD fileformat; CHAR scrm[4]; UBYTE mastervol; UBYTE initspeed; UBYTE inittempo; UBYTE mastermult; UBYTE ultraclick; UBYTE pantable; UBYTE unused2[8]; UWORD special; UBYTE channels[32]; } S3MHEADER; /* sample information */ typedef struct S3MSAMPLE { UBYTE type; CHAR filename[12]; UBYTE memsegh; UWORD memsegl; ULONG length; ULONG loopbeg; ULONG loopend; UBYTE volume; UBYTE dsk; UBYTE pack; UBYTE flags; ULONG c2spd; UBYTE unused[12]; CHAR sampname[28]; CHAR scrs[4]; } S3MSAMPLE; typedef struct S3MNOTE { UBYTE note,ins,vol,cmd,inf; } S3MNOTE; /*========== Loader variables */ static S3MNOTE *s3mbuf = NULL; /* pointer to a complete S3M pattern */ static S3MHEADER *mh = NULL; static UWORD *paraptr = NULL; /* parapointer array (see S3M docs) */ static unsigned int tracker; /* tracker id */ /* tracker identifiers */ #define NUMTRACKERS 4 static CHAR* S3M_Version[] = { "Screamtracker x.xx", "Imago Orpheus x.xx (S3M format)", "Impulse Tracker x.xx (S3M format)", "Unknown tracker x.xx (S3M format)", "Impulse Tracker 2.14p3 (S3M format)", "Impulse Tracker 2.14p4 (S3M format)" }; /* version number position in above array */ static int numeric[NUMTRACKERS]={14,14,16,16}; /*========== Loader code */ BOOL S3M_Test(void) { UBYTE id[4]; _mm_fseek(modreader,0x2c,SEEK_SET); if(!_mm_read_UBYTES(id,4,modreader)) return 0; if(!memcmp(id,"SCRM",4)) return 1; return 0; } BOOL S3M_Init(void) { if(!(s3mbuf=(S3MNOTE*)MikMod_malloc(32*64*sizeof(S3MNOTE)))) return 0; if(!(mh=(S3MHEADER*)MikMod_malloc(sizeof(S3MHEADER)))) return 0; if(!(poslookup=(UBYTE*)MikMod_malloc(sizeof(UBYTE)*256))) return 0; memset(poslookup,-1,256); return 1; } void S3M_Cleanup(void) { MikMod_free(s3mbuf); MikMod_free(paraptr); MikMod_free(poslookup); MikMod_free(mh); MikMod_free(origpositions); } /* Because so many s3m files have 16 channels as the set number used, but really only use far less (usually 8 to 12 still), I had to make this function, which determines the number of channels that are actually USED by a pattern. For every channel that's used, it sets the appropriate array entry of the global variable 'remap' NOTE: You must first seek to the file location of the pattern before calling this procedure. Returns 1 on fail. */ static BOOL S3M_GetNumChannels(void) { int row=0,flag,ch; while(row<64) { flag=_mm_read_UBYTE(modreader); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_PATTERN; return 1; } if(flag) { ch=flag&31; if(mh->channels[ch]<32) remap[ch] = 0; if(flag&32) {_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);} if(flag&64) _mm_read_UBYTE(modreader); if(flag&128){_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);} } else row++; } return 0; } static BOOL S3M_ReadPattern(void) { int row=0,flag,ch; S3MNOTE *n,dummy; /* clear pattern data */ memset(s3mbuf,255,32*64*sizeof(S3MNOTE)); while(row<64) { flag=_mm_read_UBYTE(modreader); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_PATTERN; return 0; } if(flag) { ch=remap[flag&31]; if(ch!=-1) n=&s3mbuf[(64U*ch)+row]; else n=&dummy; if(flag&32) { n->note=_mm_read_UBYTE(modreader); n->ins=_mm_read_UBYTE(modreader); } if(flag&64) { n->vol=_mm_read_UBYTE(modreader); if (n->vol>64) n->vol=64; } if(flag&128) { n->cmd=_mm_read_UBYTE(modreader); n->inf=_mm_read_UBYTE(modreader); } } else row++; } return 1; } static UBYTE* S3M_ConvertTrack(S3MNOTE* tr) { int t; UniReset(); for(t=0;t<64;t++) { UBYTE note,ins,vol; note=tr[t].note; ins=tr[t].ins; vol=tr[t].vol; if((ins)&&(ins!=255)) UniInstrument(ins-1); if(note!=255) { if(note==254) { UniPTEffect(0xc,0); /* note cut command */ vol=255; } else UniNote(((note>>4)*OCTAVE)+(note&0xf)); /* normal note */ } if(vol<255) UniPTEffect(0xc,vol); S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf, tracker == 1 ? S3MIT_OLDSTYLE | S3MIT_SCREAM : S3MIT_OLDSTYLE); UniNewline(); } return UniDup(); } BOOL S3M_Load(BOOL curious) { int t,u,track = 0; SAMPLE *q; UBYTE pan[32]; /* try to read module header */ _mm_read_string(mh->songname,28,modreader); mh->t1a =_mm_read_UBYTE(modreader); mh->type =_mm_read_UBYTE(modreader); _mm_read_UBYTES(mh->unused1,2,modreader); mh->ordnum =_mm_read_I_UWORD(modreader); mh->insnum =_mm_read_I_UWORD(modreader); mh->patnum =_mm_read_I_UWORD(modreader); mh->flags =_mm_read_I_UWORD(modreader); mh->tracker =_mm_read_I_UWORD(modreader); mh->fileformat =_mm_read_I_UWORD(modreader); _mm_read_string(mh->scrm,4,modreader); mh->mastervol =_mm_read_UBYTE(modreader); mh->initspeed =_mm_read_UBYTE(modreader); mh->inittempo =_mm_read_UBYTE(modreader); mh->mastermult =_mm_read_UBYTE(modreader); mh->ultraclick =_mm_read_UBYTE(modreader); mh->pantable =_mm_read_UBYTE(modreader); _mm_read_UBYTES(mh->unused2,8,modreader); mh->special =_mm_read_I_UWORD(modreader); _mm_read_UBYTES(mh->channels,32,modreader); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } /* then we can decide the module type */ tracker=mh->tracker>>12; if((!tracker)||(tracker>=NUMTRACKERS)) tracker=NUMTRACKERS-1; /* unknown tracker */ else { if(mh->tracker>=0x3217) tracker=NUMTRACKERS+1; /* IT 2.14p4 */ else if(mh->tracker>=0x3216) tracker=NUMTRACKERS; /* IT 2.14p3 */ else tracker--; } of.modtype = strdup(S3M_Version[tracker]); if(trackertracker>>8) &0xf)+'0'; of.modtype[numeric[tracker]+2] = ((mh->tracker>>4)&0xf)+'0'; of.modtype[numeric[tracker]+3] = ((mh->tracker)&0xf)+'0'; } /* set module variables */ of.songname = DupStr(mh->songname,28,0); of.numpat = mh->patnum; of.reppos = 0; of.numins = of.numsmp = mh->insnum; of.initspeed = mh->initspeed; of.inittempo = mh->inittempo; of.initvolume = mh->mastervol<<1; of.flags |= UF_ARPMEM | UF_PANNING; if((mh->tracker==0x1300)||(mh->flags&64)) of.flags|=UF_S3MSLIDES; of.bpmlimit = 32; /* read the order data */ if(!AllocPositions(mh->ordnum)) return 0; if(!(origpositions=MikMod_calloc(mh->ordnum,sizeof(UWORD)))) return 0; for(t=0;tordnum;t++) { origpositions[t]=_mm_read_UBYTE(modreader); if((origpositions[t]>=mh->patnum)&&(origpositions[t]<254)) origpositions[t]=255/*mh->patnum-1*/; } if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } poslookupcnt=mh->ordnum; S3MIT_CreateOrders(curious); if(!(paraptr=(UWORD*)MikMod_malloc((of.numins+of.numpat)*sizeof(UWORD)))) return 0; /* read the instrument+pattern parapointers */ _mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modreader); if(mh->pantable==252) { /* read the panning table (ST 3.2 addition. See below for further portions of channel panning [past reampper]). */ _mm_read_UBYTES(pan,32,modreader); } if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } /* load samples */ if(!AllocSamples()) return 0; q = of.samples; for(t=0;t 64000) s.length = 64000; if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } q->samplename = DupStr(s.sampname,28,0); q->speed = s.c2spd; q->length = s.length; q->loopstart = s.loopbeg; q->loopend = s.loopend; q->volume = s.volume; q->seekpos = (((long)s.memsegh)<<16|s.memsegl)<<4; if(s.flags&1) q->flags |= SF_LOOP; if(s.flags&4) q->flags |= SF_16BITS; if(mh->fileformat==1) q->flags |= SF_SIGNED; /* don't load sample if it doesn't have the SCRS tag */ if(memcmp(s.scrs,"SCRS",4)) q->length = 0; q++; } /* determine the number of channels actually used. */ of.numchn = 0; memset(remap,-1,32*sizeof(UBYTE)); for(t=0;tchannels[t]<32)&&(remap[t]!=-1)) { if(mh->channels[t]<8) of.panning[remap[t]]=0x30; else of.panning[remap[t]]=0xc0; } if(mh->pantable==252) /* set panning positions according to panning table (new for st3.2) */ for(t=0;t<32;t++) if((pan[t]&0x20)&&(mh->channels[t]<32)&&(remap[t]!=-1)) of.panning[remap[t]]=(pan[t]&0xf)<<4; /* load pattern info */ of.numtrk=of.numpat*of.numchn; if(!AllocTracks()) return 0; if(!AllocPatterns()) return 0; for(t=0;t #endif #include #ifdef HAVE_MEMORY_H #include #endif #include #include "mikmod_internals.h" #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); #endif /*========== Module structure */ /* sample information */ typedef struct STMSAMPLE { CHAR filename[12]; UBYTE unused; /* 0x00 */ UBYTE instdisk; /* Instrument disk */ UWORD reserved; UWORD length; /* Sample length */ UWORD loopbeg; /* Loop start point */ UWORD loopend; /* Loop end point */ UBYTE volume; /* Volume */ UBYTE reserved2; UWORD c2spd; /* Good old c2spd */ ULONG reserved3; UWORD isa; } STMSAMPLE; /* header */ typedef struct STMHEADER { CHAR songname[20]; CHAR trackername[8]; /* !Scream! for ST 2.xx */ UBYTE unused; /* 0x1A */ UBYTE filetype; /* 1=song, 2=module */ UBYTE ver_major; UBYTE ver_minor; UBYTE inittempo; /* initspeed= stm inittempo>>4 */ UBYTE numpat; /* number of patterns */ UBYTE globalvol; UBYTE reserved[13]; STMSAMPLE sample[31]; /* STM sample data */ UBYTE patorder[128]; /* Docs say 64 - actually 128 */ } STMHEADER; typedef struct STMNOTE { UBYTE note,insvol,volcmd,cmdinf; } STMNOTE; /*========== Loader variables */ static STMNOTE *stmbuf = NULL; static STMHEADER *mh = NULL; /* tracker identifiers */ static CHAR* STM_Version[STM_NTRACKERS] = { "Screamtracker 2", "Converted by MOD2STM (STM format)", "Wuzamod (STM format)" }; /*========== Loader code */ BOOL STM_Test(void) { UBYTE str[44]; int t; _mm_fseek(modreader,20,SEEK_SET); _mm_read_UBYTES(str,44,modreader); if(str[9]!=2) return 0; /* STM Module = filetype 2 */ /* Prevent false positives for S3M files */ if(!memcmp(str+40,"SCRM",4)) return 0; for (t=0;tnote; ins = n->insvol>>3; vol = (n->insvol&7)+((n->volcmd&0x70)>>1); cmd = n->volcmd&15; inf = n->cmdinf; if((ins)&&(ins<32)) UniInstrument(ins-1); /* special values of [SBYTE0] are handled here we have no idea if these strange values will ever be encountered. but it appears as those stms sound correct. */ if((note==254)||(note==252)) { UniPTEffect(0xc,0); /* note cut */ n->volcmd|=0x80; } else /* if note < 251, then all three bytes are stored in the file */ if(note<251) UniNote((((note>>4)+2)*OCTAVE)+(note&0xf)); if((!(n->volcmd&0x80))&&(vol<65)) UniPTEffect(0xc,vol); if(cmd!=255) switch(cmd) { case 1: /* Axx set speed to xx */ UniPTEffect(0xf,inf>>4); break; case 2: /* Bxx position jump */ UniPTEffect(0xb,inf); break; case 3: /* Cxx patternbreak to row xx */ UniPTEffect(0xd,(((inf&0xf0)>>4)*10)+(inf&0xf)); break; case 4: /* Dxy volumeslide */ UniEffect(UNI_S3MEFFECTD,inf); break; case 5: /* Exy toneslide down */ UniEffect(UNI_S3MEFFECTE,inf); break; case 6: /* Fxy toneslide up */ UniEffect(UNI_S3MEFFECTF,inf); break; case 7: /* Gxx Tone portamento,speed xx */ UniPTEffect(0x3,inf); break; case 8: /* Hxy vibrato */ UniPTEffect(0x4,inf); break; case 9: /* Ixy tremor, ontime x, offtime y */ UniEffect(UNI_S3MEFFECTI,inf); break; case 0: /* protracker arpeggio */ if(!inf) break; /* fall through */ case 0xa: /* Jxy arpeggio */ UniPTEffect(0x0,inf); break; case 0xb: /* Kxy Dual command H00 & Dxy */ UniPTEffect(0x4,0); UniEffect(UNI_S3MEFFECTD,inf); break; case 0xc: /* Lxy Dual command G00 & Dxy */ UniPTEffect(0x3,0); UniEffect(UNI_S3MEFFECTD,inf); break; /* Support all these above, since ST2 can LOAD these values but can actually only play up to J - and J is only half-way implemented in ST2 */ case 0x18: /* Xxx amiga panning command 8xx */ UniPTEffect(0x8,inf); of.flags |= UF_PANNING; break; } } static UBYTE *STM_ConvertTrack(STMNOTE *n) { int t; UniReset(); for(t=0;t<64;t++) { STM_ConvertNote(n); UniNewline(); n+=of.numchn; } return UniDup(); } static BOOL STM_LoadPatterns(void) { int t,s,tracks=0; if(!AllocPatterns()) return 0; if(!AllocTracks()) return 0; /* Allocate temporary buffer for loading and converting the patterns */ for(t=0;tsongname,20,modreader); _mm_read_string(mh->trackername,8,modreader); mh->unused =_mm_read_UBYTE(modreader); mh->filetype =_mm_read_UBYTE(modreader); mh->ver_major =_mm_read_UBYTE(modreader); mh->ver_minor =_mm_read_UBYTE(modreader); mh->inittempo =_mm_read_UBYTE(modreader); if(!mh->inittempo) { _mm_errno=MMERR_NOT_A_MODULE; return 0; } mh->numpat =_mm_read_UBYTE(modreader); mh->globalvol =_mm_read_UBYTE(modreader); _mm_read_UBYTES(mh->reserved,13,modreader); for(t=0;t<31;t++) { STMSAMPLE *s=&mh->sample[t]; /* STM sample data */ _mm_read_string(s->filename,12,modreader); s->unused =_mm_read_UBYTE(modreader); s->instdisk =_mm_read_UBYTE(modreader); s->reserved =_mm_read_I_UWORD(modreader); s->length =_mm_read_I_UWORD(modreader); s->loopbeg =_mm_read_I_UWORD(modreader); s->loopend =_mm_read_I_UWORD(modreader); s->volume =_mm_read_UBYTE(modreader); s->reserved2=_mm_read_UBYTE(modreader); s->c2spd =_mm_read_I_UWORD(modreader); s->reserved3=_mm_read_I_ULONG(modreader); s->isa =_mm_read_I_UWORD(modreader); } _mm_read_UBYTES(mh->patorder,128,modreader); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } /* set module variables */ for(t=0;ttrackername,STM_Signatures[t],8)) break; of.modtype = strdup(STM_Version[t]); of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */ of.numpat = mh->numpat; of.inittempo = 125; /* mh->inittempo+0x1c; */ of.initspeed = mh->inittempo>>4; of.numchn = 4; /* get number of channels */ of.reppos = 0; of.flags |= UF_S3MSLIDES; of.bpmlimit = 32; t=0; if(!AllocPositions(0x80)) return 0; /* 99 terminates the patorder list */ while((mh->patorder[t]<=99)&&(mh->patorder[t]numpat)) { of.positions[t]=mh->patorder[t]; t++; } if(mh->patorder[t]<=99) t++; of.numpos=t; of.numtrk=of.numpat*of.numchn; of.numins=of.numsmp=31; if(!AllocSamples()) return 0; if(!STM_LoadPatterns()) return 0; MikMod_ISA=_mm_ftell(modreader); MikMod_ISA=(MikMod_ISA+15)&0xfffffff0; /* normalize */ for(q=of.samples,t=0;tsamplename = DupStr(mh->sample[t].filename,12,1); q->speed = (mh->sample[t].c2spd * 8363) / 8448; q->volume = mh->sample[t].volume; q->length = mh->sample[t].length; if (/*(!mh->sample[t].volume)||*/(q->length==1)) q->length=0; q->loopstart = mh->sample[t].loopbeg; q->loopend = mh->sample[t].loopend; q->seekpos = MikMod_ISA; MikMod_ISA+=q->length; MikMod_ISA=(MikMod_ISA+15)&0xfffffff0; /* normalize */ /* contrary to the STM specs, sample data is signed */ q->flags = SF_SIGNED; if(q->loopend && q->loopend != 0xffff) q->flags|=SF_LOOP; } return 1; } CHAR *STM_LoadTitle(void) { CHAR s[20]; _mm_fseek(modreader,0,SEEK_SET); if(!_mm_read_UBYTES(s,20,modreader)) return NULL; return(DupStr(s,20,1)); } /*========== Loader information */ MIKMODAPI MLOADER load_stm={ NULL, "STM", "STM (Scream Tracker)", STM_Init, STM_Test, STM_Load, STM_Cleanup, STM_LoadTitle }; /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/virtch2.c0000600000175000017500000006172210543202047017552 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: virtch2.c 2421 2006-08-19 00:36:21Z avolkov $ High-quality sample mixing routines, using a 32 bits mixing buffer, interpolation, and sample smoothing to improve sound quality and remove clicks. ==============================================================================*/ /* Future Additions: Low-Pass filter to remove annoying staticy buzz. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MEMORY_H #include #endif #include #include "mikmod_internals.h" /* Constant Definitions ==================== MAXVOL_FACTOR (was BITSHIFT in virtch.c) Controls the maximum volume of the output data. All mixed data is divided by this number after mixing, so larger numbers result in quieter mixing. Smaller numbers will increase the likeliness of distortion on loud modules. REVERBERATION Larger numbers result in shorter reverb duration. Longer reverb durations can cause unwanted static and make the reverb sound more like a crappy echo. SAMPLING_SHIFT Specified the shift multiplier which controls by how much the mixing rate is multiplied while mixing. Higher values can improve quality by smoothing the sound and reducing pops and clicks. Note, this is a shift value, so a value of 2 becomes a mixing-rate multiplier of 4, and a value of 3 = 8, etc. FRACBITS The number of bits per integer devoted to the fractional part of the number. Generally, this number should not be changed for any reason. !!! IMPORTANT !!! All values below MUST ALWAYS be greater than 0 */ #define MAXVOL_FACTOR (1<<9) #define REVERBERATION 11000L #define SAMPLING_SHIFT 2 #define SAMPLING_FACTOR (1UL< sample has to be restarted */ UBYTE active; /* =1 -> sample is playing */ UWORD flags; /* 16/8 bits looping/one-shot */ SWORD handle; /* identifies the sample */ ULONG start; /* start index */ ULONG size; /* samplesize */ ULONG reppos; /* loop start */ ULONG repend; /* loop end */ ULONG frq; /* current frequency */ int vol; /* current volume */ int pan; /* current panning position */ int click; int rampvol; SLONG lastvalL,lastvalR; int lvolsel,rvolsel; /* Volume factor in range 0-255 */ int oldlvol,oldrvol; SLONGLONG current; /* current index in the sample */ SLONGLONG increment; /* increment value */ } VINFO; static SWORD **Samples; static VINFO *vinf=NULL,*vnf; static long tickleft,samplesthatfit,vc_memory=0; static int vc_softchn; static SLONGLONG idxsize,idxlpos,idxlend; static SLONG *vc_tickbuf=NULL; static UWORD vc_mode; /* Reverb control variables */ static int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8; static ULONG RVRindex; /* For Mono or Left Channel */ static SLONG *RVbufL1=NULL,*RVbufL2=NULL,*RVbufL3=NULL,*RVbufL4=NULL, *RVbufL5=NULL,*RVbufL6=NULL,*RVbufL7=NULL,*RVbufL8=NULL; /* For Stereo only (Right Channel) */ static SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL, *RVbufR5=NULL,*RVbufR6=NULL,*RVbufR7=NULL,*RVbufR8=NULL; #ifdef NATIVE_64BIT_INT #define NATIVE SLONGLONG #else #define NATIVE SLONG #endif /*========== 32 bit sample mixers - only for 32 bit platforms */ #ifndef NATIVE_64BIT_INT static SLONG Mix32MonoNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo) { SWORD sample=0; SLONG i,f; while(todo--) { i=index>>FRACBITS,f=index&FRACMASK; sample=(((SLONG)(srce[i]*(FRACMASK+1L-f)) + ((SLONG)srce[i+1]*f)) >> FRACBITS); index+=increment; if(vnf->rampvol) { *dest++ += (long)( ( ( (SLONG)(vnf->oldlvol*vnf->rampvol) + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * (SLONG)sample ) >> CLICK_SHIFT ); vnf->rampvol--; } else if(vnf->click) { *dest++ += (long)( ( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * (SLONG)sample ) + (vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT ); vnf->click--; } else *dest++ +=vnf->lvolsel*sample; } vnf->lastvalL=vnf->lvolsel * sample; return index; } static SLONG Mix32StereoNormal(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,ULONG todo) { SWORD sample=0; SLONG i,f; while(todo--) { i=index>>FRACBITS,f=index&FRACMASK; sample=((((SLONG)srce[i]*(FRACMASK+1L-f)) + ((SLONG)srce[i+1] * f)) >> FRACBITS); index += increment; if(vnf->rampvol) { *dest++ += (long)( ( ( ((SLONG)vnf->oldlvol*vnf->rampvol) + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * (SLONG)sample ) >> CLICK_SHIFT ); *dest++ += (long)( ( ( ((SLONG)vnf->oldrvol*vnf->rampvol) + (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * (SLONG)sample ) >> CLICK_SHIFT ); vnf->rampvol--; } else if(vnf->click) { *dest++ += (long)( ( ( (SLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * (SLONG)sample ) + (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT ); *dest++ += (long)( ( ( ((SLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * (SLONG)sample ) + (vnf->lastvalR * vnf->click) ) >> CLICK_SHIFT ); vnf->click--; } else { *dest++ +=vnf->lvolsel*sample; *dest++ +=vnf->rvolsel*sample; } } vnf->lastvalL=vnf->lvolsel*sample; vnf->lastvalR=vnf->rvolsel*sample; return index; } static SLONG Mix32StereoSurround(const SWORD* srce,SLONG* dest,SLONG index,SLONG increment,ULONG todo) { SWORD sample=0; long whoop; SLONG i, f; while(todo--) { i=index>>FRACBITS,f=index&FRACMASK; sample=((((SLONG)srce[i]*(FRACMASK+1L-f)) + ((SLONG)srce[i+1]*f)) >> FRACBITS); index+=increment; if(vnf->rampvol) { whoop=(long)( ( ( (SLONG)(vnf->oldlvol*vnf->rampvol) + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * (SLONG)sample) >> CLICK_SHIFT ); *dest++ +=whoop; *dest++ -=whoop; vnf->rampvol--; } else if(vnf->click) { whoop = (long)( ( ( ((SLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * (SLONG)sample) + (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT ); *dest++ +=whoop; *dest++ -=whoop; vnf->click--; } else { *dest++ +=vnf->lvolsel*sample; *dest++ -=vnf->lvolsel*sample; } } vnf->lastvalL=vnf->lvolsel*sample; vnf->lastvalR=vnf->lvolsel*sample; return index; } #endif /*========== 64 bit mixers */ static SLONGLONG MixMonoNormal(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,SLONG todo) { SWORD sample=0; SLONGLONG i,f; while(todo--) { i=index>>FRACBITS,f=index&FRACMASK; sample=(((SLONGLONG)(srce[i]*(FRACMASK+1L-f)) + ((SLONGLONG)srce[i+1]*f)) >> FRACBITS); index+=increment; if(vnf->rampvol) { *dest++ += (long)( ( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); vnf->rampvol--; } else if(vnf->click) { *dest++ += (long)( ( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * (SLONGLONG)sample ) + (vnf->lastvalL*vnf->click) ) >> CLICK_SHIFT ); vnf->click--; } else *dest++ +=vnf->lvolsel*sample; } vnf->lastvalL=vnf->lvolsel * sample; return index; } static SLONGLONG MixStereoNormal(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,ULONG todo) { SWORD sample=0; SLONGLONG i,f; while(todo--) { i=index>>FRACBITS,f=index&FRACMASK; sample=((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + ((SLONGLONG)srce[i+1] * f)) >> FRACBITS); index += increment; if(vnf->rampvol) { *dest++ += (long)( ( ( ((SLONGLONG)vnf->oldlvol*vnf->rampvol) + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); *dest++ += (long)( ( ( ((SLONGLONG)vnf->oldrvol*vnf->rampvol) + (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * (SLONGLONG)sample ) >> CLICK_SHIFT ); vnf->rampvol--; } else if(vnf->click) { *dest++ += (long)( ( ( (SLONGLONG)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * (SLONGLONG)sample ) + (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT ); *dest++ += (long)( ( ( ((SLONGLONG)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) * (SLONGLONG)sample ) + (vnf->lastvalR * vnf->click) ) >> CLICK_SHIFT ); vnf->click--; } else { *dest++ +=vnf->lvolsel*sample; *dest++ +=vnf->rvolsel*sample; } } vnf->lastvalL=vnf->lvolsel*sample; vnf->lastvalR=vnf->rvolsel*sample; return index; } static SLONGLONG MixStereoSurround(const SWORD* srce,SLONG* dest,SLONGLONG index,SLONGLONG increment,ULONG todo) { SWORD sample=0; long whoop; SLONGLONG i, f; while(todo--) { i=index>>FRACBITS,f=index&FRACMASK; sample=((((SLONGLONG)srce[i]*(FRACMASK+1L-f)) + ((SLONGLONG)srce[i+1]*f)) >> FRACBITS); index+=increment; if(vnf->rampvol) { whoop=(long)( ( ( (SLONGLONG)(vnf->oldlvol*vnf->rampvol) + (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) * (SLONGLONG)sample) >> CLICK_SHIFT ); *dest++ +=whoop; *dest++ -=whoop; vnf->rampvol--; } else if(vnf->click) { whoop = (long)( ( ( ((SLONGLONG)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) * (SLONGLONG)sample) + (vnf->lastvalL * vnf->click) ) >> CLICK_SHIFT ); *dest++ +=whoop; *dest++ -=whoop; vnf->click--; } else { *dest++ +=vnf->lvolsel*sample; *dest++ -=vnf->lvolsel*sample; } } vnf->lastvalL=vnf->lvolsel*sample; vnf->lastvalR=vnf->lvolsel*sample; return index; } static void(*Mix32to16)(SWORD* dste,const SLONG* srce,NATIVE count); static void(*Mix32to8)(SBYTE* dste,const SLONG* srce,NATIVE count); static void(*MixReverb)(SLONG* srce,NATIVE count); /* Reverb macros */ #define COMPUTE_LOC(n) loc##n = RVRindex % RVc##n #define COMPUTE_LECHO(n) RVbufL##n [loc##n ]=speedup+((ReverbPct*RVbufL##n [loc##n ])>>7) #define COMPUTE_RECHO(n) RVbufR##n [loc##n ]=speedup+((ReverbPct*RVbufR##n [loc##n ])>>7) static void MixReverb_Normal(SLONG* srce,NATIVE count) { NATIVE speedup; int ReverbPct; unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8; ReverbPct=58+(md_reverb*4); COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); while(count--) { /* Compute the left channel echo buffers */ speedup = *srce >> 3; COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4); COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8); /* Prepare to compute actual finalized data */ RVRindex++; COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); /* left channel */ *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; } } static void MixReverb_Stereo(SLONG *srce,NATIVE count) { NATIVE speedup; int ReverbPct; unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8; ReverbPct=58+(md_reverb*4); COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); while(count--) { /* Compute the left channel echo buffers */ speedup = *srce >> 3; COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4); COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8); /* Compute the right channel echo buffers */ speedup = srce[1] >> 3; COMPUTE_RECHO(1); COMPUTE_RECHO(2); COMPUTE_RECHO(3); COMPUTE_RECHO(4); COMPUTE_RECHO(5); COMPUTE_RECHO(6); COMPUTE_RECHO(7); COMPUTE_RECHO(8); /* Prepare to compute actual finalized data */ RVRindex++; COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4); COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8); /* left channel */ *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8]; /* right channel */ *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+ RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8]; } } /* Mixing macros */ #define EXTRACT_SAMPLE(var,attenuation) var=*srce++/(MAXVOL_FACTOR*attenuation) #define CHECK_SAMPLE(var,bound) var=(var>=bound)?bound-1:(var<-bound)?-bound:var static void Mix32To16_Normal(SWORD* dste,const SLONG* srce,NATIVE count) { NATIVE x1,x2,tmpx; int i; for(count/=SAMPLING_FACTOR;count;count--) { tmpx=0; for(i=SAMPLING_FACTOR/2;i;i--) { EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1); CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768); tmpx+=x1+x2; } *dste++ =tmpx/SAMPLING_FACTOR; } } static void Mix32To16_Stereo(SWORD* dste,const SLONG* srce,NATIVE count) { NATIVE x1,x2,x3,x4,tmpx,tmpy; int i; for(count/=SAMPLING_FACTOR;count;count--) { tmpx=tmpy=0; for(i=SAMPLING_FACTOR/2;i;i--) { EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1); EXTRACT_SAMPLE(x3,1); EXTRACT_SAMPLE(x4,1); CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768); CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768); tmpx+=x1+x3; tmpy+=x2+x4; } *dste++ =tmpx/SAMPLING_FACTOR; *dste++ =tmpy/SAMPLING_FACTOR; } } static void Mix32To8_Normal(SBYTE* dste,const SLONG* srce,NATIVE count) { NATIVE x1,x2,tmpx; int i; for(count/=SAMPLING_FACTOR;count;count--) { tmpx = 0; for(i=SAMPLING_FACTOR/2;i;i--) { EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256); CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128); tmpx+=x1+x2; } *dste++ =(tmpx/SAMPLING_FACTOR)+128; } } static void Mix32To8_Stereo(SBYTE* dste,const SLONG* srce,NATIVE count) { NATIVE x1,x2,x3,x4,tmpx,tmpy; int i; for(count/=SAMPLING_FACTOR;count;count--) { tmpx=tmpy=0; for(i=SAMPLING_FACTOR/2;i;i--) { EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256); EXTRACT_SAMPLE(x3,256); EXTRACT_SAMPLE(x4,256); CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128); CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128); tmpx+=x1+x3; tmpy+=x2+x4; } *dste++ =(tmpx/SAMPLING_FACTOR)+128; *dste++ =(tmpy/SAMPLING_FACTOR)+128; } } static void AddChannel(SLONG* ptr,NATIVE todo) { SLONGLONG end,done; SWORD *s; if(!(s=Samples[vnf->handle])) { vnf->current = vnf->active = 0; vnf->lastvalL = vnf->lastvalR = 0; return; } /* update the 'current' index so the sample loops, or stops playing if it reached the end of the sample */ while(todo>0) { SLONGLONG endpos; if(vnf->flags & SF_REVERSE) { /* The sample is playing in reverse */ if((vnf->flags&SF_LOOP)&&(vnf->currentflags & SF_BIDI) { /* sample is doing bidirectional loops, so 'bounce' the current index against the idxlpos */ vnf->current = idxlpos+(idxlpos-vnf->current); vnf->flags &= ~SF_REVERSE; vnf->increment = -vnf->increment; } else /* normal backwards looping, so set the current position to loopend index */ vnf->current=idxlend-(idxlpos-vnf->current); } else { /* the sample is not looping, so check if it reached index 0 */ if(vnf->current < 0) { /* playing index reached 0, so stop playing this sample */ vnf->current = vnf->active = 0; break; } } } else { /* The sample is playing forward */ if((vnf->flags & SF_LOOP) && (vnf->current >= idxlend)) { /* the sample is looping, check the loopend index */ if(vnf->flags & SF_BIDI) { /* sample is doing bidirectional loops, so 'bounce' the current index against the idxlend */ vnf->flags |= SF_REVERSE; vnf->increment = -vnf->increment; vnf->current = idxlend-(vnf->current-idxlend); } else /* normal backwards looping, so set the current position to loopend index */ vnf->current=idxlpos+(vnf->current-idxlend); } else { /* sample is not looping, so check if it reached the last position */ if(vnf->current >= idxsize) { /* yes, so stop playing this sample */ vnf->current = vnf->active = 0; break; } } } end=(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0: (vnf->flags&SF_LOOP)?idxlend:idxsize; /* if the sample is not blocked... */ if((end==vnf->current)||(!vnf->increment)) done=0; else { done=MIN((end-vnf->current)/vnf->increment+1,todo); if(done<0) done=0; } if(!done) { vnf->active = 0; break; } endpos=vnf->current+done*vnf->increment; if(vnf->vol || vnf->rampvol) { #ifndef NATIVE_64BIT_INT /* use the 32 bit mixers as often as we can (they're much faster) */ if((vnf->current<0x7fffffff)&&(endpos<0x7fffffff)) { if(vc_mode & DMODE_STEREO) { if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND)) vnf->current=Mix32StereoSurround (s,ptr,vnf->current,vnf->increment,done); else vnf->current=Mix32StereoNormal (s,ptr,vnf->current,vnf->increment,done); } else vnf->current=Mix32MonoNormal (s,ptr,vnf->current,vnf->increment,done); } else #endif { if(vc_mode & DMODE_STEREO) { if((vnf->pan==PAN_SURROUND)&&(vc_mode&DMODE_SURROUND)) vnf->current=MixStereoSurround (s,ptr,vnf->current,vnf->increment,done); else vnf->current=MixStereoNormal (s,ptr,vnf->current,vnf->increment,done); } else vnf->current=MixMonoNormal (s,ptr,vnf->current,vnf->increment,done); } } else { vnf->lastvalL = vnf->lastvalR = 0; /* update sample position */ vnf->current=endpos; } todo -= done; ptr +=(vc_mode & DMODE_STEREO)?(done<<1):done; } } #define _IN_VIRTCH_ #define VC1_SilenceBytes VC2_SilenceBytes #define VC1_WriteSamples VC2_WriteSamples #define VC1_WriteBytes VC2_WriteBytes #define VC1_Exit VC2_Exit #define VC1_VoiceSetVolume VC2_VoiceSetVolume #define VC1_VoiceGetVolume VC2_VoiceGetVolume #define VC1_VoiceSetPanning VC2_VoiceSetPanning #define VC1_VoiceGetPanning VC2_VoiceGetPanning #define VC1_VoiceSetFrequency VC2_VoiceSetFrequency #define VC1_VoiceGetFrequency VC2_VoiceGetFrequency #define VC1_VoicePlay VC2_VoicePlay #define VC1_VoiceStop VC2_VoiceStop #define VC1_VoiceStopped VC2_VoiceStopped #define VC1_VoiceGetPosition VC2_VoiceGetPosition #define VC1_SampleUnload VC2_SampleUnload #define VC1_SampleLoad VC2_SampleLoad #define VC1_SampleSpace VC2_SampleSpace #define VC1_SampleLength VC2_SampleLength #define VC1_VoiceRealVolume VC2_VoiceRealVolume #include "virtch_common.c" #undef _IN_VIRTCH_ void VC2_WriteSamples(SBYTE* buf,ULONG todo) { int left,portion=0; SBYTE *buffer; int t,pan,vol; todo*=SAMPLING_FACTOR; while(todo) { if(!tickleft) { if(vc_mode & DMODE_SOFT_MUSIC) md_player(); tickleft=(md_mixfreq*125L*SAMPLING_FACTOR)/(md_bpm*50L); tickleft&=~(SAMPLING_FACTOR-1); } left = MIN(tickleft, (long)todo); buffer = buf; tickleft -= left; todo -= left; buf += samples2bytes(left)/SAMPLING_FACTOR; while(left) { portion = MIN(left, samplesthatfit); memset(vc_tickbuf,0,portion<<((vc_mode&DMODE_STEREO)?3:2)); for(t=0;tkick) { vnf->current=((SLONGLONG)(vnf->start))<kick = 0; vnf->active = 1; vnf->click = CLICK_BUFFER; vnf->rampvol = 0; } if(!vnf->frq) vnf->active = 0; if(vnf->active) { vnf->increment=((SLONGLONG)(vnf->frq)<<(FRACBITS-SAMPLING_SHIFT)) /md_mixfreq; if(vnf->flags&SF_REVERSE) vnf->increment=-vnf->increment; vol = vnf->vol; pan = vnf->pan; vnf->oldlvol=vnf->lvolsel;vnf->oldrvol=vnf->rvolsel; if(vc_mode & DMODE_STEREO) { if(pan!=PAN_SURROUND) { vnf->lvolsel=(vol*(PAN_RIGHT-pan))>>8; vnf->rvolsel=(vol*pan)>>8; } else { vnf->lvolsel=vnf->rvolsel=(vol * 256L) / 480; } } else vnf->lvolsel=vol; idxsize=(vnf->size)?((SLONGLONG)(vnf->size)<repend)?((SLONGLONG)(vnf->repend)<reppos)<15) md_reverb=15; MixReverb(vc_tickbuf,portion); } if(vc_mode & DMODE_16BITS) Mix32to16((SWORD*)buffer,vc_tickbuf,portion); else Mix32to8((SBYTE*)buffer,vc_tickbuf,portion); buffer += samples2bytes(portion) / SAMPLING_FACTOR; left -= portion; } } } BOOL VC2_Init(void) { VC_SetupPointers(); if (!(md_mode&DMODE_HQMIXER)) return VC1_Init(); if(!(Samples=(SWORD**)MikMod_calloc(MAXSAMPLEHANDLES,sizeof(SWORD*)))) { _mm_errno = MMERR_INITIALIZING_MIXER; return 1; } if(!vc_tickbuf) if(!(vc_tickbuf=(SLONG*)MikMod_malloc((TICKLSIZE+32)*sizeof(SLONG)))) { _mm_errno = MMERR_INITIALIZING_MIXER; return 1; } if(md_mode & DMODE_STEREO) { Mix32to16 = Mix32To16_Stereo; Mix32to8 = Mix32To8_Stereo; MixReverb = MixReverb_Stereo; } else { Mix32to16 = Mix32To16_Normal; Mix32to8 = Mix32To8_Normal; MixReverb = MixReverb_Normal; } md_mode |= DMODE_INTERP; vc_mode = md_mode; return 0; } BOOL VC2_PlayStart(void) { md_mode|=DMODE_INTERP; samplesthatfit = TICKLSIZE; if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1; tickleft = 0; RVc1 = (5000L * md_mixfreq) / (REVERBERATION * 10); RVc2 = (5078L * md_mixfreq) / (REVERBERATION * 10); RVc3 = (5313L * md_mixfreq) / (REVERBERATION * 10); RVc4 = (5703L * md_mixfreq) / (REVERBERATION * 10); RVc5 = (6250L * md_mixfreq) / (REVERBERATION * 10); RVc6 = (6953L * md_mixfreq) / (REVERBERATION * 10); RVc7 = (7813L * md_mixfreq) / (REVERBERATION * 10); RVc8 = (8828L * md_mixfreq) / (REVERBERATION * 10); if(!(RVbufL1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1; if(!(RVbufL2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; if(!(RVbufL3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; if(!(RVbufL4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; if(!(RVbufL5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1; if(!(RVbufL6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1; if(!(RVbufL7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; if(!(RVbufL8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; if(!(RVbufR1=(SLONG*)MikMod_calloc((RVc1+1),sizeof(SLONG)))) return 1; if(!(RVbufR2=(SLONG*)MikMod_calloc((RVc2+1),sizeof(SLONG)))) return 1; if(!(RVbufR3=(SLONG*)MikMod_calloc((RVc3+1),sizeof(SLONG)))) return 1; if(!(RVbufR4=(SLONG*)MikMod_calloc((RVc4+1),sizeof(SLONG)))) return 1; if(!(RVbufR5=(SLONG*)MikMod_calloc((RVc5+1),sizeof(SLONG)))) return 1; if(!(RVbufR6=(SLONG*)MikMod_calloc((RVc6+1),sizeof(SLONG)))) return 1; if(!(RVbufR7=(SLONG*)MikMod_calloc((RVc7+1),sizeof(SLONG)))) return 1; if(!(RVbufR8=(SLONG*)MikMod_calloc((RVc8+1),sizeof(SLONG)))) return 1; RVRindex = 0; return 0; } void VC2_PlayStop(void) { if(RVbufL1) MikMod_free(RVbufL1); if(RVbufL2) MikMod_free(RVbufL2); if(RVbufL3) MikMod_free(RVbufL3); if(RVbufL4) MikMod_free(RVbufL4); if(RVbufL5) MikMod_free(RVbufL5); if(RVbufL6) MikMod_free(RVbufL6); if(RVbufL7) MikMod_free(RVbufL7); if(RVbufL8) MikMod_free(RVbufL8); if(RVbufR1) MikMod_free(RVbufR1); if(RVbufR2) MikMod_free(RVbufR2); if(RVbufR3) MikMod_free(RVbufR3); if(RVbufR4) MikMod_free(RVbufR4); if(RVbufR5) MikMod_free(RVbufR5); if(RVbufR6) MikMod_free(RVbufR6); if(RVbufR7) MikMod_free(RVbufR7); if(RVbufR8) MikMod_free(RVbufR8); RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL; RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL; } BOOL VC2_SetNumVoices(void) { int t; md_mode|=DMODE_INTERP; if(!(vc_softchn=md_softchn)) return 0; if(vinf) MikMod_free(vinf); if(!(vinf=MikMod_calloc(sizeof(VINFO),vc_softchn))) return 1; for(t=0;t #if defined(__OS2__)||defined(__EMX__)||defined(WIN32)||defined(WIN64) #define strcasecmp(s,t) stricmp(s,t) #endif #define MIKMOD_INTERNAL #include "mikmod_build.h" /*========== More type definitions */ /* SLONGLONG: 64bit, signed */ #if defined(__arch64__) || defined(__alpha) || defined(__x86_64) \ || defined(_M_IA64) || defined(_M_AMD64) typedef long SLONGLONG; #define NATIVE_64BIT_INT #elif defined(__powerpc64__) typedef long long SLONGLONG; #define NATIVE_64BIT_INT #elif defined(__WATCOMC__) typedef __int64 SLONGLONG; #elif defined(WIN32) && !defined(__MWERKS__) typedef LONGLONG SLONGLONG; #elif macintosh && !TYPE_LONGLONG #include typedef SInt64 SLONGLONG; #else typedef long long SLONGLONG; #endif /*========== Error handling */ #define _mm_errno MikMod_errno #define _mm_critical MikMod_critical extern MikMod_handler_t _mm_errorhandler; /*========== MT stuff */ #ifdef HAVE_PTHREAD #include #define DECLARE_MUTEX(name) \ extern pthread_mutex_t _mm_mutex_##name #define MUTEX_LOCK(name) \ pthread_mutex_lock(&_mm_mutex_##name) #define MUTEX_UNLOCK(name) \ pthread_mutex_unlock(&_mm_mutex_##name) #elif defined(__OS2__)||defined(__EMX__) #define DECLARE_MUTEX(name) \ extern HMTX _mm_mutex_##name #define MUTEX_LOCK(name) \ if(_mm_mutex_##name) \ DosRequestMutexSem(_mm_mutex_##name,SEM_INDEFINITE_WAIT) #define MUTEX_UNLOCK(name) \ if(_mm_mutex_##name) \ DosReleaseMutexSem(_mm_mutex_##name) #elif defined(WIN32) || defined(WIN64) #include #define DECLARE_MUTEX(name) \ extern HANDLE _mm_mutex_##name #define MUTEX_LOCK(name) \ if(_mm_mutex_##name) \ WaitForSingleObject(_mm_mutex_##name,INFINITE) #define MUTEX_UNLOCK(name) \ if(_mm_mutex_##name) \ ReleaseMutex(_mm_mutex_##name) #else #define DECLARE_MUTEX(name) \ extern void *_mm_mutex_##name #define MUTEX_LOCK(name) #define MUTEX_UNLOCK(name) #endif DECLARE_MUTEX(lists); DECLARE_MUTEX(vars); /*========== Portable file I/O */ extern MREADER* _mm_new_mem_reader(const void *buffer, int len); extern void _mm_delete_mem_reader(MREADER *reader); extern MREADER* _mm_new_file_reader(FILE* fp); extern void _mm_delete_file_reader(MREADER*); extern MWRITER* _mm_new_file_writer(FILE *fp); extern void _mm_delete_file_writer(MWRITER*); extern BOOL _mm_FileExists(CHAR *fname); #define _mm_write_SBYTE(x,y) y->Put(y,(int)x) #define _mm_write_UBYTE(x,y) y->Put(y,(int)x) #define _mm_read_SBYTE(x) (SBYTE)x->Get(x) #define _mm_read_UBYTE(x) (UBYTE)x->Get(x) #define _mm_write_SBYTES(x,y,z) z->Write(z,(void *)x,y) #define _mm_write_UBYTES(x,y,z) z->Write(z,(void *)x,y) #define _mm_read_SBYTES(x,y,z) z->Read(z,(void *)x,y) #define _mm_read_UBYTES(x,y,z) z->Read(z,(void *)x,y) #define _mm_fseek(x,y,z) x->Seek(x,y,z) #define _mm_ftell(x) x->Tell(x) #define _mm_rewind(x) _mm_fseek(x,0,SEEK_SET) #define _mm_eof(x) x->Eof(x) extern void _mm_iobase_setcur(MREADER*); extern void _mm_iobase_revert(MREADER*); extern FILE *_mm_fopen(CHAR*,CHAR*); extern int _mm_fclose(FILE *); extern void _mm_write_string(CHAR*,MWRITER*); extern int _mm_read_string (CHAR*,int,MREADER*); extern SWORD _mm_read_M_SWORD(MREADER*); extern SWORD _mm_read_I_SWORD(MREADER*); extern UWORD _mm_read_M_UWORD(MREADER*); extern UWORD _mm_read_I_UWORD(MREADER*); extern SLONG _mm_read_M_SLONG(MREADER*); extern SLONG _mm_read_I_SLONG(MREADER*); extern ULONG _mm_read_M_ULONG(MREADER*); extern ULONG _mm_read_I_ULONG(MREADER*); extern int _mm_read_M_SWORDS(SWORD*,int,MREADER*); extern int _mm_read_I_SWORDS(SWORD*,int,MREADER*); extern int _mm_read_M_UWORDS(UWORD*,int,MREADER*); extern int _mm_read_I_UWORDS(UWORD*,int,MREADER*); extern int _mm_read_M_SLONGS(SLONG*,int,MREADER*); extern int _mm_read_I_SLONGS(SLONG*,int,MREADER*); extern int _mm_read_M_ULONGS(ULONG*,int,MREADER*); extern int _mm_read_I_ULONGS(ULONG*,int,MREADER*); extern void _mm_write_M_SWORD(SWORD,MWRITER*); extern void _mm_write_I_SWORD(SWORD,MWRITER*); extern void _mm_write_M_UWORD(UWORD,MWRITER*); extern void _mm_write_I_UWORD(UWORD,MWRITER*); extern void _mm_write_M_SLONG(SLONG,MWRITER*); extern void _mm_write_I_SLONG(SLONG,MWRITER*); extern void _mm_write_M_ULONG(ULONG,MWRITER*); extern void _mm_write_I_ULONG(ULONG,MWRITER*); extern void _mm_write_M_SWORDS(SWORD*,int,MWRITER*); extern void _mm_write_I_SWORDS(SWORD*,int,MWRITER*); extern void _mm_write_M_UWORDS(UWORD*,int,MWRITER*); extern void _mm_write_I_UWORDS(UWORD*,int,MWRITER*); extern void _mm_write_M_SLONGS(SLONG*,int,MWRITER*); extern void _mm_write_I_SLONGS(SLONG*,int,MWRITER*); extern void _mm_write_M_ULONGS(ULONG*,int,MWRITER*); extern void _mm_write_I_ULONGS(ULONG*,int,MWRITER*); /*========== Samples */ /* This is a handle of sorts attached to any sample registered with SL_RegisterSample. Generally, this only need be used or changed by the loaders and drivers of mikmod. */ typedef struct SAMPLOAD { struct SAMPLOAD *next; ULONG length; /* length of sample (in samples!) */ ULONG loopstart; /* repeat position (relative to start, in samples) */ ULONG loopend; /* repeat end */ UWORD infmt,outfmt; int scalefactor; SAMPLE* sample; MREADER* reader; } SAMPLOAD; /*========== Sample and waves loading interface */ extern void SL_HalveSample(SAMPLOAD*,int); extern void SL_Sample8to16(SAMPLOAD*); extern void SL_Sample16to8(SAMPLOAD*); extern void SL_SampleSigned(SAMPLOAD*); extern void SL_SampleUnsigned(SAMPLOAD*); extern BOOL SL_LoadSamples(void); extern SAMPLOAD* SL_RegisterSample(SAMPLE*,int,MREADER*); extern BOOL SL_Load(void*,SAMPLOAD*,ULONG); extern BOOL SL_Init(SAMPLOAD*); extern void SL_Exit(SAMPLOAD*); /*========== Internal module representation (UniMod) interface */ /* number of notes in an octave */ #define OCTAVE 12 extern void UniSetRow(UBYTE*); extern UBYTE UniGetByte(void); extern UWORD UniGetWord(void); extern UBYTE* UniFindRow(UBYTE*,UWORD); extern void UniSkipOpcode(void); extern void UniReset(void); extern void UniWriteByte(UBYTE); extern void UniWriteWord(UWORD); extern void UniNewline(void); extern UBYTE* UniDup(void); extern BOOL UniInit(void); extern void UniCleanup(void); extern void UniEffect(UWORD,UWORD); #define UniInstrument(x) UniEffect(UNI_INSTRUMENT,x) #define UniNote(x) UniEffect(UNI_NOTE,x) extern void UniPTEffect(UBYTE,UBYTE); extern void UniVolEffect(UWORD,UBYTE); /*========== Module Commands */ enum { /* Simple note */ UNI_NOTE = 1, /* Instrument change */ UNI_INSTRUMENT, /* Protracker effects */ UNI_PTEFFECT0, /* arpeggio */ UNI_PTEFFECT1, /* porta up */ UNI_PTEFFECT2, /* porta down */ UNI_PTEFFECT3, /* porta to note */ UNI_PTEFFECT4, /* vibrato */ UNI_PTEFFECT5, /* dual effect 3+A */ UNI_PTEFFECT6, /* dual effect 4+A */ UNI_PTEFFECT7, /* tremolo */ UNI_PTEFFECT8, /* pan */ UNI_PTEFFECT9, /* sample offset */ UNI_PTEFFECTA, /* volume slide */ UNI_PTEFFECTB, /* pattern jump */ UNI_PTEFFECTC, /* set volume */ UNI_PTEFFECTD, /* pattern break */ UNI_PTEFFECTE, /* extended effects */ UNI_PTEFFECTF, /* set speed */ /* Scream Tracker effects */ UNI_S3MEFFECTA, /* set speed */ UNI_S3MEFFECTD, /* volume slide */ UNI_S3MEFFECTE, /* porta down */ UNI_S3MEFFECTF, /* porta up */ UNI_S3MEFFECTI, /* tremor */ UNI_S3MEFFECTQ, /* retrig */ UNI_S3MEFFECTR, /* tremolo */ UNI_S3MEFFECTT, /* set tempo */ UNI_S3MEFFECTU, /* fine vibrato */ UNI_KEYOFF, /* note off */ /* Fast Tracker effects */ UNI_KEYFADE, /* note fade */ UNI_VOLEFFECTS, /* volume column effects */ UNI_XMEFFECT4, /* vibrato */ UNI_XMEFFECT6, /* dual effect 4+A */ UNI_XMEFFECTA, /* volume slide */ UNI_XMEFFECTE1, /* fine porta up */ UNI_XMEFFECTE2, /* fine porta down */ UNI_XMEFFECTEA, /* fine volume slide up */ UNI_XMEFFECTEB, /* fine volume slide down */ UNI_XMEFFECTG, /* set global volume */ UNI_XMEFFECTH, /* global volume slide */ UNI_XMEFFECTL, /* set envelope position */ UNI_XMEFFECTP, /* pan slide */ UNI_XMEFFECTX1, /* extra fine porta up */ UNI_XMEFFECTX2, /* extra fine porta down */ /* Impulse Tracker effects */ UNI_ITEFFECTG, /* porta to note */ UNI_ITEFFECTH, /* vibrato */ UNI_ITEFFECTI, /* tremor (xy not incremented) */ UNI_ITEFFECTM, /* set channel volume */ UNI_ITEFFECTN, /* slide / fineslide channel volume */ UNI_ITEFFECTP, /* slide / fineslide channel panning */ UNI_ITEFFECTT, /* slide tempo */ UNI_ITEFFECTU, /* fine vibrato */ UNI_ITEFFECTW, /* slide / fineslide global volume */ UNI_ITEFFECTY, /* panbrello */ UNI_ITEFFECTZ, /* resonant filters */ UNI_ITEFFECTS0, /* UltraTracker effects */ UNI_ULTEFFECT9, /* Sample fine offset */ /* OctaMED effects */ UNI_MEDSPEED, UNI_MEDEFFECTF1, /* play note twice */ UNI_MEDEFFECTF2, /* delay note */ UNI_MEDEFFECTF3, /* play note three times */ /* Oktalyzer effects */ UNI_OKTARP, /* arpeggio */ UNI_LAST }; extern UWORD unioperands[UNI_LAST]; /* IT / S3M Extended SS effects: */ enum { SS_GLISSANDO = 1, SS_FINETUNE, SS_VIBWAVE, SS_TREMWAVE, SS_PANWAVE, SS_FRAMEDELAY, SS_S7EFFECTS, SS_PANNING, SS_SURROUND, SS_HIOFFSET, SS_PATLOOP, SS_NOTECUT, SS_NOTEDELAY, SS_PATDELAY }; /* IT Volume column effects */ enum { VOL_VOLUME = 1, VOL_PANNING, VOL_VOLSLIDE, VOL_PITCHSLIDEDN, VOL_PITCHSLIDEUP, VOL_PORTAMENTO, VOL_VIBRATO }; /* IT resonant filter information */ #define UF_MAXMACRO 0x10 #define UF_MAXFILTER 0x100 #define FILT_CUT 0x80 #define FILT_RESONANT 0x81 typedef struct FILTER { UBYTE filter,inf; } FILTER; /*========== Instruments */ /* Instrument format flags */ #define IF_OWNPAN 1 #define IF_PITCHPAN 2 /* Envelope flags: */ #define EF_ON 1 #define EF_SUSTAIN 2 #define EF_LOOP 4 #define EF_VOLENV 8 /* New Note Action Flags */ #define NNA_CUT 0 #define NNA_CONTINUE 1 #define NNA_OFF 2 #define NNA_FADE 3 #define NNA_MASK 3 #define DCT_OFF 0 #define DCT_NOTE 1 #define DCT_SAMPLE 2 #define DCT_INST 3 #define DCA_CUT 0 #define DCA_OFF 1 #define DCA_FADE 2 #define KEY_KICK 0 #define KEY_OFF 1 #define KEY_FADE 2 #define KEY_KILL (KEY_OFF|KEY_FADE) #define KICK_ABSENT 0 #define KICK_NOTE 1 #define KICK_KEYOFF 2 #define KICK_ENV 4 #define AV_IT 1 /* IT vs. XM vibrato info */ /*========== Playing */ #define POS_NONE (-2) /* no loop position defined */ #define LAST_PATTERN (UWORD)(-1) /* special ``end of song'' pattern */ typedef struct ENVPR { UBYTE flg; /* envelope flag */ UBYTE pts; /* number of envelope points */ UBYTE susbeg; /* envelope sustain index begin */ UBYTE susend; /* envelope sustain index end */ UBYTE beg; /* envelope loop begin */ UBYTE end; /* envelope loop end */ SWORD p; /* current envelope counter */ UWORD a; /* envelope index a */ UWORD b; /* envelope index b */ ENVPT* env; /* envelope points */ } ENVPR; typedef struct MP_CHANNEL { INSTRUMENT* i; SAMPLE* s; UBYTE sample; /* which sample number */ UBYTE note; /* the audible note as heard, direct rep of period */ SWORD outvolume; /* output volume (vol + sampcol + instvol) */ SBYTE chanvol; /* channel's "global" volume */ UWORD fadevol; /* fading volume rate */ SWORD panning; /* panning position */ UBYTE kick; /* if true = sample has to be restarted */ UWORD period; /* period to play the sample at */ UBYTE nna; /* New note action type + master/slave flags */ UBYTE volflg; /* volume envelope settings */ UBYTE panflg; /* panning envelope settings */ UBYTE pitflg; /* pitch envelope settings */ UBYTE keyoff; /* if true = fade out and stuff */ SWORD handle; /* which sample-handle */ UBYTE notedelay; /* (used for note delay) */ SLONG start; /* The starting byte index in the sample */ } MP_CHANNEL; typedef struct MP_CONTROL { struct MP_CHANNEL main; struct MP_VOICE *slave; /* Audio Slave of current effects control channel */ UBYTE slavechn; /* Audio Slave of current effects control channel */ UBYTE muted; /* if set, channel not played */ UWORD ultoffset; /* fine sample offset memory */ UBYTE anote; /* the note that indexes the audible */ UBYTE oldnote; SWORD ownper; SWORD ownvol; UBYTE dca; /* duplicate check action */ UBYTE dct; /* duplicate check type */ UBYTE* row; /* row currently playing on this channel */ SBYTE retrig; /* retrig value (0 means don't retrig) */ ULONG speed; /* what finetune to use */ SWORD volume; /* amiga volume (0 t/m 64) to play the sample at */ SWORD tmpvolume; /* tmp volume */ UWORD tmpperiod; /* tmp period */ UWORD wantedperiod; /* period to slide to (with effect 3 or 5) */ UBYTE arpmem; /* arpeggio command memory */ UBYTE pansspd; /* panslide speed */ UWORD slidespeed; UWORD portspeed; /* noteslide speed (toneportamento) */ UBYTE s3mtremor; /* s3m tremor (effect I) counter */ UBYTE s3mtronof; /* s3m tremor ontime/offtime */ UBYTE s3mvolslide; /* last used volslide */ SBYTE sliding; UBYTE s3mrtgspeed; /* last used retrig speed */ UBYTE s3mrtgslide; /* last used retrig slide */ UBYTE glissando; /* glissando (0 means off) */ UBYTE wavecontrol; SBYTE vibpos; /* current vibrato position */ UBYTE vibspd; /* "" speed */ UBYTE vibdepth; /* "" depth */ SBYTE trmpos; /* current tremolo position */ UBYTE trmspd; /* "" speed */ UBYTE trmdepth; /* "" depth */ UBYTE fslideupspd; UBYTE fslidednspd; UBYTE fportupspd; /* fx E1 (extra fine portamento up) data */ UBYTE fportdnspd; /* fx E2 (extra fine portamento dn) data */ UBYTE ffportupspd; /* fx X1 (extra fine portamento up) data */ UBYTE ffportdnspd; /* fx X2 (extra fine portamento dn) data */ ULONG hioffset; /* last used high order of sample offset */ UWORD soffset; /* last used low order of sample-offset (effect 9) */ UBYTE sseffect; /* last used Sxx effect */ UBYTE ssdata; /* last used Sxx data info */ UBYTE chanvolslide; /* last used channel volume slide */ UBYTE panbwave; /* current panbrello waveform */ UBYTE panbpos; /* current panbrello position */ SBYTE panbspd; /* "" speed */ UBYTE panbdepth; /* "" depth */ UWORD newsamp; /* set to 1 upon a sample / inst change */ UBYTE voleffect; /* Volume Column Effect Memory as used by IT */ UBYTE voldata; /* Volume Column Data Memory */ SWORD pat_reppos; /* patternloop position */ UWORD pat_repcnt; /* times to loop */ } MP_CONTROL; /* Used by NNA only player (audio control. AUDTMP is used for full effects control). */ typedef struct MP_VOICE { struct MP_CHANNEL main; ENVPR venv; ENVPR penv; ENVPR cenv; UWORD avibpos; /* autovibrato pos */ UWORD aswppos; /* autovibrato sweep pos */ ULONG totalvol; /* total volume of channel (before global mixings) */ BOOL mflag; SWORD masterchn; UWORD masterperiod; MP_CONTROL* master; /* index of "master" effects channel */ } MP_VOICE; /*========== Loaders */ typedef struct MLOADER { struct MLOADER* next; CHAR* type; CHAR* version; BOOL (*Init)(void); BOOL (*Test)(void); BOOL (*Load)(BOOL); void (*Cleanup)(void); CHAR* (*LoadTitle)(void); } MLOADER; /* internal loader variables */ extern MREADER* modreader; extern UWORD finetune[16]; extern MODULE of; /* static unimod loading space */ extern UWORD npertab[7*OCTAVE]; /* used by the original MOD loaders */ extern SBYTE remap[UF_MAXCHAN]; /* for removing empty channels */ extern UBYTE* poslookup; /* lookup table for pattern jumps after blank pattern removal */ extern UBYTE poslookupcnt; extern UWORD* origpositions; extern BOOL filters; /* resonant filters in use */ extern UBYTE activemacro; /* active midi macro number for Sxx */ extern UBYTE filtermacros[UF_MAXMACRO]; /* midi macro settings */ extern FILTER filtersettings[UF_MAXFILTER]; /* computed filter settings */ extern int* noteindex; /*========== Internal loader interface */ extern BOOL ReadComment(UWORD); extern BOOL ReadLinedComment(UWORD,UWORD); extern BOOL AllocPositions(int); extern BOOL AllocPatterns(void); extern BOOL AllocTracks(void); extern BOOL AllocInstruments(void); extern BOOL AllocSamples(void); extern CHAR* DupStr(CHAR*,UWORD,BOOL); /* loader utility functions */ extern int* AllocLinear(void); extern void FreeLinear(void); extern int speed_to_finetune(ULONG,int); extern void S3MIT_ProcessCmd(UBYTE,UBYTE,unsigned int); extern void S3MIT_CreateOrders(BOOL); /* flags for S3MIT_ProcessCmd */ #define S3MIT_OLDSTYLE 1 /* behave as old scream tracker */ #define S3MIT_IT 2 /* behave as impulse tracker */ #define S3MIT_SCREAM 4 /* enforce scream tracker specific limits */ /* used to convert c4spd to linear XM periods (IT and IMF loaders). */ extern UWORD getlinearperiod(UWORD,ULONG); extern ULONG getfrequency(UWORD,ULONG); /* loader shared data */ #define STM_NTRACKERS 3 extern CHAR *STM_Signatures[STM_NTRACKERS]; /*========== Player interface */ extern BOOL Player_Init(MODULE*); extern void Player_Exit(MODULE*); extern void Player_HandleTick(void); /*========== Drivers */ /* max. number of handles a driver has to provide. (not strict) */ #define MAXSAMPLEHANDLES 384 /* These variables can be changed at ANY time and results will be immediate */ extern UWORD md_bpm; /* current song / hardware BPM rate */ /* Variables below can be changed via MD_SetNumVoices at any time. However, a call to MD_SetNumVoicess while the driver is active will cause the sound to skip slightly. */ extern UBYTE md_numchn; /* number of song + sound effects voices */ extern UBYTE md_sngchn; /* number of song voices */ extern UBYTE md_sfxchn; /* number of sound effects voices */ extern UBYTE md_hardchn; /* number of hardware mixed voices */ extern UBYTE md_softchn; /* number of software mixed voices */ /* This is for use by the hardware drivers only. It points to the registered tickhandler function. */ extern void (*md_player)(void); extern SWORD MD_SampleLoad(SAMPLOAD*,int); extern void MD_SampleUnload(SWORD); extern ULONG MD_SampleSpace(int); extern ULONG MD_SampleLength(int,SAMPLE*); /* uLaw conversion */ extern void unsignedtoulaw(char *,int); /* Parameter extraction helper */ extern CHAR *MD_GetAtom(CHAR*,CHAR*,BOOL); /* Internal software mixer stuff */ extern void VC_SetupPointers(void); extern BOOL VC1_Init(void); extern BOOL VC2_Init(void); #if defined(unix) || defined(__APPLE__) && defined(__MACH__) /* POSIX helper functions */ extern BOOL MD_Access(CHAR *); extern BOOL MD_DropPrivileges(void); #endif /* Macro to define a missing driver, yet allowing binaries to dynamically link with the library without missing symbol errors */ #define MISSING(a) MDRIVER a = { NULL, NULL, NULL, 0, 0 } /*========== Prototypes for non-MT safe versions of some public functions */ extern void _mm_registerdriver(struct MDRIVER*); extern void _mm_registerloader(struct MLOADER*); extern BOOL MikMod_Active_internal(void); extern void MikMod_DisableOutput_internal(void); extern BOOL MikMod_EnableOutput_internal(void); extern void MikMod_Exit_internal(void); extern BOOL MikMod_SetNumVoices_internal(int,int); extern void Player_Exit_internal(MODULE*); extern void Player_Stop_internal(void); extern BOOL Player_Paused_internal(void); extern void Sample_Free_internal(SAMPLE*); extern void Voice_Play_internal(SBYTE,SAMPLE*,ULONG); extern void Voice_SetFrequency_internal(SBYTE,ULONG); extern void Voice_SetPanning_internal(SBYTE,ULONG); extern void Voice_SetVolume_internal(SBYTE,UWORD); extern void Voice_Stop_internal(SBYTE); extern BOOL Voice_Stopped_internal(SBYTE); #ifdef __cplusplus } #endif #endif /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/munitrk.c0000600000175000017500000001723410543202047017661 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: munitrk.c 2412 2006-08-18 18:37:39Z avolkov $ All routines dealing with the manipulation of UNITRK streams ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mikmod_internals.h" #include /* Unibuffer chunk size */ #define BUFPAGE 128 UWORD unioperands[UNI_LAST]={ 0, /* not used */ 1, /* UNI_NOTE */ 1, /* UNI_INSTRUMENT */ 1, /* UNI_PTEFFECT0 */ 1, /* UNI_PTEFFECT1 */ 1, /* UNI_PTEFFECT2 */ 1, /* UNI_PTEFFECT3 */ 1, /* UNI_PTEFFECT4 */ 1, /* UNI_PTEFFECT5 */ 1, /* UNI_PTEFFECT6 */ 1, /* UNI_PTEFFECT7 */ 1, /* UNI_PTEFFECT8 */ 1, /* UNI_PTEFFECT9 */ 1, /* UNI_PTEFFECTA */ 1, /* UNI_PTEFFECTB */ 1, /* UNI_PTEFFECTC */ 1, /* UNI_PTEFFECTD */ 1, /* UNI_PTEFFECTE */ 1, /* UNI_PTEFFECTF */ 1, /* UNI_S3MEFFECTA */ 1, /* UNI_S3MEFFECTD */ 1, /* UNI_S3MEFFECTE */ 1, /* UNI_S3MEFFECTF */ 1, /* UNI_S3MEFFECTI */ 1, /* UNI_S3MEFFECTQ */ 1, /* UNI_S3MEFFECTR */ 1, /* UNI_S3MEFFECTT */ 1, /* UNI_S3MEFFECTU */ 0, /* UNI_KEYOFF */ 1, /* UNI_KEYFADE */ 2, /* UNI_VOLEFFECTS */ 1, /* UNI_XMEFFECT4 */ 1, /* UNI_XMEFFECT6 */ 1, /* UNI_XMEFFECTA */ 1, /* UNI_XMEFFECTE1 */ 1, /* UNI_XMEFFECTE2 */ 1, /* UNI_XMEFFECTEA */ 1, /* UNI_XMEFFECTEB */ 1, /* UNI_XMEFFECTG */ 1, /* UNI_XMEFFECTH */ 1, /* UNI_XMEFFECTL */ 1, /* UNI_XMEFFECTP */ 1, /* UNI_XMEFFECTX1 */ 1, /* UNI_XMEFFECTX2 */ 1, /* UNI_ITEFFECTG */ 1, /* UNI_ITEFFECTH */ 1, /* UNI_ITEFFECTI */ 1, /* UNI_ITEFFECTM */ 1, /* UNI_ITEFFECTN */ 1, /* UNI_ITEFFECTP */ 1, /* UNI_ITEFFECTT */ 1, /* UNI_ITEFFECTU */ 1, /* UNI_ITEFFECTW */ 1, /* UNI_ITEFFECTY */ 2, /* UNI_ITEFFECTZ */ 1, /* UNI_ITEFFECTS0 */ 2, /* UNI_ULTEFFECT9 */ 2, /* UNI_MEDSPEED */ 0, /* UNI_MEDEFFECTF1 */ 0, /* UNI_MEDEFFECTF2 */ 0, /* UNI_MEDEFFECTF3 */ 2, /* UNI_OKTARP */ }; /* Sparse description of the internal module format ------------------------------------------------ A UNITRK stream is an array of bytes representing a single track of a pattern. It's made up of 'repeat/length' bytes, opcodes and operands (sort of a assembly language): rrrlllll [REP/LEN][OPCODE][OPERAND][OPCODE][OPERAND] [REP/LEN][OPCODE][OPERAND].. ^ ^ ^ |-------ROWS 0 - 0+REP of a track---------| |-------ROWS xx - xx+REP of a track... The rep/len byte contains the number of bytes in the current row, _including_ the length byte itself (So the LENGTH byte of row 0 in the previous example would have a value of 5). This makes it easy to search through a stream for a particular row. A track is concluded by a 0-value length byte. The upper 3 bits of the rep/len byte contain the number of times -1 this row is repeated for this track. (so a value of 7 means this row is repeated 8 times) Opcodes can range from 1 to 255 but currently only opcodes 1 to 62 are being used. Each opcode can have a different number of operands. You can find the number of operands to a particular opcode by using the opcode as an index into the 'unioperands' table. */ /*========== Reading routines */ static UBYTE *rowstart; /* startadress of a row */ static UBYTE *rowend; /* endaddress of a row (exclusive) */ static UBYTE *rowpc; /* current unimod(tm) programcounter */ static UBYTE lastbyte; /* for UniSkipOpcode() */ void UniSetRow(UBYTE* t) { rowstart = t; rowpc = rowstart; rowend = t?rowstart+(*(rowpc++)&0x1f):t; } UBYTE UniGetByte(void) { return lastbyte = (rowpc end of track.. */ l = (c>>5)+1; /* extract repeat value */ if(l>row) break; /* reached wanted row? -> return pointer */ row -= l; /* haven't reached row yet.. update row */ t += c&0x1f; /* point t to the next row */ } return t; } /*========== Writing routines */ static UBYTE *unibuf; /* pointer to the temporary unitrk buffer */ static UWORD unimax; /* buffer size */ static UWORD unipc; /* buffer cursor */ static UWORD unitt; /* current row index */ static UWORD lastp; /* previous row index */ /* Resets index-pointers to create a new track. */ void UniReset(void) { unitt = 0; /* reset index to rep/len byte */ unipc = 1; /* first opcode will be written to index 1 */ lastp = 0; /* no previous row yet */ unibuf[0] = 0; /* clear rep/len byte */ } /* Expands the buffer */ static BOOL UniExpand(int wanted) { if ((unipc+wanted)>=unimax) { UBYTE *newbuf; /* Expand the buffer by BUFPAGE bytes */ newbuf=(UBYTE*)MikMod_realloc(unibuf,(unimax+BUFPAGE)*sizeof(UBYTE)); /* Check if realloc succeeded */ if(newbuf) { unibuf = newbuf; unimax+=BUFPAGE; return 1; } else return 0; } return 1; } /* Appends one byte of data to the current row of a track. */ void UniWriteByte(UBYTE data) { if (UniExpand(1)) /* write byte to current position and update */ unibuf[unipc++]=data; } void UniWriteWord(UWORD data) { if (UniExpand(2)) { unibuf[unipc++]=data>>8; unibuf[unipc++]=data&0xff; } } static BOOL MyCmp(UBYTE* a,UBYTE* b,UWORD l) { UWORD t; for(t=0;t>5)+1; /* repeat of previous row */ l = (unibuf[lastp]&0x1f); /* length of previous row */ len = unipc-unitt; /* length of current row */ /* Now, check if the previous and the current row are identical.. when they are, just increase the repeat field of the previous row */ if(n<8 && len==l && MyCmp(&unibuf[lastp+1],&unibuf[unitt+1],len-1)) { unibuf[lastp]+=0x20; unipc = unitt+1; } else { if (UniExpand(unitt-unipc)) { /* current and previous row aren't equal... update the pointers */ unibuf[unitt] = len; lastp = unitt; unitt = unipc++; } } } /* Terminates the current unitrk stream and returns a pointer to a copy of the stream. */ UBYTE* UniDup(void) { UBYTE *d; if (!UniExpand(unitt-unipc)) return NULL; unibuf[unitt] = 0; if(!(d=(UBYTE *)MikMod_malloc(unipc))) return NULL; memcpy(d,unibuf,unipc); return d; } BOOL UniInit(void) { unimax = BUFPAGE; if(!(unibuf=(UBYTE*)MikMod_malloc(unimax*sizeof(UBYTE)))) return 0; return 1; } void UniCleanup(void) { if(unibuf) MikMod_free(unibuf); unibuf = NULL; } /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/sloader.c0000600000175000017500000002665010543202047017623 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: sloader.c 2412 2006-08-18 18:37:39Z avolkov $ Routines for loading samples. The sample loader utilizes the routines provided by the "registered" sample loader. ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #include "mikmod_internals.h" static int sl_rlength; static SWORD sl_old; static SWORD *sl_buffer=NULL; static SAMPLOAD *musiclist=NULL,*sndfxlist=NULL; /* size of the loader buffer in words */ #define SLBUFSIZE 2048 /* IT-Compressed status structure */ typedef struct ITPACK { UWORD bits; /* current number of bits */ UWORD bufbits; /* bits in buffer */ SWORD last; /* last output */ UBYTE buf; /* bit buffer */ } ITPACK; BOOL SL_Init(SAMPLOAD* s) { if(!sl_buffer) if(!(sl_buffer=MikMod_malloc(SLBUFSIZE*sizeof(SWORD)))) return 0; sl_rlength = s->length; if(s->infmt & SF_16BITS) sl_rlength>>=1; sl_old = 0; return 1; } void SL_Exit(SAMPLOAD *s) { if(sl_rlength>0) _mm_fseek(s->reader,sl_rlength,SEEK_CUR); if(sl_buffer) { MikMod_free(sl_buffer); sl_buffer=NULL; } } /* unpack a 8bit IT packed sample */ static BOOL read_itcompr8(ITPACK* status,MREADER *reader,SWORD *sl_buffer,UWORD count,UWORD* incnt) { SWORD *dest=sl_buffer,*end=sl_buffer+count; UWORD x,y,needbits,havebits,new_count=0; UWORD bits = status->bits; UWORD bufbits = status->bufbits; SBYTE last = status->last; UBYTE buf = status->buf; while (dest>=y; bufbits-=y; needbits-=y; havebits+=y; } if (new_count) { new_count = 0; if (++x >= bits) x++; bits = x; continue; } if (bits<7) { if (x==(1<<(bits-1))) { new_count = 1; continue; } } else if (bits<9) { y = (0xff >> (9-bits)) - 4; if ((x>y)&&(x<=y+8)) { if ((x-=y)>=bits) x++; bits = x; continue; } } else if (bits<10) { if (x>=0x100) { bits=x-0x100+1; continue; } } else { /* error in compressed data... */ _mm_errno=MMERR_ITPACK_INVALID_DATA; return 0; } if (bits<8) /* extend sign */ x = ((SBYTE)(x <<(8-bits))) >> (8-bits); *(dest++)= (last+=x) << 8; /* convert to 16 bit */ } status->bits = bits; status->bufbits = bufbits; status->last = last; status->buf = buf; return !!(dest-sl_buffer); } /* unpack a 16bit IT packed sample */ static BOOL read_itcompr16(ITPACK *status,MREADER *reader,SWORD *sl_buffer,UWORD count,UWORD* incnt) { SWORD *dest=sl_buffer,*end=sl_buffer+count; SLONG x,y,needbits,havebits,new_count=0; UWORD bits = status->bits; UWORD bufbits = status->bufbits; SWORD last = status->last; UBYTE buf = status->buf; while (dest>=y; bufbits-=y; needbits-=y; havebits+=y; } if (new_count) { new_count = 0; if (++x >= bits) x++; bits = x; continue; } if (bits<7) { if (x==(1<<(bits-1))) { new_count=1; continue; } } else if (bits<17) { y=(0xffff>>(17-bits))-8; if ((x>y)&&(x<=y+16)) { if ((x-=y)>=bits) x++; bits = x; continue; } } else if (bits<18) { if (x>=0x10000) { bits=x-0x10000+1; continue; } } else { /* error in compressed data... */ _mm_errno=MMERR_ITPACK_INVALID_DATA; return 0; } if (bits<16) /* extend sign */ x = ((SWORD)(x<<(16-bits)))>>(16-bits); *(dest++)=(last+=x); } status->bits = bits; status->bufbits = bufbits; status->last = last; status->buf = buf; return !!(dest-sl_buffer); } static BOOL SL_LoadInternal(void* buffer,UWORD infmt,UWORD outfmt,int scalefactor,ULONG length,MREADER* reader,BOOL dither) { SBYTE *bptr = (SBYTE*)buffer; SWORD *wptr = (SWORD*)buffer; int stodo,t,u; int result,c_block=0; /* compression bytes until next block */ ITPACK status; UWORD incnt; while(length) { stodo=(lengthRead(reader,sl_buffer,sizeof(SBYTE)*stodo); src = (SBYTE*)sl_buffer; dest = sl_buffer; src += stodo;dest += stodo; for(t=0;t>1; length-=2; } stodo = idx; } } if(outfmt & SF_16BITS) { for(t=0;t>8; } } return 0; } BOOL SL_Load(void* buffer,SAMPLOAD *smp,ULONG length) { return SL_LoadInternal(buffer,smp->infmt,smp->outfmt,smp->scalefactor, length,smp->reader,0); } /* Registers a sample for loading when SL_LoadSamples() is called. */ SAMPLOAD* SL_RegisterSample(SAMPLE* s,int type,MREADER* reader) { SAMPLOAD *news,**samplist,*cruise; if(type==MD_MUSIC) { samplist = &musiclist; cruise = musiclist; } else if (type==MD_SNDFX) { samplist = &sndfxlist; cruise = sndfxlist; } else return NULL; /* Allocate and add structure to the END of the list */ if(!(news=(SAMPLOAD*)MikMod_malloc(sizeof(SAMPLOAD)))) return NULL; if(cruise) { while(cruise->next) cruise=cruise->next; cruise->next = news; } else *samplist = news; news->infmt = s->flags & SF_FORMATMASK; news->outfmt = news->infmt; news->reader = reader; news->sample = s; news->length = s->length; news->loopstart = s->loopstart; news->loopend = s->loopend; return news; } static void FreeSampleList(SAMPLOAD* s) { SAMPLOAD *old; while(s) { old = s; s = s->next; MikMod_free(old); } } /* Returns the total amount of memory required by the samplelist queue. */ static ULONG SampleTotal(SAMPLOAD* samplist,int type) { int total = 0; while(samplist) { samplist->sample->flags= (samplist->sample->flags&~SF_FORMATMASK)|samplist->outfmt; total += MD_SampleLength(type,samplist->sample); samplist=samplist->next; } return total; } static ULONG RealSpeed(SAMPLOAD *s) { return(s->sample->speed/(s->scalefactor?s->scalefactor:1)); } static BOOL DitherSamples(SAMPLOAD* samplist,int type) { SAMPLOAD *c2smp=NULL; ULONG maxsize, speed; SAMPLOAD *s; if(!samplist) return 0; if((maxsize=MD_SampleSpace(type)*1024)) while(SampleTotal(samplist,type)>maxsize) { /* First Pass - check for any 16 bit samples */ s = samplist; while(s) { if(s->outfmt & SF_16BITS) { SL_Sample16to8(s); break; } s=s->next; } /* Second pass (if no 16bits found above) is to take the sample with the highest speed and dither it by half. */ if(!s) { s = samplist; speed = 0; while(s) { if((s->sample->length) && (RealSpeed(s)>speed)) { speed=RealSpeed(s); c2smp=s; } s=s->next; } if (c2smp) SL_HalveSample(c2smp,2); } } /* Samples dithered, now load them ! */ s = samplist; while(s) { /* sample has to be loaded ? -> increase number of samples, allocate memory and load sample. */ if(s->sample->length) { if(s->sample->seekpos) _mm_fseek(s->reader, s->sample->seekpos, SEEK_SET); /* Call the sample load routine of the driver module. It has to return a 'handle' (>=0) that identifies the sample. */ s->sample->handle = MD_SampleLoad(s, type); s->sample->flags = (s->sample->flags & ~SF_FORMATMASK) | s->outfmt; if(s->sample->handle<0) { FreeSampleList(samplist); if(_mm_errorhandler) _mm_errorhandler(); return 1; } } s = s->next; } FreeSampleList(samplist); return 0; } BOOL SL_LoadSamples(void) { BOOL ok; _mm_critical = 0; if((!musiclist)&&(!sndfxlist)) return 0; ok=DitherSamples(musiclist,MD_MUSIC)||DitherSamples(sndfxlist,MD_SNDFX); musiclist=sndfxlist=NULL; return ok; } void SL_Sample16to8(SAMPLOAD* s) { s->outfmt &= ~SF_16BITS; s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt; } void SL_Sample8to16(SAMPLOAD* s) { s->outfmt |= SF_16BITS; s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt; } void SL_SampleSigned(SAMPLOAD* s) { s->outfmt |= SF_SIGNED; s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt; } void SL_SampleUnsigned(SAMPLOAD* s) { s->outfmt &= ~SF_SIGNED; s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt; } void SL_HalveSample(SAMPLOAD* s,int factor) { s->scalefactor=factor>0?factor:2; s->sample->divfactor = s->scalefactor; s->sample->length = s->length / s->scalefactor; s->sample->loopstart = s->loopstart / s->scalefactor; s->sample->loopend = s->loopend / s->scalefactor; } /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mloader.c0000600000175000017500000003227610543202047017616 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mloader.c 2412 2006-08-18 18:37:39Z avolkov $ These routines are used to access the available module loaders ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_MEMORY_H #include #endif #include #include "mikmod_internals.h" #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); #endif MREADER *modreader; MODULE of; static MLOADER *firstloader=NULL; UWORD finetune[16]={ 8363,8413,8463,8529,8581,8651,8723,8757, 7895,7941,7985,8046,8107,8169,8232,8280 }; MIKMODAPI CHAR* MikMod_InfoLoader(void) { int len=0; MLOADER *l; CHAR *list=NULL; MUTEX_LOCK(lists); /* compute size of buffer */ for(l=firstloader;l;l=l->next) len+=1+(l->next?1:0)+strlen(l->version); if(len) if((list=MikMod_malloc(len*sizeof(CHAR)))) { list[0]=0; /* list all registered module loders */ for(l=firstloader;l;l=l->next) sprintf(list,(l->next)?"%s%s\n":"%s%s",list,l->version); } MUTEX_UNLOCK(lists); return list; } void _mm_registerloader(MLOADER* ldr) { MLOADER *cruise=firstloader; if(cruise) { while(cruise->next) cruise = cruise->next; cruise->next=ldr; } else firstloader=ldr; } MIKMODAPI void MikMod_RegisterLoader(struct MLOADER* ldr) { /* if we try to register an invalid loader, or an already registered loader, ignore this attempt */ if ((!ldr)||(ldr->next)) return; MUTEX_LOCK(lists); _mm_registerloader(ldr); MUTEX_UNLOCK(lists); } BOOL ReadComment(UWORD len) { if(len) { int i; if(!(of.comment=(CHAR*)MikMod_malloc(len+1))) return 0; _mm_read_UBYTES(of.comment,len,modreader); /* translate IT linefeeds */ for(i=0;i=0)&&(line[i]==' ');i--) line[i]=0; for(i=0;ilines) { if(!(of.comment=(CHAR*)MikMod_malloc(total+1))) { MikMod_free(storage); MikMod_free(tempcomment); return 0; } /* convert message */ for(line=tempcomment,t=0;tlength) SL_RegisterSample(s,MD_MUSIC,modreader); return 1; } /* Creates a CSTR out of a character buffer of 'len' bytes, but strips any terminating non-printing characters like 0, spaces etc. */ CHAR *DupStr(CHAR* s,UWORD len,BOOL strict) { UWORD t; CHAR *d=NULL; /* Scan for last printing char in buffer [includes high ascii up to 254] */ while(len) { if(s[len-1]>0x20) break; len--; } /* Scan forward for possible NULL character */ if(strict) { for(t=0;thandle>=0) MD_SampleUnload(s->handle); if(s->samplename) MikMod_free(s->samplename); } static void ML_XFreeInstrument(INSTRUMENT *i) { if(i->insname) MikMod_free(i->insname); } static void ML_FreeEx(MODULE *mf) { UWORD t; if(mf->songname) MikMod_free(mf->songname); if(mf->comment) MikMod_free(mf->comment); if(mf->modtype) MikMod_free(mf->modtype); if(mf->positions) MikMod_free(mf->positions); if(mf->patterns) MikMod_free(mf->patterns); if(mf->pattrows) MikMod_free(mf->pattrows); if(mf->tracks) { for(t=0;tnumtrk;t++) if(mf->tracks[t]) MikMod_free(mf->tracks[t]); MikMod_free(mf->tracks); } if(mf->instruments) { for(t=0;tnumins;t++) ML_XFreeInstrument(&mf->instruments[t]); MikMod_free(mf->instruments); } if(mf->samples) { for(t=0;tnumsmp;t++) if(mf->samples[t].length) ML_XFreeSample(&mf->samples[t]); MikMod_free(mf->samples); } memset(mf,0,sizeof(MODULE)); if(mf!=&of) MikMod_free(mf); } static MODULE *ML_AllocUniMod(void) { MODULE *mf; return (mf=MikMod_malloc(sizeof(MODULE))); } void Player_Free_internal(MODULE *mf) { if(mf) { Player_Exit_internal(mf); ML_FreeEx(mf); } } MIKMODAPI void Player_Free(MODULE *mf) { MUTEX_LOCK(vars); Player_Free_internal(mf); MUTEX_UNLOCK(vars); } static CHAR* Player_LoadTitle_internal(MREADER *reader) { MLOADER *l; modreader=reader; _mm_errno = 0; _mm_critical = 0; _mm_iobase_setcur(modreader); /* Try to find a loader that recognizes the module */ for(l=firstloader;l;l=l->next) { _mm_rewind(modreader); if(l->Test()) break; } if(!l) { _mm_errno = MMERR_NOT_A_MODULE; if(_mm_errorhandler) _mm_errorhandler(); return NULL; } return l->LoadTitle(); } MIKMODAPI CHAR* Player_LoadTitleFP(FILE *fp) { CHAR* result=NULL; MREADER* reader; if(fp && (reader=_mm_new_file_reader(fp))) { MUTEX_LOCK(lists); result=Player_LoadTitle_internal(reader); MUTEX_UNLOCK(lists); _mm_delete_file_reader(reader); } return result; } MIKMODAPI CHAR* Player_LoadTitleMem(const char *buffer,int len) { CHAR *result=NULL; MREADER* reader; if ((reader=_mm_new_mem_reader(buffer,len))) { MUTEX_LOCK(lists); result=Player_LoadTitle_internal(reader); MUTEX_UNLOCK(lists); _mm_delete_mem_reader(reader); } return result; } MIKMODAPI CHAR* Player_LoadTitleGeneric(MREADER *reader) { CHAR *result=NULL; if (reader) { MUTEX_LOCK(lists); result=Player_LoadTitle_internal(reader); MUTEX_UNLOCK(lists); } return result; } MIKMODAPI CHAR* Player_LoadTitle(CHAR* filename) { CHAR* result=NULL; FILE* fp; MREADER* reader; if((fp=_mm_fopen(filename,"rb"))) { if((reader=_mm_new_file_reader(fp))) { MUTEX_LOCK(lists); result=Player_LoadTitle_internal(reader); MUTEX_UNLOCK(lists); _mm_delete_file_reader(reader); } _mm_fclose(fp); } return result; } /* Loads a module given an reader */ MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,BOOL curious) { int t; MLOADER *l; BOOL ok; MODULE *mf; modreader = reader; _mm_errno = 0; _mm_critical = 0; _mm_iobase_setcur(modreader); /* Try to find a loader that recognizes the module */ for(l=firstloader;l;l=l->next) { _mm_rewind(modreader); if(l->Test()) break; } if(!l) { _mm_errno = MMERR_NOT_A_MODULE; if(_mm_errorhandler) _mm_errorhandler(); _mm_rewind(modreader);_mm_iobase_revert(modreader); return NULL; } /* init unitrk routines */ if(!UniInit()) { if(_mm_errorhandler) _mm_errorhandler(); _mm_rewind(modreader);_mm_iobase_revert(modreader); return NULL; } /* init the module structure with vanilla settings */ memset(&of,0,sizeof(MODULE)); of.bpmlimit = 33; of.initvolume = 128; for (t = 0; t < UF_MAXCHAN; t++) of.chanvol[t] = 64; for (t = 0; t < UF_MAXCHAN; t++) of.panning[t] = ((t + 1) & 2) ? PAN_RIGHT : PAN_LEFT; /* init module loader and load the header / patterns */ if (!l->Init || l->Init()) { _mm_rewind(modreader); ok = l->Load(curious); if (ok) { /* propagate inflags=flags for in-module samples */ for (t = 0; t < of.numsmp; t++) if (of.samples[t].inflags == 0) of.samples[t].inflags = of.samples[t].flags; } } else ok = 0; /* free loader and unitrk allocations */ if (l->Cleanup) l->Cleanup(); UniCleanup(); if(!ok) { ML_FreeEx(&of); if(_mm_errorhandler) _mm_errorhandler(); _mm_rewind(modreader);_mm_iobase_revert(modreader); return NULL; } if(!ML_LoadSamples()) { ML_FreeEx(&of); if(_mm_errorhandler) _mm_errorhandler(); _mm_rewind(modreader);_mm_iobase_revert(modreader); return NULL; } if(!(mf=ML_AllocUniMod())) { ML_FreeEx(&of); _mm_rewind(modreader);_mm_iobase_revert(modreader); if(_mm_errorhandler) _mm_errorhandler(); return NULL; } /* If the module doesn't have any specific panning, create a MOD-like panning, with the channels half-separated. */ if (!(of.flags & UF_PANNING)) for (t = 0; t < of.numchn; t++) of.panning[t] = ((t + 1) & 2) ? PAN_HALFRIGHT : PAN_HALFLEFT; /* Copy the static MODULE contents into the dynamic MODULE struct. */ memcpy(mf,&of,sizeof(MODULE)); if(maxchan>0) { if(!(mf->flags&UF_NNA)&&(mf->numchnnumchn; else if((mf->numvoices)&&(mf->numvoicesnumvoices; if(maxchannumchn) mf->flags |= UF_NNA; if(MikMod_SetNumVoices_internal(maxchan,-1)) { _mm_iobase_revert(modreader); Player_Free(mf); return NULL; } } if(SL_LoadSamples()) { _mm_iobase_revert(modreader); Player_Free_internal(mf); return NULL; } if(Player_Init(mf)) { _mm_iobase_revert(modreader); Player_Free_internal(mf); mf=NULL; } _mm_iobase_revert(modreader); return mf; } MIKMODAPI MODULE* Player_LoadGeneric(MREADER *reader,int maxchan,BOOL curious) { MODULE* result; MUTEX_LOCK(vars); MUTEX_LOCK(lists); result=Player_LoadGeneric_internal(reader,maxchan,curious); MUTEX_UNLOCK(lists); MUTEX_UNLOCK(vars); return result; } MIKMODAPI MODULE* Player_LoadMem(const char *buffer,int len,int maxchan,BOOL curious) { MODULE* result=NULL; MREADER* reader; if ((reader=_mm_new_mem_reader(buffer, len))) { result=Player_LoadGeneric(reader,maxchan,curious); _mm_delete_mem_reader(reader); } return result; } /* Loads a module given a file pointer. File is loaded from the current file seek position. */ MIKMODAPI MODULE* Player_LoadFP(FILE* fp,int maxchan,BOOL curious) { MODULE* result=NULL; struct MREADER* reader=_mm_new_file_reader (fp); if (reader) { result=Player_LoadGeneric(reader,maxchan,curious); _mm_delete_file_reader(reader); } return result; } /* Open a module via its filename. The loader will initialize the specified song-player 'player'. */ MIKMODAPI MODULE* Player_Load(CHAR* filename,int maxchan,BOOL curious) { FILE *fp; MODULE *mf=NULL; if((fp=_mm_fopen(filename,"rb"))) { mf=Player_LoadFP(fp,maxchan,curious); _mm_fclose(fp); } return mf; } /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mmalloc.c0000600000175000017500000000345710543202047017616 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mmalloc.c 2412 2006-08-18 18:37:39Z avolkov $ Dynamic memory routines ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mikmod_internals.h" void* MikMod_realloc(void *data, size_t size) { if (data) return realloc(data, size); else return MikMod_malloc(size); } /* Same as malloc, but sets error variable _mm_error when fails */ void* MikMod_malloc(size_t size) { void *d; if(!(d=calloc(1,size))) { _mm_errno = MMERR_OUT_OF_MEMORY; if(_mm_errorhandler) _mm_errorhandler(); } return d; } /* Same as calloc, but sets error variable _mm_error when fails */ void* MikMod_calloc(size_t nitems,size_t size) { void *d; if(!(d=calloc(nitems,size))) { _mm_errno = MMERR_OUT_OF_MEMORY; if(_mm_errorhandler) _mm_errorhandler(); } return d; } void MikMod_free(void *p) { if (p) free(p); } /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mikmod.h0000600000175000017500000005766110543202047017465 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mikmod.h 2412 2006-08-18 18:37:39Z avolkov $ MikMod sound library include file ==============================================================================*/ #ifndef _MIKMOD_H_ #define _MIKMOD_H_ #include #include #ifdef __cplusplus extern "C" { #endif /* * ========== Compiler magic for shared libraries */ #if defined(LIBMIKMOD_DLL) #if defined(DLL_EXPORTS) #define MIKMODAPI __declspec(dllexport) #else #define MIKMODAPI __declspec(dllimport) #endif #else #define MIKMODAPI #endif /* * ========== Library version */ #define LIBMIKMOD_VERSION_MAJOR 3L #define LIBMIKMOD_VERSION_MINOR 1L #define LIBMIKMOD_REVISION 12L #define LIBMIKMOD_VERSION \ ((LIBMIKMOD_VERSION_MAJOR<<16)| \ (LIBMIKMOD_VERSION_MINOR<< 8)| \ (LIBMIKMOD_REVISION)) MIKMODAPI extern long MikMod_GetVersion(void); /* * ========== Platform independent-type definitions */ #if defined(WIN32)||defined(WIN64) #define WIN32_LEAN_AND_MEAN #include #include #include #endif #if defined(__OS2__)||defined(__EMX__) #define INCL_DOSSEMAPHORES #include #else typedef char CHAR; #endif #if defined(__arch64__) || defined(__alpha) || defined(__x86_64) \ || defined(__powerpc64__) || defined(_M_IA64) || defined(_M_AMD64) /* 64 bit architectures */ typedef signed char SBYTE; /* 1 byte, signed */ typedef unsigned char UBYTE; /* 1 byte, unsigned */ typedef signed short SWORD; /* 2 bytes, signed */ typedef unsigned short UWORD; /* 2 bytes, unsigned */ typedef signed int SLONG; /* 4 bytes, signed */ typedef unsigned int ULONG; /* 4 bytes, unsigned */ typedef int BOOL; /* 0=false, <>0 true */ #else /* 32 bit architectures */ typedef signed char SBYTE; /* 1 byte, signed */ typedef unsigned char UBYTE; /* 1 byte, unsigned */ typedef signed short SWORD; /* 2 bytes, signed */ typedef unsigned short UWORD; /* 2 bytes, unsigned */ typedef signed long SLONG; /* 4 bytes, signed */ #if !defined(__OS2__)&&!defined(__EMX__)&&!defined(WIN32) typedef unsigned long ULONG; /* 4 bytes, unsigned */ typedef int BOOL; /* 0=false, <>0 true */ #endif #endif /* * ========== Error codes */ enum { MMERR_OPENING_FILE = 1, MMERR_OUT_OF_MEMORY, MMERR_DYNAMIC_LINKING, MMERR_SAMPLE_TOO_BIG, MMERR_OUT_OF_HANDLES, MMERR_UNKNOWN_WAVE_TYPE, MMERR_LOADING_PATTERN, MMERR_LOADING_TRACK, MMERR_LOADING_HEADER, MMERR_LOADING_SAMPLEINFO, MMERR_NOT_A_MODULE, MMERR_NOT_A_STREAM, MMERR_MED_SYNTHSAMPLES, MMERR_ITPACK_INVALID_DATA, MMERR_DETECTING_DEVICE, MMERR_INVALID_DEVICE, MMERR_INITIALIZING_MIXER, MMERR_OPENING_AUDIO, MMERR_8BIT_ONLY, MMERR_16BIT_ONLY, MMERR_STEREO_ONLY, MMERR_ULAW, MMERR_NON_BLOCK, MMERR_AF_AUDIO_PORT, MMERR_AIX_CONFIG_INIT, MMERR_AIX_CONFIG_CONTROL, MMERR_AIX_CONFIG_START, MMERR_GUS_SETTINGS, MMERR_GUS_RESET, MMERR_GUS_TIMER, MMERR_HP_SETSAMPLESIZE, MMERR_HP_SETSPEED, MMERR_HP_CHANNELS, MMERR_HP_AUDIO_OUTPUT, MMERR_HP_AUDIO_DESC, MMERR_HP_BUFFERSIZE, MMERR_OSS_SETFRAGMENT, MMERR_OSS_SETSAMPLESIZE, MMERR_OSS_SETSTEREO, MMERR_OSS_SETSPEED, MMERR_SGI_SPEED, MMERR_SGI_16BIT, MMERR_SGI_8BIT, MMERR_SGI_STEREO, MMERR_SGI_MONO, MMERR_SUN_INIT, MMERR_OS2_MIXSETUP, MMERR_OS2_SEMAPHORE, MMERR_OS2_TIMER, MMERR_OS2_THREAD, MMERR_DS_PRIORITY, MMERR_DS_BUFFER, MMERR_DS_FORMAT, MMERR_DS_NOTIFY, MMERR_DS_EVENT, MMERR_DS_THREAD, MMERR_DS_UPDATE, MMERR_WINMM_HANDLE, MMERR_WINMM_ALLOCATED, MMERR_WINMM_DEVICEID, MMERR_WINMM_FORMAT, MMERR_WINMM_UNKNOWN, MMERR_MAC_SPEED, MMERR_MAC_START, MMERR_MAX }; /* * ========== Error handling */ typedef void (MikMod_handler)(void); typedef MikMod_handler *MikMod_handler_t; MIKMODAPI extern int MikMod_errno; MIKMODAPI extern BOOL MikMod_critical; MIKMODAPI extern char *MikMod_strerror(int); MIKMODAPI extern MikMod_handler_t MikMod_RegisterErrorHandler(MikMod_handler_t); /* * ========== Library initialization and core functions */ struct MDRIVER; MIKMODAPI extern void MikMod_RegisterAllDrivers(void); MIKMODAPI extern CHAR* MikMod_InfoDriver(void); MIKMODAPI extern void MikMod_RegisterDriver(struct MDRIVER*); MIKMODAPI extern int MikMod_DriverFromAlias(CHAR*); MIKMODAPI extern BOOL MikMod_Init(CHAR*); MIKMODAPI extern void MikMod_Exit(void); MIKMODAPI extern BOOL MikMod_Reset(CHAR*); MIKMODAPI extern BOOL MikMod_SetNumVoices(int,int); MIKMODAPI extern BOOL MikMod_Active(void); MIKMODAPI extern BOOL MikMod_EnableOutput(void); MIKMODAPI extern void MikMod_DisableOutput(void); MIKMODAPI extern void MikMod_Update(void); MIKMODAPI extern BOOL MikMod_InitThreads(void); MIKMODAPI extern void MikMod_Lock(void); MIKMODAPI extern void MikMod_Unlock(void); MIKMODAPI extern void* MikMod_malloc(size_t); MIKMODAPI extern void* MikMod_realloc(void *, size_t); MIKMODAPI extern void* MikMod_calloc(size_t,size_t); MIKMODAPI extern void MikMod_free(void *); /* * ========== Reader, Writer */ typedef struct MREADER { BOOL (*Seek)(struct MREADER*,long,int); long (*Tell)(struct MREADER*); BOOL (*Read)(struct MREADER*,void*,size_t); int (*Get)(struct MREADER*); BOOL (*Eof)(struct MREADER*); long iobase; long prev_iobase; } MREADER; typedef struct MWRITER { BOOL (*Seek)(struct MWRITER*,long,int); long (*Tell)(struct MWRITER*); BOOL (*Write)(struct MWRITER*,void*,size_t); BOOL (*Put)(struct MWRITER*,int); } MWRITER; /* * ========== Samples */ /* Sample playback should not be interrupted */ #define SFX_CRITICAL 1 /* Sample format [loading and in-memory] flags: */ #define SF_16BITS 0x0001 #define SF_STEREO 0x0002 #define SF_SIGNED 0x0004 #define SF_BIG_ENDIAN 0x0008 #define SF_DELTA 0x0010 #define SF_ITPACKED 0x0020 #define SF_FORMATMASK 0x003F /* General Playback flags */ #define SF_LOOP 0x0100 #define SF_BIDI 0x0200 #define SF_REVERSE 0x0400 #define SF_SUSTAIN 0x0800 #define SF_PLAYBACKMASK 0x0C00 /* Module-only Playback Flags */ #define SF_OWNPAN 0x1000 #define SF_UST_LOOP 0x2000 #define SF_EXTRAPLAYBACKMASK 0x3000 /* Panning constants */ #define PAN_LEFT 0 #define PAN_HALFLEFT 64 #define PAN_CENTER 128 #define PAN_HALFRIGHT 192 #define PAN_RIGHT 255 #define PAN_SURROUND 512 /* panning value for Dolby Surround */ typedef struct SAMPLE { SWORD panning; /* panning (0-255 or PAN_SURROUND) */ ULONG speed; /* Base playing speed/frequency of note */ UBYTE volume; /* volume 0-64 */ UWORD inflags; /* sample format on disk */ UWORD flags; /* sample format in memory */ ULONG length; /* length of sample (in samples!) */ ULONG loopstart; /* repeat position (relative to start, in samples) */ ULONG loopend; /* repeat end */ ULONG susbegin; /* sustain loop begin (in samples) \ Not Supported */ ULONG susend; /* sustain loop end / Yet! */ /* Variables used by the module player only! (ignored for sound effects) */ UBYTE globvol; /* global volume */ UBYTE vibflags; /* autovibrato flag stuffs */ UBYTE vibtype; /* Vibratos moved from INSTRUMENT to SAMPLE */ UBYTE vibsweep; UBYTE vibdepth; UBYTE vibrate; CHAR* samplename; /* name of the sample */ /* Values used internally only */ UWORD avibpos; /* autovibrato pos [player use] */ UBYTE divfactor; /* for sample scaling, maintains proper period slides */ ULONG seekpos; /* seek position in file */ SWORD handle; /* sample handle used by individual drivers */ } SAMPLE; /* Sample functions */ MIKMODAPI extern SAMPLE *Sample_Load(CHAR*); MIKMODAPI extern SAMPLE *Sample_LoadFP(FILE*); MIKMODAPI extern SAMPLE *Sample_LoadMem(const char *buf, int len); MIKMODAPI extern SAMPLE *Sample_LoadGeneric(MREADER*); MIKMODAPI extern void Sample_Free(SAMPLE*); MIKMODAPI extern SBYTE Sample_Play(SAMPLE*,ULONG,UBYTE); MIKMODAPI extern void Voice_SetVolume(SBYTE,UWORD); MIKMODAPI extern UWORD Voice_GetVolume(SBYTE); MIKMODAPI extern void Voice_SetFrequency(SBYTE,ULONG); MIKMODAPI extern ULONG Voice_GetFrequency(SBYTE); MIKMODAPI extern void Voice_SetPanning(SBYTE,ULONG); MIKMODAPI extern ULONG Voice_GetPanning(SBYTE); MIKMODAPI extern void Voice_Play(SBYTE,SAMPLE*,ULONG); MIKMODAPI extern void Voice_Stop(SBYTE); MIKMODAPI extern BOOL Voice_Stopped(SBYTE); MIKMODAPI extern SLONG Voice_GetPosition(SBYTE); MIKMODAPI extern ULONG Voice_RealVolume(SBYTE); /* * ========== Internal module representation (UniMod) */ /* Instrument definition - for information only, the only field which may be of use in user programs is the name field */ /* Instrument note count */ #define INSTNOTES 120 /* Envelope point */ typedef struct ENVPT { SWORD pos; SWORD val; } ENVPT; /* Envelope point count */ #define ENVPOINTS 32 /* Instrument structure */ typedef struct INSTRUMENT { CHAR* insname; UBYTE flags; UWORD samplenumber[INSTNOTES]; UBYTE samplenote[INSTNOTES]; UBYTE nnatype; UBYTE dca; /* duplicate check action */ UBYTE dct; /* duplicate check type */ UBYTE globvol; UWORD volfade; SWORD panning; /* instrument-based panning var */ UBYTE pitpansep; /* pitch pan separation (0 to 255) */ UBYTE pitpancenter; /* pitch pan center (0 to 119) */ UBYTE rvolvar; /* random volume varations (0 - 100%) */ UBYTE rpanvar; /* random panning varations (0 - 100%) */ /* volume envelope */ UBYTE volflg; /* bit 0: on 1: sustain 2: loop */ UBYTE volpts; UBYTE volsusbeg; UBYTE volsusend; UBYTE volbeg; UBYTE volend; ENVPT volenv[ENVPOINTS]; /* panning envelope */ UBYTE panflg; /* bit 0: on 1: sustain 2: loop */ UBYTE panpts; UBYTE pansusbeg; UBYTE pansusend; UBYTE panbeg; UBYTE panend; ENVPT panenv[ENVPOINTS]; /* pitch envelope */ UBYTE pitflg; /* bit 0: on 1: sustain 2: loop */ UBYTE pitpts; UBYTE pitsusbeg; UBYTE pitsusend; UBYTE pitbeg; UBYTE pitend; ENVPT pitenv[ENVPOINTS]; } INSTRUMENT; struct MP_CONTROL; struct MP_VOICE; /* Module definition */ /* maximum master channels supported */ #define UF_MAXCHAN 64 /* Module flags */ #define UF_XMPERIODS 0x0001 /* XM periods / finetuning */ #define UF_LINEAR 0x0002 /* LINEAR periods (UF_XMPERIODS must be set) */ #define UF_INST 0x0004 /* Instruments are used */ #define UF_NNA 0x0008 /* IT: NNA used, set numvoices rather than numchn */ #define UF_S3MSLIDES 0x0010 /* uses old S3M volume slides */ #define UF_BGSLIDES 0x0020 /* continue volume slides in the background */ #define UF_HIGHBPM 0x0040 /* MED: can use >255 bpm */ #define UF_NOWRAP 0x0080 /* XM-type (i.e. illogical) pattern break semantics */ #define UF_ARPMEM 0x0100 /* IT: need arpeggio memory */ #define UF_FT2QUIRKS 0x0200 /* emulate some FT2 replay quirks */ #define UF_PANNING 0x0400 /* module uses panning effects or have non-tracker default initial panning */ typedef struct MODULE { /* general module information */ CHAR* songname; /* name of the song */ CHAR* modtype; /* string type of module loaded */ CHAR* comment; /* module comments */ UWORD flags; /* See module flags above */ UBYTE numchn; /* number of module channels */ UBYTE numvoices; /* max # voices used for full NNA playback */ UWORD numpos; /* number of positions in this song */ UWORD numpat; /* number of patterns in this song */ UWORD numins; /* number of instruments */ UWORD numsmp; /* number of samples */ struct INSTRUMENT* instruments; /* all instruments */ struct SAMPLE* samples; /* all samples */ UBYTE realchn; /* real number of channels used */ UBYTE totalchn; /* total number of channels used (incl NNAs) */ /* playback settings */ UWORD reppos; /* restart position */ UBYTE initspeed; /* initial song speed */ UWORD inittempo; /* initial song tempo */ UBYTE initvolume; /* initial global volume (0 - 128) */ UWORD panning[UF_MAXCHAN]; /* panning positions */ UBYTE chanvol[UF_MAXCHAN]; /* channel positions */ UWORD bpm; /* current beats-per-minute speed */ UWORD sngspd; /* current song speed */ SWORD volume; /* song volume (0-128) (or user volume) */ BOOL extspd; /* extended speed flag (default enabled) */ BOOL panflag; /* panning flag (default enabled) */ BOOL wrap; /* wrap module ? (default disabled) */ BOOL loop; /* allow module to loop ? (default enabled) */ BOOL fadeout; /* volume fade out during last pattern */ UWORD patpos; /* current row number */ SWORD sngpos; /* current song position */ ULONG sngtime; /* current song time in 2^-10 seconds */ SWORD relspd; /* relative speed factor */ /* internal module representation */ UWORD numtrk; /* number of tracks */ UBYTE** tracks; /* array of numtrk pointers to tracks */ UWORD* patterns; /* array of Patterns */ UWORD* pattrows; /* array of number of rows for each pattern */ UWORD* positions; /* all positions */ BOOL forbid; /* if true, no player update! */ UWORD numrow; /* number of rows on current pattern */ UWORD vbtick; /* tick counter (counts from 0 to sngspd) */ UWORD sngremainder;/* used for song time computation */ struct MP_CONTROL* control; /* Effects Channel info (size pf->numchn) */ struct MP_VOICE* voice; /* Audio Voice information (size md_numchn) */ UBYTE globalslide; /* global volume slide rate */ UBYTE pat_repcrazy;/* module has just looped to position -1 */ UWORD patbrk; /* position where to start a new pattern */ UBYTE patdly; /* patterndelay counter (command memory) */ UBYTE patdly2; /* patterndelay counter (real one) */ SWORD posjmp; /* flag to indicate a jump is needed... */ UWORD bpmlimit; /* threshold to detect bpm or speed values */ } MODULE; /* * ========== Module loaders */ struct MLOADER; MIKMODAPI extern CHAR* MikMod_InfoLoader(void); MIKMODAPI extern void MikMod_RegisterAllLoaders(void); MIKMODAPI extern void MikMod_RegisterLoader(struct MLOADER*); MIKMODAPI extern struct MLOADER load_669; /* 669 and Extended-669 (by Tran/Renaissance) */ MIKMODAPI extern struct MLOADER load_amf; /* DMP Advanced Module Format (by Otto Chrons) */ MIKMODAPI extern struct MLOADER load_dsm; /* DSIK internal module format */ MIKMODAPI extern struct MLOADER load_far; /* Farandole Composer (by Daniel Potter) */ MIKMODAPI extern struct MLOADER load_gdm; /* General DigiMusic (by Edward Schlunder) */ MIKMODAPI extern struct MLOADER load_it; /* Impulse Tracker (by Jeffrey Lim) */ MIKMODAPI extern struct MLOADER load_imf; /* Imago Orpheus (by Lutz Roeder) */ MIKMODAPI extern struct MLOADER load_med; /* Amiga MED modules (by Teijo Kinnunen) */ MIKMODAPI extern struct MLOADER load_m15; /* Soundtracker 15-instrument */ MIKMODAPI extern struct MLOADER load_mod; /* Standard 31-instrument Module loader */ MIKMODAPI extern struct MLOADER load_mtm; /* Multi-Tracker Module (by Renaissance) */ MIKMODAPI extern struct MLOADER load_okt; /* Amiga Oktalyzer */ MIKMODAPI extern struct MLOADER load_stm; /* ScreamTracker 2 (by Future Crew) */ MIKMODAPI extern struct MLOADER load_stx; /* STMIK 0.2 (by Future Crew) */ MIKMODAPI extern struct MLOADER load_s3m; /* ScreamTracker 3 (by Future Crew) */ MIKMODAPI extern struct MLOADER load_ult; /* UltraTracker (by MAS) */ MIKMODAPI extern struct MLOADER load_uni; /* MikMod and APlayer internal module format */ MIKMODAPI extern struct MLOADER load_xm; /* FastTracker 2 (by Triton) */ /* * ========== Module player */ MIKMODAPI extern MODULE* Player_Load(CHAR*,int,BOOL); MIKMODAPI extern MODULE* Player_LoadFP(FILE*,int,BOOL); MIKMODAPI extern MODULE* Player_LoadMem(const char *buffer,int len,int maxchan,BOOL curious); MIKMODAPI extern MODULE* Player_LoadGeneric(MREADER*,int,BOOL); MIKMODAPI extern CHAR* Player_LoadTitle(CHAR*); MIKMODAPI extern CHAR* Player_LoadTitleFP(FILE*); MIKMODAPI extern CHAR* Player_LoadTitleMem(const char *buffer,int len); MIKMODAPI extern CHAR* Player_LoadTitleGeneric(MREADER*); MIKMODAPI extern void Player_Free(MODULE*); MIKMODAPI extern void Player_Start(MODULE*); MIKMODAPI extern BOOL Player_Active(void); MIKMODAPI extern void Player_Stop(void); MIKMODAPI extern void Player_TogglePause(void); MIKMODAPI extern BOOL Player_Paused(void); MIKMODAPI extern void Player_NextPosition(void); MIKMODAPI extern void Player_PrevPosition(void); MIKMODAPI extern void Player_SetPosition(UWORD); MIKMODAPI extern BOOL Player_Muted(UBYTE); MIKMODAPI extern void Player_SetVolume(SWORD); MIKMODAPI extern MODULE* Player_GetModule(void); MIKMODAPI extern void Player_SetSpeed(UWORD); MIKMODAPI extern void Player_SetTempo(UWORD); MIKMODAPI extern void Player_Unmute(SLONG,...); MIKMODAPI extern void Player_Mute(SLONG,...); MIKMODAPI extern void Player_ToggleMute(SLONG,...); MIKMODAPI extern int Player_GetChannelVoice(UBYTE); MIKMODAPI extern UWORD Player_GetChannelPeriod(UBYTE); typedef void (MikMod_player)(void); typedef MikMod_player *MikMod_player_t; MIKMODAPI extern MikMod_player_t MikMod_RegisterPlayer(MikMod_player_t); #define MUTE_EXCLUSIVE 32000 #define MUTE_INCLUSIVE 32001 /* * ========== Drivers */ enum { MD_MUSIC = 0, MD_SNDFX }; enum { MD_HARDWARE = 0, MD_SOFTWARE }; /* Mixing flags */ /* These ones take effect only after MikMod_Init or MikMod_Reset */ #define DMODE_16BITS 0x0001 /* enable 16 bit output */ #define DMODE_STEREO 0x0002 /* enable stereo output */ #define DMODE_SOFT_SNDFX 0x0004 /* Process sound effects via software mixer */ #define DMODE_SOFT_MUSIC 0x0008 /* Process music via software mixer */ #define DMODE_HQMIXER 0x0010 /* Use high-quality (slower) software mixer */ /* These take effect immediately. */ #define DMODE_SURROUND 0x0100 /* enable surround sound */ #define DMODE_INTERP 0x0200 /* enable interpolation */ #define DMODE_REVERSE 0x0400 /* reverse stereo */ struct SAMPLOAD; typedef struct MDRIVER { struct MDRIVER* next; CHAR* Name; CHAR* Version; UBYTE HardVoiceLimit; /* Limit of hardware mixer voices */ UBYTE SoftVoiceLimit; /* Limit of software mixer voices */ CHAR* Alias; void (*CommandLine) (CHAR*); BOOL (*IsPresent) (void); SWORD (*SampleLoad) (struct SAMPLOAD*,int); void (*SampleUnload) (SWORD); ULONG (*FreeSampleSpace) (int); ULONG (*RealSampleLength) (int,struct SAMPLE*); BOOL (*Init) (void); void (*Exit) (void); BOOL (*Reset) (void); BOOL (*SetNumVoices) (void); BOOL (*PlayStart) (void); void (*PlayStop) (void); void (*Update) (void); void (*Pause) (void); void (*VoiceSetVolume) (UBYTE,UWORD); UWORD (*VoiceGetVolume) (UBYTE); void (*VoiceSetFrequency)(UBYTE,ULONG); ULONG (*VoiceGetFrequency)(UBYTE); void (*VoiceSetPanning) (UBYTE,ULONG); ULONG (*VoiceGetPanning) (UBYTE); void (*VoicePlay) (UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD); void (*VoiceStop) (UBYTE); BOOL (*VoiceStopped) (UBYTE); SLONG (*VoiceGetPosition) (UBYTE); ULONG (*VoiceRealVolume) (UBYTE); } MDRIVER; /* These variables can be changed at ANY time and results will be immediate */ MIKMODAPI extern UBYTE md_volume; /* global sound volume (0-128) */ MIKMODAPI extern UBYTE md_musicvolume; /* volume of song */ MIKMODAPI extern UBYTE md_sndfxvolume; /* volume of sound effects */ MIKMODAPI extern UBYTE md_reverb; /* 0 = none; 15 = chaos */ MIKMODAPI extern UBYTE md_pansep; /* 0 = mono; 128 == 100% (full left/right) */ /* The variables below can be changed at any time, but changes will not be implemented until MikMod_Reset is called. A call to MikMod_Reset may result in a skip or pop in audio (depending on the soundcard driver and the settings changed). */ MIKMODAPI extern UWORD md_device; /* device */ MIKMODAPI extern UWORD md_mixfreq; /* mixing frequency */ MIKMODAPI extern UWORD md_mode; /* mode. See DMODE_? flags above */ /* The following variable should not be changed! */ MIKMODAPI extern MDRIVER* md_driver; /* Current driver in use. */ /* Known drivers list */ MIKMODAPI extern struct MDRIVER drv_nos; /* no sound */ MIKMODAPI extern struct MDRIVER drv_pipe; /* piped output */ MIKMODAPI extern struct MDRIVER drv_raw; /* raw file disk writer [music.raw] */ MIKMODAPI extern struct MDRIVER drv_stdout; /* output to stdout */ MIKMODAPI extern struct MDRIVER drv_wav; /* RIFF WAVE file disk writer [music.wav] */ MIKMODAPI extern struct MDRIVER drv_ultra; /* Linux Ultrasound driver */ MIKMODAPI extern struct MDRIVER drv_sam9407; /* Linux sam9407 driver */ MIKMODAPI extern struct MDRIVER drv_AF; /* Dec Alpha AudioFile */ MIKMODAPI extern struct MDRIVER drv_aix; /* AIX audio device */ MIKMODAPI extern struct MDRIVER drv_alsa; /* Advanced Linux Sound Architecture (ALSA) */ MIKMODAPI extern struct MDRIVER drv_esd; /* Enlightened sound daemon (EsounD) */ MIKMODAPI extern struct MDRIVER drv_hp; /* HP-UX audio device */ MIKMODAPI extern struct MDRIVER drv_oss; /* OpenSound System (Linux,FreeBSD...) */ MIKMODAPI extern struct MDRIVER drv_sgi; /* SGI audio library */ MIKMODAPI extern struct MDRIVER drv_sun; /* Sun/NetBSD/OpenBSD audio device */ MIKMODAPI extern struct MDRIVER drv_dart; /* OS/2 Direct Audio RealTime */ MIKMODAPI extern struct MDRIVER drv_os2; /* OS/2 MMPM/2 */ MIKMODAPI extern struct MDRIVER drv_ds; /* Win32 DirectSound driver */ MIKMODAPI extern struct MDRIVER drv_win; /* Win32 multimedia API driver */ MIKMODAPI extern struct MDRIVER drv_mac; /* Macintosh Sound Manager driver */ /*========== Virtual channel mixer interface (for user-supplied drivers only) */ MIKMODAPI extern BOOL VC_Init(void); MIKMODAPI extern void VC_Exit(void); MIKMODAPI extern BOOL VC_SetNumVoices(void); MIKMODAPI extern ULONG VC_SampleSpace(int); MIKMODAPI extern ULONG VC_SampleLength(int,SAMPLE*); MIKMODAPI extern BOOL VC_PlayStart(void); MIKMODAPI extern void VC_PlayStop(void); MIKMODAPI extern SWORD VC_SampleLoad(struct SAMPLOAD*,int); MIKMODAPI extern void VC_SampleUnload(SWORD); MIKMODAPI extern ULONG VC_WriteBytes(SBYTE*,ULONG); MIKMODAPI extern ULONG VC_SilenceBytes(SBYTE*,ULONG); MIKMODAPI extern void VC_VoiceSetVolume(UBYTE,UWORD); MIKMODAPI extern UWORD VC_VoiceGetVolume(UBYTE); MIKMODAPI extern void VC_VoiceSetFrequency(UBYTE,ULONG); MIKMODAPI extern ULONG VC_VoiceGetFrequency(UBYTE); MIKMODAPI extern void VC_VoiceSetPanning(UBYTE,ULONG); MIKMODAPI extern ULONG VC_VoiceGetPanning(UBYTE); MIKMODAPI extern void VC_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD); MIKMODAPI extern void VC_VoiceStop(UBYTE); MIKMODAPI extern BOOL VC_VoiceStopped(UBYTE); MIKMODAPI extern SLONG VC_VoiceGetPosition(UBYTE); MIKMODAPI extern ULONG VC_VoiceRealVolume(UBYTE); #ifdef __cplusplus } #endif #endif /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mikmod_build.h0000600000175000017500000000026010543202047020623 0ustar joeyjoey#include "mikmod.h" #if defined(WIN32) && !defined(__STDC__) # define __STDC__ 1 #endif #if defined(WIN32) && defined(_MSC_VER) # pragma warning(disable: 4018 4244) #endif uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mlreg.c0000600000175000017500000000301510543202047017266 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mlreg.c 2412 2006-08-18 18:37:39Z avolkov $ Routine for registering all loaders in libmikmod for the current platform. ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mikmod_internals.h" void MikMod_RegisterAllLoaders_internal(void) { _mm_registerloader(&load_it); _mm_registerloader(&load_mod); _mm_registerloader(&load_s3m); _mm_registerloader(&load_stm); _mm_registerloader(&load_xm); } void MikMod_RegisterAllLoaders(void) { MUTEX_LOCK(lists); MikMod_RegisterAllLoaders_internal(); MUTEX_UNLOCK(lists); } /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/Makeinfo0000600000175000017500000000035410543202047017473 0ustar joeyjoeyuqm_CFILES="drv_nos.c load_it.c load_mod.c load_s3m.c load_stm.c load_xm.c mdreg.c mdriver.c mloader.c mlreg.c mlutil.c mmalloc.c mmerror.c mmio.c mplayer.c munitrk.c mwav.c npertab.c sloader.c virtch.c virtch2.c virtch_common.c" uqm-0.6.2/sc2/src/sc2code/libs/mikmod/mmerror.c0000600000175000017500000001167110543202047017652 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: mmerror.c 2412 2006-08-18 18:37:39Z avolkov $ Error handling functions. Register an error handler with _mm_RegisterErrorHandler() and you're all set. ==============================================================================*/ /* The global variables _mm_errno, and _mm_critical are set before the error handler in called. See below for the values of these variables. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mikmod_internals.h" CHAR *_mm_errmsg[MMERR_MAX+1] = { /* No error */ "No error", /* Generic errors */ "Could not open requested file", "Out of memory", "Dynamic linking failed", /* Sample errors */ "Out of memory to load sample", "Out of sample handles to load sample", "Sample format not recognized", /* Module errors */ "Failure loading module pattern", "Failure loading module track", "Failure loading module header", "Failure loading sampleinfo", "Module format not recognized", "Module sample format not recognized", "Synthsounds not supported in MED files", "Compressed sample is invalid", /* Driver errors: */ "Sound device not detected", "Device number out of range", "Software mixer failure", "Could not open sound device", "This driver supports 8 bit linear output only", "This driver supports 16 bit linear output only", "This driver supports stereo output only", "This driver supports uLaw output (8 bit mono, 8 kHz) only", "Unable to set non-blocking mode for audio device", /* AudioFile driver errors */ "Cannot find suitable AudioFile audio port", /* AIX driver errors */ "Configuration (init step) of audio device failed", "Configuration (control step) of audio device failed", "Configuration (start step) of audio device failed", /* ALSA driver errors */ /* EsounD driver errors */ /* Ultrasound driver errors */ "Ultrasound driver only works in 16 bit stereo 44 KHz", "Ultrasound card could not be reset", "Could not start Ultrasound timer", /* HP driver errors */ "Unable to select 16bit-linear sample format", "Could not select requested sample-rate", "Could not select requested number of channels", "Unable to select audio output", "Unable to get audio description", "Could not set transmission buffer size", /* Open Sound System driver errors */ "Could not set fragment size", "Could not set sample size", "Could not set mono/stereo setting", "Could not set sample rate", /* SGI driver errors */ "Unsupported sample rate", "Hardware does not support 16 bit sound", "Hardware does not support 8 bit sound", "Hardware does not support stereo sound", "Hardware does not support mono sound", /* Sun driver errors */ "Sound device initialization failed", /* OS/2 drivers errors */ "Could not set mixing parameters", "Could not create playback semaphores", "Could not create playback timer", "Could not create playback thread", /* DirectSound driver errors */ "Could not set playback priority", "Could not create playback buffers", "Could not set playback format", "Could not register callback", "Could not register event", "Could not create playback thread", "Could not initialize playback thread", /* Windows Multimedia API driver errors */ "Invalid device handle", "The resource is already allocated", "Invalid device identifier", "Unsupported output format", "Unknown error", /* Macintosh driver errors */ "Unsupported sample rate", "Could not start playback", /* Invalid error */ "Invalid error code" }; MIKMODAPI char *MikMod_strerror(int code) { if ((code<0)||(code>MMERR_MAX)) code=MMERR_MAX+1; return _mm_errmsg[code]; } /* User installed error callback */ MikMod_handler_t _mm_errorhandler = NULL; MIKMODAPI int _mm_errno = 0; MIKMODAPI BOOL _mm_critical = 0; MikMod_handler_t _mm_registererrorhandler(MikMod_handler_t proc) { MikMod_handler_t oldproc=_mm_errorhandler; _mm_errorhandler = proc; return oldproc; } MIKMODAPI MikMod_handler_t MikMod_RegisterErrorHandler(MikMod_handler_t proc) { MikMod_handler_t result; MUTEX_LOCK(vars); result=_mm_registererrorhandler(proc); MUTEX_UNLOCK(vars); return result; } /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/load_it.c0000600000175000017500000007006710543202047017606 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: load_it.c 2412 2006-08-18 18:37:39Z avolkov $ Impulse tracker (IT) module loader ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #ifdef HAVE_MEMORY_H #include #endif #include #include "mikmod_internals.h" #ifdef SUNOS extern int fprintf(FILE *, const char *, ...); extern int toupper(int); #endif /*========== Module structure */ /* header */ typedef struct ITHEADER { CHAR songname[26]; UBYTE blank01[2]; UWORD ordnum; UWORD insnum; UWORD smpnum; UWORD patnum; UWORD cwt; /* Created with tracker (y.xx = 0x0yxx) */ UWORD cmwt; /* Compatible with tracker ver > than val. */ UWORD flags; UWORD special; /* bit 0 set = song message attached */ UBYTE globvol; UBYTE mixvol; /* mixing volume [ignored] */ UBYTE initspeed; UBYTE inittempo; UBYTE pansep; /* panning separation between channels */ UBYTE zerobyte; UWORD msglength; ULONG msgoffset; UBYTE blank02[4]; UBYTE pantable[64]; UBYTE voltable[64]; } ITHEADER; /* sample information */ typedef struct ITSAMPLE { CHAR filename[12]; UBYTE zerobyte; UBYTE globvol; UBYTE flag; UBYTE volume; UBYTE panning; CHAR sampname[28]; UWORD convert; /* sample conversion flag */ ULONG length; ULONG loopbeg; ULONG loopend; ULONG c5spd; ULONG susbegin; ULONG susend; ULONG sampoffset; UBYTE vibspeed; UBYTE vibdepth; UBYTE vibrate; UBYTE vibwave; /* 0=sine, 1=rampdown, 2=square, 3=random (speed ignored) */ } ITSAMPLE; /* instrument information */ #define ITENVCNT 25 #define ITNOTECNT 120 typedef struct ITINSTHEADER { ULONG size; /* (dword) Instrument size */ CHAR filename[12]; /* (char) Instrument filename */ UBYTE zerobyte; /* (byte) Instrument type (always 0) */ UBYTE volflg; UBYTE volpts; UBYTE volbeg; /* (byte) Volume loop start (node) */ UBYTE volend; /* (byte) Volume loop end (node) */ UBYTE volsusbeg; /* (byte) Volume sustain begin (node) */ UBYTE volsusend; /* (byte) Volume Sustain end (node) */ UBYTE panflg; UBYTE panpts; UBYTE panbeg; /* (byte) channel loop start (node) */ UBYTE panend; /* (byte) channel loop end (node) */ UBYTE pansusbeg; /* (byte) channel sustain begin (node) */ UBYTE pansusend; /* (byte) channel Sustain end (node) */ UBYTE pitflg; UBYTE pitpts; UBYTE pitbeg; /* (byte) pitch loop start (node) */ UBYTE pitend; /* (byte) pitch loop end (node) */ UBYTE pitsusbeg; /* (byte) pitch sustain begin (node) */ UBYTE pitsusend; /* (byte) pitch Sustain end (node) */ UWORD blank; UBYTE globvol; UBYTE chanpan; UWORD fadeout; /* Envelope end / NNA volume fadeout */ UBYTE dnc; /* Duplicate note check */ UBYTE dca; /* Duplicate check action */ UBYTE dct; /* Duplicate check type */ UBYTE nna; /* New Note Action [0,1,2,3] */ UWORD trkvers; /* tracker version used to save [files only] */ UBYTE ppsep; /* Pitch-pan Separation */ UBYTE ppcenter; /* Pitch-pan Center */ UBYTE rvolvar; /* random volume varations */ UBYTE rpanvar; /* random panning varations */ UWORD numsmp; /* Number of samples in instrument [files only] */ CHAR name[26]; /* Instrument name */ UBYTE blank01[6]; UWORD samptable[ITNOTECNT];/* sample for each note [note / samp pairs] */ UBYTE volenv[200]; /* volume envelope (IT 1.x stuff) */ UBYTE oldvoltick[ITENVCNT];/* volume tick position (IT 1.x stuff) */ UBYTE volnode[ITENVCNT]; /* amplitude of volume nodes */ UWORD voltick[ITENVCNT]; /* tick value of volume nodes */ SBYTE pannode[ITENVCNT]; /* panenv - node points */ UWORD pantick[ITENVCNT]; /* tick value of panning nodes */ SBYTE pitnode[ITENVCNT]; /* pitchenv - node points */ UWORD pittick[ITENVCNT]; /* tick value of pitch nodes */ } ITINSTHEADER; /* unpacked note */ typedef struct ITNOTE { UBYTE note,ins,volpan,cmd,inf; } ITNOTE; /*========== Loader data */ static ULONG *paraptr=NULL; /* parapointer array (see IT docs) */ static ITHEADER *mh=NULL; static ITNOTE *itpat=NULL; /* allocate to space for one full pattern */ static UBYTE *mask=NULL; /* arrays allocated to 64 elements and used for */ static ITNOTE *last=NULL; /* uncompressing IT's pattern information */ static int numtrk=0; static unsigned int old_effect; /* if set, use S3M old-effects stuffs */ static CHAR* IT_Version[]={ "ImpulseTracker . ", "Compressed ImpulseTracker . ", "ImpulseTracker 2.14p3", "Compressed ImpulseTracker 2.14p3", "ImpulseTracker 2.14p4", "Compressed ImpulseTracker 2.14p4", }; /* table for porta-to-note command within volume/panning column */ static UBYTE portatable[10]= {0,1,4,8,16,32,64,96,128,255}; /*========== Loader code */ BOOL IT_Test(void) { UBYTE id[4]; if(!_mm_read_UBYTES(id,4,modreader)) return 0; if(!memcmp(id,"IMPM",4)) return 1; return 0; } BOOL IT_Init(void) { if(!(mh=(ITHEADER*)MikMod_malloc(sizeof(ITHEADER)))) return 0; if(!(poslookup=(UBYTE*)MikMod_malloc(256*sizeof(UBYTE)))) return 0; if(!(itpat=(ITNOTE*)MikMod_malloc(200*64*sizeof(ITNOTE)))) return 0; if(!(mask=(UBYTE*)MikMod_malloc(64*sizeof(UBYTE)))) return 0; if(!(last=(ITNOTE*)MikMod_malloc(64*sizeof(ITNOTE)))) return 0; return 1; } void IT_Cleanup(void) { FreeLinear(); MikMod_free(mh); MikMod_free(poslookup); MikMod_free(itpat); MikMod_free(mask); MikMod_free(last); MikMod_free(paraptr); MikMod_free(origpositions); } /* Because so many IT files have 64 channels as the set number used, but really only use far less (usually from 8 to 24 still), I had to make this function, which determines the number of channels that are actually USED by a pattern. NOTE: You must first seek to the file location of the pattern before calling this procedure. Returns 1 on error */ static BOOL IT_GetNumChannels(UWORD patrows) { int row=0,flag,ch; do { if((flag=_mm_read_UBYTE(modreader))==EOF) { _mm_errno=MMERR_LOADING_PATTERN; return 1; } if(!flag) row++; else { ch=(flag-1)&63; remap[ch]=0; if(flag & 128) mask[ch]=_mm_read_UBYTE(modreader); if(mask[ch]&1) _mm_read_UBYTE(modreader); if(mask[ch]&2) _mm_read_UBYTE(modreader); if(mask[ch]&4) _mm_read_UBYTE(modreader); if(mask[ch]&8) { _mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader); } } } while(rownote=n->note=_mm_read_UBYTE(modreader))==255) l->note=n->note=253; if(mask[ch]&2) l->ins=n->ins=_mm_read_UBYTE(modreader); if(mask[ch]&4) l->volpan=n->volpan=_mm_read_UBYTE(modreader); if(mask[ch]&8) { l->cmd=n->cmd=_mm_read_UBYTE(modreader); l->inf=n->inf=_mm_read_UBYTE(modreader); } if(mask[ch]&16) n->note=l->note; if(mask[ch]&32) n->ins=l->ins; if(mask[ch]&64) n->volpan=l->volpan; if(mask[ch]&128) { n->cmd=l->cmd; n->inf=l->inf; } } } while(rowsongname,26,modreader); _mm_read_UBYTES(mh->blank01,2,modreader); mh->ordnum =_mm_read_I_UWORD(modreader); mh->insnum =_mm_read_I_UWORD(modreader); mh->smpnum =_mm_read_I_UWORD(modreader); mh->patnum =_mm_read_I_UWORD(modreader); mh->cwt =_mm_read_I_UWORD(modreader); mh->cmwt =_mm_read_I_UWORD(modreader); mh->flags =_mm_read_I_UWORD(modreader); mh->special =_mm_read_I_UWORD(modreader); mh->globvol =_mm_read_UBYTE(modreader); mh->mixvol =_mm_read_UBYTE(modreader); mh->initspeed =_mm_read_UBYTE(modreader); mh->inittempo =_mm_read_UBYTE(modreader); mh->pansep =_mm_read_UBYTE(modreader); mh->zerobyte =_mm_read_UBYTE(modreader); mh->msglength =_mm_read_I_UWORD(modreader); mh->msgoffset =_mm_read_I_ULONG(modreader); _mm_read_UBYTES(mh->blank02,4,modreader); _mm_read_UBYTES(mh->pantable,64,modreader); _mm_read_UBYTES(mh->voltable,64,modreader); if(_mm_eof(modreader)) { _mm_errno=MMERR_LOADING_HEADER; return 0; } /* set module variables */ of.songname = DupStr(mh->songname,26,0); /* make a cstr of songname */ of.reppos = 0; of.numpat = mh->patnum; of.numins = mh->insnum; of.numsmp = mh->smpnum; of.initspeed = mh->initspeed; of.inittempo = mh->inittempo; of.initvolume = mh->globvol; of.flags |= UF_BGSLIDES | UF_ARPMEM; if (!(mh->flags & 1)) of.flags |= UF_PANNING; of.bpmlimit=32; if(mh->songname[25]) { of.numvoices=1+mh->songname[25]; #ifdef MIKMOD_DEBUG fprintf(stderr,"Embedded IT limitation to %d voices\n",of.numvoices); #endif } /* set the module type */ /* 2.17 : IT 2.14p4 */ /* 2.16 : IT 2.14p3 with resonant filters */ /* 2.15 : IT 2.14p3 (improved compression) */ if((mh->cwt<=0x219)&&(mh->cwt>=0x217)) of.modtype=strdup(IT_Version[mh->cmwt<0x214?4:5]); else if (mh->cwt>=0x215) of.modtype=strdup(IT_Version[mh->cmwt<0x214?2:3]); else { of.modtype = strdup(IT_Version[mh->cmwt<0x214?0:1]); of.modtype[mh->cmwt<0x214?15:26] = (mh->cwt>>8)+'0'; of.modtype[mh->cmwt<0x214?17:28] = ((mh->cwt>>4)&0xf)+'0'; of.modtype[mh->cmwt<0x214?18:29] = ((mh->cwt)&0xf)+'0'; } if(mh->flags&8) of.flags |= UF_XMPERIODS | UF_LINEAR; if((mh->cwt>=0x106)&&(mh->flags&16)) old_effect=S3MIT_OLDSTYLE; else old_effect=0; /* set panning positions */ if (mh->flags & 1) for(t=0;t<64;t++) { mh->pantable[t]&=0x7f; if(mh->pantable[t]<64) of.panning[t]=mh->pantable[t]<<2; else if(mh->pantable[t]==64) of.panning[t]=255; else if(mh->pantable[t]==100) of.panning[t]=PAN_SURROUND; else if(mh->pantable[t]==127) of.panning[t]=PAN_CENTER; else { _mm_errno=MMERR_LOADING_HEADER; return 0; } } else for(t=0;t<64;t++) of.panning[t]=PAN_CENTER; /* set channel volumes */ memcpy(of.chanvol,mh->voltable,64); /* read the order data */ if(!AllocPositions(mh->ordnum)) return 0; if(!(origpositions=MikMod_calloc(mh->ordnum,sizeof(UWORD)))) return 0; for(t=0;tordnum;t++) { origpositions[t]=_mm_read_UBYTE(modreader); if((origpositions[t]>mh->patnum)&&(origpositions[t]<254)) origpositions[t]=255; } if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } poslookupcnt=mh->ordnum; S3MIT_CreateOrders(curious); if(!(paraptr=(ULONG*)MikMod_malloc((mh->insnum+mh->smpnum+of.numpat)* sizeof(ULONG)))) return 0; /* read the instrument, sample, and pattern parapointers */ _mm_read_I_ULONGS(paraptr,mh->insnum+mh->smpnum+of.numpat,modreader); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } /* Check for and load midi information for resonant filters */ if(mh->cmwt>=0x216) { if(mh->special&8) { IT_LoadMidiConfiguration(modreader); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } } else IT_LoadMidiConfiguration(NULL); filters=1; } /* Check for and load song comment */ if((mh->special&1)&&(mh->cwt>=0x104)&&(mh->msglength)) { _mm_fseek(modreader,(long)(mh->msgoffset),SEEK_SET); if(!ReadComment(mh->msglength)) return 0; } if(!(mh->flags&4)) of.numins=of.numsmp; if(!AllocSamples()) return 0; if(!AllocLinear()) return 0; /* Load all samples */ q = of.samples; for(t=0;tsmpnum;t++) { ITSAMPLE s; /* seek to sample position */ _mm_fseek(modreader,(long)(paraptr[mh->insnum+t]+4),SEEK_SET); /* load sample info */ _mm_read_string(s.filename,12,modreader); s.zerobyte = _mm_read_UBYTE(modreader); s.globvol = _mm_read_UBYTE(modreader); s.flag = _mm_read_UBYTE(modreader); s.volume = _mm_read_UBYTE(modreader); _mm_read_string(s.sampname,26,modreader); s.convert = _mm_read_UBYTE(modreader); s.panning = _mm_read_UBYTE(modreader); s.length = _mm_read_I_ULONG(modreader); s.loopbeg = _mm_read_I_ULONG(modreader); s.loopend = _mm_read_I_ULONG(modreader); s.c5spd = _mm_read_I_ULONG(modreader); s.susbegin = _mm_read_I_ULONG(modreader); s.susend = _mm_read_I_ULONG(modreader); s.sampoffset = _mm_read_I_ULONG(modreader); s.vibspeed = _mm_read_UBYTE(modreader); s.vibdepth = _mm_read_UBYTE(modreader); s.vibrate = _mm_read_UBYTE(modreader); s.vibwave = _mm_read_UBYTE(modreader); /* Generate an error if c5spd is > 512k, or samplelength > 256 megs (nothing would EVER be that high) */ if(_mm_eof(modreader)||(s.c5spd>0x7ffffL)||(s.length>0xfffffffUL)) { _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } /* Reality check for sample loop information */ if((s.flag&16)&& ((s.loopbeg>0xfffffffUL)||(s.loopend>0xfffffffUL))) { _mm_errno = MMERR_LOADING_SAMPLEINFO; return 0; } q->samplename = DupStr(s.sampname,26,0); q->speed = s.c5spd / 2; q->panning = ((s.panning&127)==64)?255:(s.panning&127)<<2; q->length = s.length; q->loopstart = s.loopbeg; q->loopend = s.loopend; q->volume = s.volume; q->globvol = s.globvol; q->seekpos = s.sampoffset; /* Convert speed to XM linear finetune */ if(of.flags&UF_LINEAR) q->speed=speed_to_finetune(s.c5spd,t); if(s.panning&128) q->flags|=SF_OWNPAN; if(s.vibrate) { q->vibflags |= AV_IT; q->vibtype = s.vibwave; q->vibsweep = s.vibrate * 2; q->vibdepth = s.vibdepth; q->vibrate = s.vibspeed; } if(s.flag&2) q->flags|=SF_16BITS; if((s.flag&8)&&(mh->cwt>=0x214)) { q->flags|=SF_ITPACKED; compressed=1; } if(s.flag&16) q->flags|=SF_LOOP; if(s.flag&64) q->flags|=SF_BIDI; if(mh->cwt>=0x200) { if(s.convert&1) q->flags|=SF_SIGNED; if(s.convert&4) q->flags|=SF_DELTA; } q++; } /* Load instruments if instrument mode flag enabled */ if(mh->flags&4) { if(!AllocInstruments()) return 0; d=of.instruments; of.flags|=UF_NNA|UF_INST; for(t=0;tinsnum;t++) { ITINSTHEADER ih; /* seek to instrument position */ _mm_fseek(modreader,paraptr[t]+4,SEEK_SET); /* load instrument info */ _mm_read_string(ih.filename,12,modreader); ih.zerobyte = _mm_read_UBYTE(modreader); if(mh->cwt<0x200) { /* load IT 1.xx inst header */ ih.volflg = _mm_read_UBYTE(modreader); ih.volbeg = _mm_read_UBYTE(modreader); ih.volend = _mm_read_UBYTE(modreader); ih.volsusbeg = _mm_read_UBYTE(modreader); ih.volsusend = _mm_read_UBYTE(modreader); _mm_read_I_UWORD(modreader); ih.fadeout = _mm_read_I_UWORD(modreader); ih.nna = _mm_read_UBYTE(modreader); ih.dnc = _mm_read_UBYTE(modreader); } else { /* Read IT200+ header */ ih.nna = _mm_read_UBYTE(modreader); ih.dct = _mm_read_UBYTE(modreader); ih.dca = _mm_read_UBYTE(modreader); ih.fadeout = _mm_read_I_UWORD(modreader); ih.ppsep = _mm_read_UBYTE(modreader); ih.ppcenter = _mm_read_UBYTE(modreader); ih.globvol = _mm_read_UBYTE(modreader); ih.chanpan = _mm_read_UBYTE(modreader); ih.rvolvar = _mm_read_UBYTE(modreader); ih.rpanvar = _mm_read_UBYTE(modreader); } ih.trkvers = _mm_read_I_UWORD(modreader); ih.numsmp = _mm_read_UBYTE(modreader); _mm_read_UBYTE(modreader); _mm_read_string(ih.name,26,modreader); _mm_read_UBYTES(ih.blank01,6,modreader); _mm_read_I_UWORDS(ih.samptable,ITNOTECNT,modreader); if(mh->cwt<0x200) { /* load IT 1xx volume envelope */ _mm_read_UBYTES(ih.volenv,200,modreader); for(lp=0;lpvolflg|=EF_VOLENV; d->insname = DupStr(ih.name,26,0); d->nnatype = ih.nna & NNA_MASK; if(mh->cwt<0x200) { d->volfade=ih.fadeout<< 6; if(ih.dnc) { d->dct=DCT_NOTE; d->dca=DCA_CUT; } if(ih.volflg&1) d->volflg|=EF_ON; if(ih.volflg&2) d->volflg|=EF_LOOP; if(ih.volflg&4) d->volflg|=EF_SUSTAIN; /* XM conversion of IT envelope Array */ d->volbeg = ih.volbeg; d->volend = ih.volend; d->volsusbeg = ih.volsusbeg; d->volsusend = ih.volsusend; if(ih.volflg&1) { for(u=0;uvolpts]!=0xff) { d->volenv[d->volpts].val=(ih.volnode[d->volpts]<<2); d->volenv[d->volpts].pos=ih.oldvoltick[d->volpts]; d->volpts++; } else break; } } else { d->panning=((ih.chanpan&127)==64)?255:(ih.chanpan&127)<<2; if(!(ih.chanpan&128)) d->flags|=IF_OWNPAN; if(!(ih.ppsep & 128)) { d->pitpansep=ih.ppsep<<2; d->pitpancenter=ih.ppcenter; d->flags|=IF_PITCHPAN; } d->globvol=ih.globvol>>1; d->volfade=ih.fadeout<<5; d->dct =ih.dct; d->dca =ih.dca; if(mh->cwt>=0x204) { d->rvolvar = ih.rvolvar; d->rpanvar = ih.rpanvar; } #if defined __STDC__ || defined _MSC_VER || defined MPW_C #define IT_ProcessEnvelope(name) \ if(ih. name##flg&1) d-> name##flg|=EF_ON; \ if(ih. name##flg&2) d-> name##flg|=EF_LOOP; \ if(ih. name##flg&4) d-> name##flg|=EF_SUSTAIN; \ d-> name##pts=ih. name##pts; \ d-> name##beg=ih. name##beg; \ d-> name##end=ih. name##end; \ d-> name##susbeg=ih. name##susbeg; \ d-> name##susend=ih. name##susend; \ \ for(u=0;u name##env[u].pos=ih. name##tick[u]; \ \ if((d-> name##flg&EF_ON)&&(d-> name##pts<2)) \ d-> name##flg&=~EF_ON #else #define IT_ProcessEnvelope(name) \ if(ih. name/**/flg&1) d-> name/**/flg|=EF_ON; \ if(ih. name/**/flg&2) d-> name/**/flg|=EF_LOOP; \ if(ih. name/**/flg&4) d-> name/**/flg|=EF_SUSTAIN; \ d-> name/**/pts=ih. name/**/pts; \ d-> name/**/beg=ih. name/**/beg; \ d-> name/**/end=ih. name/**/end; \ d-> name/**/susbeg=ih. name/**/susbeg; \ d-> name/**/susend=ih. name/**/susend; \ \ for(u=0;u name/**/env[u].pos=ih. name/**/tick[u]; \ \ if((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \ d-> name/**/flg&=~EF_ON #endif IT_ProcessEnvelope(vol); for(u=0;uvolenv[u].val=(ih.volnode[u]<<2); IT_ProcessEnvelope(pan); for(u=0;upanenv[u].val= ih.pannode[u]==32?255:(ih.pannode[u]+32)<<2; IT_ProcessEnvelope(pit); for(u=0;upitenv[u].val=ih.pitnode[u]+32; #undef IT_ProcessEnvelope if(ih.pitflg&0x80) { /* filter envelopes not supported yet */ d->pitflg&=~EF_ON; ih.pitpts=ih.pitbeg=ih.pitend=0; #ifdef MIKMOD_DEBUG { static int warn=0; if(!warn) fprintf(stderr, "\rFilter envelopes not supported yet\n"); warn=1; } #endif } } for(u=0;usamplenote[u]=(ih.samptable[u]&255); d->samplenumber[u]= (ih.samptable[u]>>8)?((ih.samptable[u]>>8)-1):0xffff; if(d->samplenumber[u]>=of.numsmp) d->samplenote[u]=255; else if (of.flags&UF_LINEAR) { int note=(int)d->samplenote[u]+noteindex[d->samplenumber[u]]; d->samplenote[u]=(note<0)?0:(note>255?255:note); } } d++; } } else if(of.flags & UF_LINEAR) { if(!AllocInstruments()) return 0; d=of.instruments; of.flags|=UF_INST; for(t=0;tsmpnum;t++,d++) for(u=0;usamplenumber[u]>=of.numsmp) d->samplenote[u]=255; else { int note=(int)d->samplenote[u]+noteindex[d->samplenumber[u]]; d->samplenote[u]=(note<0)?0:(note>255?255:note); } } } /* Figure out how many channels this song actually uses */ of.numchn=0; memset(remap,-1,UF_MAXCHAN*sizeof(UBYTE)); for(t=0;tinsnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */ _mm_fseek(modreader,((long)paraptr[mh->insnum+mh->smpnum+t]),SEEK_SET); _mm_read_I_UWORD(modreader); /* read pattern length (# of rows) Impulse Tracker never creates patterns with less than 32 rows, but some other trackers do, so we only check for more than 256 rows */ packlen=_mm_read_I_UWORD(modreader); if(packlen>256) { _mm_errno=MMERR_LOADING_PATTERN; return 0; } _mm_read_I_ULONG(modreader); if(IT_GetNumChannels(packlen)) return 0; } } /* give each of them a different number */ for(t=0;tinsnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */ of.pattrows[t]=64; for(u=0;uinsnum+mh->smpnum+t]),SEEK_SET); packlen=_mm_read_I_UWORD(modreader); of.pattrows[t]=_mm_read_I_UWORD(modreader); _mm_read_I_ULONG(modreader); if(!IT_ReadPattern(of.pattrows[t])) return 0; } } return 1; } CHAR *IT_LoadTitle(void) { CHAR s[26]; _mm_fseek(modreader,4,SEEK_SET); if(!_mm_read_UBYTES(s,26,modreader)) return NULL; return(DupStr(s,26,0)); } /*========== Loader information */ MIKMODAPI MLOADER load_it={ NULL, "IT", "IT (Impulse Tracker)", IT_Init, IT_Test, IT_Load, IT_Cleanup, IT_LoadTitle }; /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/virtch_common.c0000600000175000017500000003077510543202047021044 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: virtch_common.c 2421 2006-08-19 00:36:21Z avolkov $ Common source parts between the two software mixers. This file is probably the ugliest part of libmikmod... ==============================================================================*/ #ifndef _IN_VIRTCH_ #include "mikmod_internals.h" extern BOOL VC1_Init(void); extern BOOL VC2_Init(void); static BOOL (*VC_Init_ptr)(void)=VC1_Init; extern void VC1_Exit(void); extern void VC2_Exit(void); static void (*VC_Exit_ptr)(void)=VC1_Exit; extern BOOL VC1_SetNumVoices(void); extern BOOL VC2_SetNumVoices(void); static BOOL (*VC_SetNumVoices_ptr)(void); extern ULONG VC1_SampleSpace(int); extern ULONG VC2_SampleSpace(int); static ULONG (*VC_SampleSpace_ptr)(int); extern ULONG VC1_SampleLength(int,SAMPLE*); extern ULONG VC2_SampleLength(int,SAMPLE*); static ULONG (*VC_SampleLength_ptr)(int,SAMPLE*); extern BOOL VC1_PlayStart(void); extern BOOL VC2_PlayStart(void); static BOOL (*VC_PlayStart_ptr)(void); extern void VC1_PlayStop(void); extern void VC2_PlayStop(void); static void (*VC_PlayStop_ptr)(void); extern SWORD VC1_SampleLoad(struct SAMPLOAD*,int); extern SWORD VC2_SampleLoad(struct SAMPLOAD*,int); static SWORD (*VC_SampleLoad_ptr)(struct SAMPLOAD*,int); extern void VC1_SampleUnload(SWORD); extern void VC2_SampleUnload(SWORD); static void (*VC_SampleUnload_ptr)(SWORD); extern ULONG VC1_WriteBytes(SBYTE*,ULONG); extern ULONG VC2_WriteBytes(SBYTE*,ULONG); static ULONG (*VC_WriteBytes_ptr)(SBYTE*,ULONG); extern ULONG VC1_SilenceBytes(SBYTE*,ULONG); extern ULONG VC2_SilenceBytes(SBYTE*,ULONG); static ULONG (*VC_SilenceBytes_ptr)(SBYTE*,ULONG); extern void VC1_VoiceSetVolume(UBYTE,UWORD); extern void VC2_VoiceSetVolume(UBYTE,UWORD); static void (*VC_VoiceSetVolume_ptr)(UBYTE,UWORD); extern UWORD VC1_VoiceGetVolume(UBYTE); extern UWORD VC2_VoiceGetVolume(UBYTE); static UWORD (*VC_VoiceGetVolume_ptr)(UBYTE); extern void VC1_VoiceSetFrequency(UBYTE,ULONG); extern void VC2_VoiceSetFrequency(UBYTE,ULONG); static void (*VC_VoiceSetFrequency_ptr)(UBYTE,ULONG); extern ULONG VC1_VoiceGetFrequency(UBYTE); extern ULONG VC2_VoiceGetFrequency(UBYTE); static ULONG (*VC_VoiceGetFrequency_ptr)(UBYTE); extern void VC1_VoiceSetPanning(UBYTE,ULONG); extern void VC2_VoiceSetPanning(UBYTE,ULONG); static void (*VC_VoiceSetPanning_ptr)(UBYTE,ULONG); extern ULONG VC1_VoiceGetPanning(UBYTE); extern ULONG VC2_VoiceGetPanning(UBYTE); static ULONG (*VC_VoiceGetPanning_ptr)(UBYTE); extern void VC1_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD); extern void VC2_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD); static void (*VC_VoicePlay_ptr)(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD); extern void VC1_VoiceStop(UBYTE); extern void VC2_VoiceStop(UBYTE); static void (*VC_VoiceStop_ptr)(UBYTE); extern BOOL VC1_VoiceStopped(UBYTE); extern BOOL VC2_VoiceStopped(UBYTE); static BOOL (*VC_VoiceStopped_ptr)(UBYTE); extern SLONG VC1_VoiceGetPosition(UBYTE); extern SLONG VC2_VoiceGetPosition(UBYTE); static SLONG (*VC_VoiceGetPosition_ptr)(UBYTE); extern ULONG VC1_VoiceRealVolume(UBYTE); extern ULONG VC2_VoiceRealVolume(UBYTE); static ULONG (*VC_VoiceRealVolume_ptr)(UBYTE); #if defined __STDC__ || defined _MSC_VER || defined MPW_C #define VC_PROC0(suffix) \ MIKMODAPI void VC_##suffix (void) { VC_##suffix##_ptr(); } #define VC_FUNC0(suffix,ret) \ MIKMODAPI ret VC_##suffix (void) { return VC_##suffix##_ptr(); } #define VC_PROC1(suffix,typ1) \ MIKMODAPI void VC_##suffix (typ1 a) { VC_##suffix##_ptr(a); } #define VC_FUNC1(suffix,ret,typ1) \ MIKMODAPI ret VC_##suffix (typ1 a) { return VC_##suffix##_ptr(a); } #define VC_PROC2(suffix,typ1,typ2) \ MIKMODAPI void VC_##suffix (typ1 a,typ2 b) { VC_##suffix##_ptr(a,b); } #define VC_FUNC2(suffix,ret,typ1,typ2) \ MIKMODAPI ret VC_##suffix (typ1 a,typ2 b) { return VC_##suffix##_ptr(a,b); } #else #define VC_PROC0(suffix) \ MIKMODAPI void VC_/**/suffix (void) { VC_/**/suffix/**/_ptr(); } #define VC_FUNC0(suffix,ret) \ MIKMODAPI ret VC_/**/suffix (void) { return VC_/**/suffix/**/_ptr(); } #define VC_PROC1(suffix,typ1) \ MIKMODAPI void VC_/**/suffix (typ1 a) { VC_/**/suffix/**/_ptr(a); } #define VC_FUNC1(suffix,ret,typ1) \ MIKMODAPI ret VC_/**/suffix (typ1 a) { return VC_/**/suffix/**/_ptr(a); } #define VC_PROC2(suffix,typ1,typ2) \ MIKMODAPI void VC_/**/suffix (typ1 a,typ2 b) { VC_/**/suffix/**/_ptr(a,b); } #define VC_FUNC2(suffix,ret,typ1,typ2) \ MIKMODAPI ret VC_/**/suffix (typ1 a,typ2 b) { return VC_/**/suffix/**/_ptr(a,b); } #endif VC_FUNC0(Init,BOOL) VC_PROC0(Exit) VC_FUNC0(SetNumVoices,BOOL) VC_FUNC1(SampleSpace,ULONG,int) VC_FUNC2(SampleLength,ULONG,int,SAMPLE*) VC_FUNC0(PlayStart,BOOL) VC_PROC0(PlayStop) VC_FUNC2(SampleLoad,SWORD,struct SAMPLOAD*,int) VC_PROC1(SampleUnload,SWORD) VC_FUNC2(WriteBytes,ULONG,SBYTE*,ULONG) VC_FUNC2(SilenceBytes,ULONG,SBYTE*,ULONG) VC_PROC2(VoiceSetVolume,UBYTE,UWORD) VC_FUNC1(VoiceGetVolume,UWORD,UBYTE) VC_PROC2(VoiceSetFrequency,UBYTE,ULONG) VC_FUNC1(VoiceGetFrequency,ULONG,UBYTE) VC_PROC2(VoiceSetPanning,UBYTE,ULONG) VC_FUNC1(VoiceGetPanning,ULONG,UBYTE) void VC_VoicePlay(UBYTE a,SWORD b,ULONG c,ULONG d,ULONG e,ULONG f,UWORD g) { VC_VoicePlay_ptr(a,b,c,d,e,f,g); } VC_PROC1(VoiceStop,UBYTE) VC_FUNC1(VoiceStopped,BOOL,UBYTE) VC_FUNC1(VoiceGetPosition,SLONG,UBYTE) VC_FUNC1(VoiceRealVolume,ULONG,UBYTE) void VC_SetupPointers(void) { if (md_mode&DMODE_HQMIXER) { VC_Init_ptr=VC2_Init; VC_Exit_ptr=VC2_Exit; VC_SetNumVoices_ptr=VC2_SetNumVoices; VC_SampleSpace_ptr=VC2_SampleSpace; VC_SampleLength_ptr=VC2_SampleLength; VC_PlayStart_ptr=VC2_PlayStart; VC_PlayStop_ptr=VC2_PlayStop; VC_SampleLoad_ptr=VC2_SampleLoad; VC_SampleUnload_ptr=VC2_SampleUnload; VC_WriteBytes_ptr=VC2_WriteBytes; VC_SilenceBytes_ptr=VC2_SilenceBytes; VC_VoiceSetVolume_ptr=VC2_VoiceSetVolume; VC_VoiceGetVolume_ptr=VC2_VoiceGetVolume; VC_VoiceSetFrequency_ptr=VC2_VoiceSetFrequency; VC_VoiceGetFrequency_ptr=VC2_VoiceGetFrequency; VC_VoiceSetPanning_ptr=VC2_VoiceSetPanning; VC_VoiceGetPanning_ptr=VC2_VoiceGetPanning; VC_VoicePlay_ptr=VC2_VoicePlay; VC_VoiceStop_ptr=VC2_VoiceStop; VC_VoiceStopped_ptr=VC2_VoiceStopped; VC_VoiceGetPosition_ptr=VC2_VoiceGetPosition; VC_VoiceRealVolume_ptr=VC2_VoiceRealVolume; } else { VC_Init_ptr=VC1_Init; VC_Exit_ptr=VC1_Exit; VC_SetNumVoices_ptr=VC1_SetNumVoices; VC_SampleSpace_ptr=VC1_SampleSpace; VC_SampleLength_ptr=VC1_SampleLength; VC_PlayStart_ptr=VC1_PlayStart; VC_PlayStop_ptr=VC1_PlayStop; VC_SampleLoad_ptr=VC1_SampleLoad; VC_SampleUnload_ptr=VC1_SampleUnload; VC_WriteBytes_ptr=VC1_WriteBytes; VC_SilenceBytes_ptr=VC1_SilenceBytes; VC_VoiceSetVolume_ptr=VC1_VoiceSetVolume; VC_VoiceGetVolume_ptr=VC1_VoiceGetVolume; VC_VoiceSetFrequency_ptr=VC1_VoiceSetFrequency; VC_VoiceGetFrequency_ptr=VC1_VoiceGetFrequency; VC_VoiceSetPanning_ptr=VC1_VoiceSetPanning; VC_VoiceGetPanning_ptr=VC1_VoiceGetPanning; VC_VoicePlay_ptr=VC1_VoicePlay; VC_VoiceStop_ptr=VC1_VoiceStop; VC_VoiceStopped_ptr=VC1_VoiceStopped; VC_VoiceGetPosition_ptr=VC1_VoiceGetPosition; VC_VoiceRealVolume_ptr=VC1_VoiceRealVolume; } } #else #ifndef _VIRTCH_COMMON_ #define _VIRTCH_COMMON_ static ULONG samples2bytes(ULONG samples) { if(vc_mode & DMODE_16BITS) samples <<= 1; if(vc_mode & DMODE_STEREO) samples <<= 1; return samples; } static ULONG bytes2samples(ULONG bytes) { if(vc_mode & DMODE_16BITS) bytes >>= 1; if(vc_mode & DMODE_STEREO) bytes >>= 1; return bytes; } /* Fill the buffer with 'todo' bytes of silence (it depends on the mixing mode how the buffer is filled) */ ULONG VC1_SilenceBytes(SBYTE* buf,ULONG todo) { todo=samples2bytes(bytes2samples(todo)); /* clear the buffer to zero (16 bits signed) or 0x80 (8 bits unsigned) */ if(vc_mode & DMODE_16BITS) memset(buf,0,todo); else memset(buf,0x80,todo); return todo; } void VC1_WriteSamples(SBYTE*,ULONG); /* Writes 'todo' mixed SBYTES (!!) to 'buf'. It returns the number of SBYTES actually written to 'buf' (which is rounded to number of samples that fit into 'todo' bytes). */ ULONG VC1_WriteBytes(SBYTE* buf,ULONG todo) { if(!vc_softchn) return VC1_SilenceBytes(buf,todo); todo = bytes2samples(todo); VC1_WriteSamples(buf,todo); return samples2bytes(todo); } void VC1_Exit(void) { if(vc_tickbuf) MikMod_free(vc_tickbuf); if(vinf) MikMod_free(vinf); if(Samples) MikMod_free(Samples); vc_tickbuf = NULL; vinf = NULL; Samples = NULL; VC_SetupPointers(); } UWORD VC1_VoiceGetVolume(UBYTE voice) { return vinf[voice].vol; } ULONG VC1_VoiceGetPanning(UBYTE voice) { return vinf[voice].pan; } void VC1_VoiceSetFrequency(UBYTE voice,ULONG frq) { vinf[voice].frq=frq; } ULONG VC1_VoiceGetFrequency(UBYTE voice) { return vinf[voice].frq; } void VC1_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { vinf[voice].flags = flags; vinf[voice].handle = handle; vinf[voice].start = start; vinf[voice].size = size; vinf[voice].reppos = reppos; vinf[voice].repend = repend; vinf[voice].kick = 1; } void VC1_VoiceStop(UBYTE voice) { vinf[voice].active = 0; } BOOL VC1_VoiceStopped(UBYTE voice) { return(vinf[voice].active==0); } SLONG VC1_VoiceGetPosition(UBYTE voice) { return(vinf[voice].current>>FRACBITS); } void VC1_VoiceSetVolume(UBYTE voice,UWORD vol) { /* protect against clicks if volume variation is too high */ if(abs((int)vinf[voice].vol-(int)vol)>32) vinf[voice].rampvol=CLICK_BUFFER; vinf[voice].vol=vol; } void VC1_VoiceSetPanning(UBYTE voice,ULONG pan) { /* protect against clicks if panning variation is too high */ if(abs((int)vinf[voice].pan-(int)pan)>48) vinf[voice].rampvol=CLICK_BUFFER; vinf[voice].pan=pan; } /*========== External mixer interface */ void VC1_SampleUnload(SWORD handle) { if (handlesample; int handle; ULONG t, length,loopstart,loopend; if(type==MD_HARDWARE) return -1; /* Find empty slot to put sample address in */ for(handle=0;handleloopend > s->length) s->loopend = s->length; if (s->loopstart >= s->loopend) s->flags &= ~SF_LOOP; length = s->length; loopstart = s->loopstart; loopend = s->loopend; SL_SampleSigned(sload); SL_Sample8to16(sload); if(!(Samples[handle]=(SWORD*)MikMod_malloc((length+20)<<1))) { _mm_errno = MMERR_SAMPLE_TOO_BIG; return -1; } /* read sample into buffer */ if (SL_Load(Samples[handle],sload,length)) return -1; /* Unclick sample */ if(s->flags & SF_LOOP) { if(s->flags & SF_BIDI) for(t=0;t<16;t++) Samples[handle][loopend+t]=Samples[handle][(loopend-t)-1]; else for(t=0;t<16;t++) Samples[handle][loopend+t]=Samples[handle][t+loopstart]; } else for(t=0;t<16;t++) Samples[handle][t+length]=0; return handle; } ULONG VC1_SampleSpace(int type) { (void)type; /* unused arg */ return vc_memory; } ULONG VC1_SampleLength(int type,SAMPLE* s) { (void)type; /* unused arg */ if (!s) return 0; return (s->length*((s->flags&SF_16BITS)?2:1))+16; } ULONG VC1_VoiceRealVolume(UBYTE voice) { ULONG i,s,size; int k,j; SWORD *smp; SLONG t; t = vinf[voice].current>>FRACBITS; if(!vinf[voice].active) return 0; s = vinf[voice].handle; size = vinf[voice].size; i=64; t-=64; k=0; j=0; if(i>size) i = size; if(t<0) t = 0; if(t+i > size) t = size-i; i &= ~1; /* make sure it's EVEN. */ smp = &Samples[s][t]; for(;i;i--,smp++) { if(k<*smp) k = *smp; if(j>*smp) j = *smp; } return abs(k-j); } #endif #endif /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/mikmod/AUTHORS0000600000175000017500000001006710543202047017071 0ustar joeyjoeylibmikmod main authors ---------------------- * Jean-Paul Mikkers (MikMak) wrote MikMod and maintained it until version 3. * Jake Stine (Air Richter) [email doesn't work anymore...] made decisive contributions to the code (esp. IT support) and maintained MikMod version 3 until it was discontinued. He still works on the WinAmp module plugin, roughly based on MikMod. * Miod Vallat current overbooked libmikmod maintainer (since version 3.0.4), made an audit of the code resulting in many bugs fixed. Previous Unix maintainers ------------------------- * Steve McIntyre maintained MikMod'Unix version 2. Used to maintain the Debian package for MikMod. * Peter Amstutz maintained MikMod'Unix version 3 up to version 3.0.3. General contributors -------------------- * Arne de Bruijn wrote the compressed IT sample support. * Shlomi Fish wrote the Java port, bug fixes. * Juan Linietsky overall bug fixes. * Claudio Matsuoka wrote the STX loader and submitted bug fixes. * Sebastiaan A. Megens fixed various bugs (memory leaks, endianness issues, etc). * ``UFO'' wrote the OKT loader. * Kev Vance wrote the GDM loader. * Paul Fisher made decisive contributions and improvements. * Alexander Kerkhove fixed an ULT panning effect bug. * ``Kodiak'' helped on the interfaces of libmikmod. * Sylvain Marchand make MikMod more portable and GCC compilable. Contributors on the Unix side ----------------------------- * Douglas Carmichael ported MikMod to FreeBSD. * Chris Conn wrote the OSS driver. * Roine Gustaffson wrote the Digital AudioFile driver. * Stephan Kanthak wrote the SGI driver. * Lutz Vieweg wrote the AIX and HP-UX drivers. * Valtteri Vuorikoski wrote the Sun driver. * Andy Lo A Foe wrote the Ultra driver (for the Gravis Ultrasound sound card). * C Ray C updated the Ultra driver to work with libmikmod 3. * ``MenTaLguY'' autoconfized the Unix libmikmod distribution. * Tobias Gloth created the new I/O interface, made the code MT-safe and submitted bug fixes. * Simon Hosie wrote the piped output driver, and submitted speed optimizations and bugfixes for the software mixer. * Gerd Rausch wrote the sam9407 driver. * Joseph Carter maintains the Debian package for MikMod and libmikmod, submitted bugfixes. Contributors on the Windows side -------------------------------- * Brian McKinney created the DirectSound driver. * Bjornar Henden created the Multimedia API windows driver. Contributors on the Dos side ---------------------------- Their code isn't there anymore, but they contributed to the success of libmikmod... * Jean-Philippe Ajirent wrote the EMS memory routines. * Peter Breitling ported MikMod to DJGPP. * Arnout Cosman wrote the PAS driver. * Mario Koeppen wrote the WSS driver. * Mike Leibow wrote the GUS driver. * Jeremy McDonald wrote a fast assembly-language mixer. * Steffen Rusitschka and Vince Vu wrote the AWE driver. Contributors on the Macintosh side ---------------------------------- * Anders Bjoerklund ported libmikmod to the Macintosh. Contributors on the OS/2 side ----------------------------- * Stefan Tibus ported libmikmod to OS/2. * Andrew Zabolotny improved the existing OS/2 drivers. Contributors on the BeOS side ----------------------------- * Thomas Neumann integrated libmikmod into his BeOS APlayer, and contributed many bug fixes. -- If your name is missing, don't hesitate to remind me at uqm-0.6.2/sc2/src/sc2code/libs/mikmod/npertab.c0000600000175000017500000000352010543202047017614 0ustar joeyjoey/* MikMod sound library (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id: npertab.c 2412 2006-08-18 18:37:39Z avolkov $ MOD format period table. Used by both the MOD and M15 (15-inst mod) Loaders. ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "mikmod_internals.h" UWORD npertab[7 * OCTAVE] = { /* Octaves 6 -> 0 */ /* C C# D D# E F F# G G# A A# B */ 0x6b0,0x650,0x5f4,0x5a0,0x54c,0x500,0x4b8,0x474,0x434,0x3f8,0x3c0,0x38a, 0x358,0x328,0x2fa,0x2d0,0x2a6,0x280,0x25c,0x23a,0x21a,0x1fc,0x1e0,0x1c5, 0x1ac,0x194,0x17d,0x168,0x153,0x140,0x12e,0x11d,0x10d,0x0fe,0x0f0,0x0e2, 0x0d6,0x0ca,0x0be,0x0b4,0x0aa,0x0a0,0x097,0x08f,0x087,0x07f,0x078,0x071, 0x06b,0x065,0x05f,0x05a,0x055,0x050,0x04b,0x047,0x043,0x03f,0x03c,0x038, 0x035,0x032,0x02f,0x02d,0x02a,0x028,0x025,0x023,0x021,0x01f,0x01e,0x01c, 0x01b,0x019,0x018,0x016,0x015,0x014,0x013,0x012,0x011,0x010,0x00f,0x00e }; /* ex:set ts=4: */ uqm-0.6.2/sc2/src/sc2code/libs/network/0000755000175000017500000000000010552600274016242 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/network/netport.h0000600000175000017500000000242510543202041020067 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETPORT_H #define _NETPORT_H #include "port.h" #ifdef USE_WINSOCK int winsockErrorToErrno(int winsockError); int getWinsockErrno(void); # define EAI_SYSTEM 0x02000001 // Any value will do that doesn't conflict with an existing value. #ifdef __MINGW32__ // MinGW does not have a working gai_strerror() yet. static inline const char * gai_strerror(int err) { (void) err; return "[gai_strerror() is not available on MinGW]"; } #endif /* defined(__MINGW32__) */ #endif #endif /* _NETPORT_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/netport.c0000600000175000017500000000626710543202041020072 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PORT_WANT_ERRNO #include "port.h" #include "netport.h" #ifdef USE_WINSOCK # include int winsockErrorToErrno(int winsockError) { switch (winsockError) { case WSAEINTR: return EINTR; case WSAEACCES: return EACCES; case WSAEFAULT: return EFAULT; case WSAEINVAL: return EINVAL; case WSAEMFILE: return EMFILE; case WSAEWOULDBLOCK: return EWOULDBLOCK; case WSAEINPROGRESS: return EINPROGRESS; case WSAEALREADY: return EALREADY; case WSAENOTSOCK: return ENOTSOCK; case WSAEDESTADDRREQ: return EDESTADDRREQ; case WSAEMSGSIZE: return EMSGSIZE; case WSAEPROTOTYPE: return EPROTOTYPE; case WSAENOPROTOOPT: return ENOPROTOOPT; case WSAEPROTONOSUPPORT: return EPROTONOSUPPORT; case WSAESOCKTNOSUPPORT: return ESOCKTNOSUPPORT; case WSAEOPNOTSUPP: return EOPNOTSUPP; case WSAEPFNOSUPPORT: return EPFNOSUPPORT; case WSAEAFNOSUPPORT: return EAFNOSUPPORT; case WSAEADDRINUSE: return EADDRINUSE; case WSAEADDRNOTAVAIL: return EADDRNOTAVAIL; case WSAENETDOWN: return ENETDOWN; case WSAENETUNREACH: return ENETUNREACH; case WSAENETRESET: return ENETRESET; case WSAECONNABORTED: return ECONNABORTED; case WSAECONNRESET: return ECONNRESET; case WSAENOBUFS: return ENOBUFS; case WSAEISCONN: return EISCONN; case WSAENOTCONN: return ENOTCONN; case WSAESHUTDOWN: return ESHUTDOWN; case WSAETIMEDOUT: return ETIMEDOUT; case WSAECONNREFUSED: return ECONNREFUSED; case WSAEHOSTDOWN: return EHOSTDOWN; case WSAEHOSTUNREACH: return EHOSTUNREACH; case WSAEPROCLIM: return EPROCLIM; case WSASYSNOTREADY: return ENOSYS; case WSAVERNOTSUPPORTED: return ENOSYS; case WSANOTINITIALISED: return ENOSYS; case WSAEDISCON: return ECONNRESET; case WSATYPE_NOT_FOUND: return ENODATA; case WSAHOST_NOT_FOUND: return ENODATA; case WSATRY_AGAIN: return EAGAIN; case WSANO_RECOVERY: return EIO; case WSANO_DATA: return ENODATA; case WSA_INVALID_HANDLE: return EBADF; case WSA_INVALID_PARAMETER: return EINVAL; case WSA_IO_INCOMPLETE: return EAGAIN; case WSA_IO_PENDING: return EINPROGRESS; case WSA_NOT_ENOUGH_MEMORY: return ENOMEM; case WSA_OPERATION_ABORTED: return EINTR; case WSAEINVALIDPROCTABLE: return ENOSYS; case WSAEINVALIDPROVIDER: return ENOSYS; case WSAEPROVIDERFAILEDINIT: return ENOSYS; case WSASYSCALLFAILURE: return EIO; default: return EIO; } } int getWinsockErrno(void) { return winsockErrorToErrno(WSAGetLastError()); } #endif /* defined (USE_WINSOCK) */ uqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/0000755000175000017500000000000010552600274020363 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/netmanager_win.c0000600000175000017500000003020010543202040023475 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PORT_WANT_ERRNO #include "port.h" #include "../netport.h" #define NETMANAGER_INTERNAL #define NETDESCRIPTOR_INTERNAL #define SOCKET_INTERNAL #include "netmanager_win.h" #include "../socket/socket.h" #include "ndesc.h" #include "types.h" #include "libs/misc.h" #include "libs/log.h" #include #include #include "netmanager_common.ci" int closeWSAEvent(WSAEVENT event); // The elements of the following arrays with the same index belong to // eachother. #define MAX_SOCKETS WSA_MAXIMUM_WAIT_EVENTS // We cannot have more sockets than we can have events, as // all may need an event at some point. static NetDescriptor *netDescriptors[MAX_SOCKETS]; static WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS]; static size_t numSockets; static size_t numActiveEvents; // For each NetDescriptor registered with the NetManager, an event // is created. Only the first numActiveEvents will be processed though. // Inv: numActiveEvents <= numSockets // Inv: for all i: 0 <= i < numActiveEvents: events[i] is active // (events[i] being active also means netDescriptor[i]->smd->eventMask // != 0) // Inv: for all i: 0 <= i < numSockets: netDescriptor[i]->smd->index == i void NetManager_init(void) { numActiveEvents = 0; } void NetManager_uninit(void) { assert(numActiveEvents == 0); } static inline SocketManagementDataWin * SocketManagementData_alloc(void) { return malloc(sizeof (SocketManagementDataWin)); } static inline void SocketManagementData_free(SocketManagementDataWin *smd) { free(smd); } // XXX: This function should be moved to some file with generic network // functions. int closeWSAEvent(WSAEVENT event) { for (;;) { int error; if (WSACloseEvent(event)) break; error = WSAGetLastError(); if (error != WSAEINPROGRESS) { log_add(log_Error, "WSACloseEvent() failed with error code %d.\n", error); errno = winsockErrorToErrno(error); return -1; } } return 0; } // Register the NetDescriptor with the NetManager. int NetManager_addDesc(NetDescriptor *nd) { long eventMask = 0; WSAEVENT event; if (numSockets >= WSA_MAXIMUM_WAIT_EVENTS) { errno = EMFILE; return -1; } if (nd->readCallback != NULL) eventMask |= FD_READ | FD_ACCEPT; if (nd->writeCallback != NULL) eventMask |= FD_WRITE /* | FD_CONNECT */; if (nd->exceptionCallback != NULL) eventMask |= FD_OOB; eventMask |= FD_CLOSE; event = WSACreateEvent(); if (event == WSA_INVALID_EVENT) { errno = getWinsockErrno(); return -1; } nd->smd = SocketManagementData_alloc(); if (eventMask != 0) { // XXX: This guard is now always true, because of FD_CLOSE. // This means that numActiveEvents will always be equal to // numEvents. // Once I'm convinced this is the right way to go, // I can remove some unnecessary code. if (WSAEventSelect(nd->socket->sock, event, eventMask) == SOCKET_ERROR) { int savedErrno = getWinsockErrno(); int closeStatus = closeWSAEvent(event); if (closeStatus == -1) { log_add(log_Fatal, "closeWSAEvent() failed: %s.\n", strerror(errno)); explode(); } SocketManagementData_free(nd->smd); errno = savedErrno; return -1; } // Move existing socket for which there exists no event, so // so that all sockets for which there exists an event are at // the front of the array of netdescriptors. if (numActiveEvents < numSockets) { netDescriptors[numSockets] = netDescriptors[numActiveEvents]; netDescriptors[numSockets]->smd->index = numSockets; } nd->smd->index = numActiveEvents; numActiveEvents++; } else { nd->smd->index = numSockets; } nd->smd->eventMask = eventMask; netDescriptors[nd->smd->index] = nd; events[nd->smd->index] = event; numSockets++; return 0; } void NetManager_removeDesc(NetDescriptor *nd) { assert(nd->smd != NULL); assert(nd->smd->index < numSockets); assert(nd == netDescriptors[nd->smd->index]); { int closeStatus = closeWSAEvent(events[nd->smd->index]); if (closeStatus == -1) explode(); } if (nd->smd->index < numActiveEvents) { size_t index = nd->smd->index; if (index + 1 != numActiveEvents) { // Keep the list of active events consecutive by filling // the new hole with the last active event. events[index] = events[numActiveEvents - 1]; netDescriptors[index] = netDescriptors[numActiveEvents - 1]; netDescriptors[index]->smd->index = index; } numActiveEvents--; } SocketManagementData_free(nd->smd); nd->smd = NULL; numSockets--; } static void swapSockets(int index1, int index2) { NetDescriptor *tempNd; WSAEVENT tempEvent; tempNd = netDescriptors[index2]; tempEvent = events[index2]; netDescriptors[index2] = netDescriptors[index1]; events[index2] = events[index1]; netDescriptors[index2]->smd->index = index2; netDescriptors[index1] = tempNd; events[index1] = tempEvent; netDescriptors[index1]->smd->index = index1; } static int NetManager_updateEvent(NetDescriptor *nd) { assert(nd == netDescriptors[nd->smd->index]); if (WSAEventSelect(nd->socket->sock, events[nd->smd->index], nd->smd->eventMask) == SOCKET_ERROR) { int savedErrno = getWinsockErrno(); int closeStatus = closeWSAEvent(events[nd->smd->index]); if (closeStatus == -1) { log_add(log_Fatal, "closeWSAEvent() failed: %s.\n", strerror(errno)); explode(); } errno = savedErrno; return -1; } if (nd->smd->eventMask != 0) { // There are some events that we are interested in. if (nd->smd->index >= numActiveEvents) { // Event was not yet active. if (nd->smd->index != numActiveEvents) { // Need to keep the active nds and events in the front of // their arrays. swapSockets(nd->smd->index, numActiveEvents); } numActiveEvents++; } } else { // There are no events that we are interested in. if (nd->smd->index < numActiveEvents) { // Event was active. if (nd->smd->index != numActiveEvents - 1) { // Need to keep the active nds and events in the front of // their arrays. swapSockets(nd->smd->index, numActiveEvents - 1); } } numActiveEvents--; } return 0; } static void activateSomeCallback(NetDescriptor *nd, long eventMask) { nd->smd->eventMask |= eventMask; { int status = NetManager_updateEvent(nd); if (status == -1) { log_add(log_Fatal, "NetManager_updateEvent() failed: %s.\n", strerror(errno)); explode(); // TODO: better error handling. } } } static void deactivateSomeCallback(NetDescriptor *nd, long eventMask) { nd->smd->eventMask &= ~eventMask; { int status = NetManager_updateEvent(nd); if (status == -1) { log_add(log_Fatal, "NetManager_updateEvent() failed: %s.\n", strerror(errno)); explode(); // TODO: better error handling } } } void NetManager_activateReadCallback(NetDescriptor *nd) { activateSomeCallback(nd, FD_READ | FD_ACCEPT); } void NetManager_deactivateReadCallback(NetDescriptor *nd) { deactivateSomeCallback(nd, FD_READ | FD_ACCEPT); } void NetManager_activateWriteCallback(NetDescriptor *nd) { activateSomeCallback(nd, FD_WRITE /* | FD_CONNECT */); } void NetManager_deactivateWriteCallback(NetDescriptor *nd) { deactivateSomeCallback(nd, FD_WRITE /* | FD_CONNECT */); } void NetManager_activateExceptionCallback(NetDescriptor *nd) { activateSomeCallback(nd, FD_OOB); } void NetManager_deactivateExceptionCallback(NetDescriptor *nd) { deactivateSomeCallback(nd, FD_OOB); } static inline int NetManager_processEvent(size_t index) { WSANETWORKEVENTS networkEvents; int enumRes; enumRes = WSAEnumNetworkEvents(netDescriptors[index]->socket->sock, events[index], &networkEvents); if (enumRes == SOCKET_ERROR) { errno = getWinsockErrno(); return -1; } if (networkEvents.lNetworkEvents & FD_READ) { bool closed; if (networkEvents.iErrorCode[FD_READ_BIT] != 0) { // No special handling is required; the callback function // will try to do a recv() and will get the error then. } closed = NetManager_doReadCallback(netDescriptors[index]); if (closed) goto closed; } if (networkEvents.lNetworkEvents & FD_WRITE) { bool closed; if (networkEvents.iErrorCode[FD_WRITE_BIT] != 0) { // No special handling is required; the callback function // will try to do a send() and will get the error then. } closed = NetManager_doWriteCallback(netDescriptors[index]); if (closed) goto closed; } if (networkEvents.lNetworkEvents & FD_OOB) { bool closed; if (networkEvents.iErrorCode[FD_OOB_BIT] != 0) { // No special handling is required; the callback function // will get the error then when it tries to do a recv(). } closed = NetManager_doExceptionCallback(netDescriptors[index]); if (closed) goto closed; } if (networkEvents.lNetworkEvents & FD_ACCEPT) { // There is no specific accept callback (because the BSD sockets // don't work with specific notification for accept); we use // the read callback instead. bool closed; if (networkEvents.iErrorCode[FD_READ_BIT] != 0) { // No special handling is required; the callback function // will try to do an accept() and will get the error then. } closed = NetManager_doReadCallback(netDescriptors[index]); if (closed) goto closed; } #if 0 // No need for this. Windows also sets FD_WRITE in this case, and // writability is what we check for anyhow. if (networkEvents.lNetworkEvents & FD_CONNECT) { // There is no specific connect callback (because the BSD sockets // don't work with specific notification for connect); we use // the write callback instead. bool closed; if (networkEvents.iErrorCode[FD_WRITE_BIT] != 0) { // No special handling is required; the callback function // should do getsockopt() with SO_ERROR to get the error. } closed = NetManager_doWriteCallback(netDescriptors[index]); if (closed) goto closed; } #endif if (networkEvents.lNetworkEvents & FD_CLOSE) { // The close event is handled last, in case there was still // data in the buffers which could be processed. NetDescriptor_close(netDescriptors[index]); goto closed; } closed: /* No special actions required for now. */ return 0; } // This function may be called again from inside a callback function // triggered by this function. BUG: This may result in callbacks being // called multiple times. // This function should however not be called from multiple threads at once. int NetManager_process(uint32 *timeoutMs) { DWORD timeoutTemp; DWORD waitResult; DWORD startEvent; timeoutTemp = (DWORD) *timeoutMs; // WSAWaitForMultipleEvents only reports events for one socket at a // time. In order to have each socket checked once, we call it // again after it has reported an event, but passing only the // events not yet processed. The second time, the timeout will be set // to 0, so it won't wait. startEvent = 0; while (startEvent < numActiveEvents) { waitResult = WSAWaitForMultipleEvents(numActiveEvents - startEvent, &events[startEvent], FALSE, timeoutTemp, FALSE); if (waitResult == WSA_WAIT_IO_COMPLETION) continue; if (waitResult == WSA_WAIT_TIMEOUT) { // No events waiting. *timeoutMs = 0; return 0; } if (waitResult == WSA_WAIT_FAILED) { errno = getWinsockErrno(); *timeoutMs = timeoutTemp; return -1; } { DWORD eventIndex = waitResult - WSA_WAIT_EVENT_0; if (NetManager_processEvent((size_t) eventIndex) == -1) { // errno is set *timeoutMs = timeoutTemp; return -1; } // Check the rest of the sockets, but don't wait anymore. startEvent += eventIndex + 1; timeoutTemp = 0; } } *timeoutMs = timeoutTemp; return 0; } uqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/ndindex.ci0000600000175000017500000000477710543202040022325 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // This file is part of netmanager_bsd.c, from where it is #included. // Only used for BSD sockets. // This file provides a mapping of Sockets to NetDescriptors. static NetDescriptor *netDescriptors[FD_SETSIZE]; // INV: flags.closed is not set for entries in netDescriptors. static size_t maxND; // One past the largest used ND in netDescriptors, as used in // the first argument of select(); static inline void NDIndex_init(void) { size_t i; size_t numND = sizeof (netDescriptors) / sizeof (netDescriptors[0]); for (i = 0; i < numND; i++) netDescriptors[i] = NULL; } static inline void NDIndex_uninit(void) { // Nothing to do. } static inline int NDIndex_registerNDWithSocket(Socket *sock, NetDescriptor *nd) { if ((unsigned int) sock->fd >= FD_SETSIZE) { errno = EMFILE; return -1; } netDescriptors[sock->fd] = nd; if ((size_t) sock->fd >= maxND) maxND = (size_t) sock->fd + 1; return 0; } static inline void NDIndex_unregisterNDForSocket(Socket *sock) { NetDescriptor **last; netDescriptors[sock->fd] = NULL; last = &netDescriptors[sock->fd]; if ((size_t) sock->fd + 1 == maxND) { do { maxND--; if (last == &netDescriptors[0]) break; last--; } while (*last == NULL); } } static inline NetDescriptor * NDIndex_getNDForSocket(Socket *sock) { assert((size_t) sock->fd < maxND); return netDescriptors[sock->fd]; } static inline NetDescriptor * NDIndex_getNDForSocketFd(int fd) { assert((size_t) fd < maxND); return netDescriptors[fd]; } static inline bool NDIndex_socketRegistered(Socket *sock) { return ((size_t) sock->fd < maxND) && (NDIndex_getNDForSocket(sock) != NULL); } // Get the first argument to be used in select(). static inline size_t NDIndex_getSelectNumND(void) { return maxND; } uqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/netmanager_win.h0000600000175000017500000000214710543202040023513 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETMANAGER_WIN_H #define _NETMANAGER_WIN_H typedef struct SocketManagementDataWin SocketManagementDataWin; typedef SocketManagementDataWin SocketManagementData; #ifdef NETMANAGER_INTERNAL struct SocketManagementDataWin { size_t index; long eventMask; }; #endif /* NETMANAGER_INTERNAL */ #endif /* _NETMANAGER_WIN_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/netmanager.h0000600000175000017500000000311210543202040022627 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETMANAGER_H #define _NETMANAGER_H #include "port.h" #include "types.h" #ifdef USE_WINSOCK # include "netmanager_win.h" #else # include "netmanager_bsd.h" #endif #include "ndesc.h" void NetManager_init(void); void NetManager_uninit(void); int NetManager_process(uint32 *timeoutMs); // Only for internal use by the NetManager: int NetManager_addDesc(NetDescriptor *nd); void NetManager_removeDesc(NetDescriptor *nd); void NetManager_activateReadCallback(NetDescriptor *nd); void NetManager_deactivateReadCallback(NetDescriptor *nd); void NetManager_activateWriteCallback(NetDescriptor *nd); void NetManager_deactivateWriteCallback(NetDescriptor *nd); void NetManager_activateExceptionCallback(NetDescriptor *nd); void NetManager_deactivateExceptionCallback(NetDescriptor *nd); #endif /* _NETMANAGER_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/netmanager_bsd.h0000600000175000017500000000174310543202040023467 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETMANAGER_BSD_H #define _NETMANAGER_BSD_H typedef struct SocketManagementDataBsd SocketManagementDataBsd; typedef SocketManagementDataBsd SocketManagementData; #endif /* _NETMANAGER_BSD_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/netmanager_bsd.c0000600000175000017500000001216410543202040023461 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define SOCKET_INTERNAL #define NETDESCRIPTOR_INTERNAL #include "netmanager_bsd.h" #include "ndesc.h" #include "../socket/socket.h" #include "ndesc.h" #include "types.h" #include "libs/log.h" #include #include #include #include #include "netmanager_common.ci" #include "ndindex.ci" // INV: The following sets only contain sockets present in the netDescriptor // array. static fd_set readSet; static fd_set writeSet; static fd_set exceptionSet; void NetManager_init(void) { NDIndex_init(); FD_ZERO(&readSet); FD_ZERO(&writeSet); FD_ZERO(&exceptionSet); } void NetManager_uninit(void) { NDIndex_uninit(); } // Register the NetDescriptor with the NetManager. int NetManager_addDesc(NetDescriptor *nd) { int fd; assert(nd->socket != Socket_noSocket); assert(!NDIndex_socketRegistered(nd->socket)); if (NDIndex_registerNDWithSocket(nd->socket, nd) == -1) { // errno is set return -1; } fd = nd->socket->fd; if (nd->readCallback != NULL) FD_SET(fd, &readSet); if (nd->writeCallback != NULL) FD_SET(fd, &writeSet); if (nd->exceptionCallback != NULL) FD_SET(fd, &exceptionSet); return 0; } void NetManager_removeDesc(NetDescriptor *nd) { int fd; assert(nd->socket != Socket_noSocket); assert(NDIndex_getNDForSocket(nd->socket) == nd); fd = nd->socket->fd; FD_CLR(fd, &readSet); FD_CLR(fd, &writeSet); FD_CLR(fd, &exceptionSet); NDIndex_unregisterNDForSocket(nd->socket); } void NetManager_activateReadCallback(NetDescriptor *nd) { FD_SET(nd->socket->fd, &readSet); } void NetManager_deactivateReadCallback(NetDescriptor *nd) { FD_CLR(nd->socket->fd, &readSet); } void NetManager_activateWriteCallback(NetDescriptor *nd) { FD_SET(nd->socket->fd, &writeSet); } void NetManager_deactivateWriteCallback(NetDescriptor *nd) { FD_CLR(nd->socket->fd, &writeSet); } void NetManager_activateExceptionCallback(NetDescriptor *nd) { FD_SET(nd->socket->fd, &exceptionSet); } void NetManager_deactivateExceptionCallback(NetDescriptor *nd) { FD_CLR(nd->socket->fd, &exceptionSet); } // This function may be called again from inside a callback function // triggered by this function. BUG: This may result in callbacks being // called multiple times. // This function should however not be called from multiple threads at once. int NetManager_process(uint32 *timeoutMs) { struct timeval timeout; size_t i; int selectResult; fd_set newReadSet; fd_set newWriteSet; fd_set newExceptionSet; bool bitSet; timeout.tv_sec = *timeoutMs / 1000; timeout.tv_usec = (*timeoutMs % 1000) * 1000; // Structure assignment: newReadSet = readSet; newWriteSet = writeSet; newExceptionSet = exceptionSet; do { selectResult = select(NDIndex_getSelectNumND(), &newReadSet, &newWriteSet, &newExceptionSet, &timeout); // BUG: If select() is restarted because of EINTR, the timeout // may start over. (Linux changes 'timeout' to the time left, // but most other platforms don't.) } while (selectResult == -1 && errno == EINTR); if (selectResult == -1) { int savedErrno = errno; log_add(log_Error, "select() failed: %s.\n", strerror(errno)); errno = savedErrno; *timeoutMs = (timeout.tv_sec * 1000) + (timeout.tv_usec / 1000); // XXX: rounding microseconds down. Is that the correct // thing to do? return -1; } for (i = 0; i < maxND; i++) { NetDescriptor *nd; if (selectResult == 0) { // No more bits set in the fd_sets break; } nd = NDIndex_getNDForSocketFd(i); if (nd == NULL) continue; bitSet = false; // Is one of the bits in the fd_sets set? // A callback may cause a NetDescriptor to be closed. The deletion // of the structure will be scheduled, but will still be // available at least until this function returns. if (FD_ISSET(i, &newExceptionSet)) { bool closed; bitSet = true; closed = NetManager_doExceptionCallback(nd); if (closed) goto next; } if (FD_ISSET(i, &newWriteSet)) { bool closed; bitSet = true; closed = NetManager_doWriteCallback(nd); if (closed) goto next; } if (FD_ISSET(i, &newReadSet)) { bool closed; bitSet = true; closed = NetManager_doReadCallback(nd); if (closed) goto next; } next: if (bitSet) selectResult--; } *timeoutMs = (timeout.tv_sec * 1000) + (timeout.tv_usec / 1000); // XXX: rounding microseconds down. Is that the correct // thing to do? return 0; } uqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/ndesc.h0000644000175000017500000000523110545477400021636 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NDESC_H #define _NDESC_H #include "types.h" typedef struct NetDescriptor NetDescriptor; typedef void (*NetDescriptor_ReadCallback)(NetDescriptor *nd); typedef void (*NetDescriptor_WriteCallback)(NetDescriptor *nd); typedef void (*NetDescriptor_ExceptionCallback)(NetDescriptor *nd); typedef void (*NetDescriptor_CloseCallback)(NetDescriptor *nd); typedef uint32 RefCount; #define REFCOUNT_MAX UINT32_MAX #include "../socket/socket.h" #include "netmanager.h" #ifdef NETDESCRIPTOR_INTERNAL // All created NetDescriptors are registered to the NetManager. // They are unregisted when the NetDescriptor is closed. // On creation the ref count is set to 1. On close it is decremented by 1. struct NetDescriptor { struct { bool closed: 1; } flags; RefCount refCount; NetDescriptor_ReadCallback readCallback; NetDescriptor_WriteCallback writeCallback; NetDescriptor_ExceptionCallback exceptionCallback; NetDescriptor_CloseCallback closeCallback; Socket *socket; SocketManagementData *smd; // Extra state-dependant information for the user. void *extra; }; #endif NetDescriptor *NetDescriptor_new(Socket *socket, void *extra); void NetDescriptor_close(NetDescriptor *nd); void NetDescriptor_incRef(NetDescriptor *nd); bool NetDescriptor_decRef(NetDescriptor *nd); void NetDescriptor_detach(NetDescriptor *nd); Socket *NetDescriptor_getSocket(NetDescriptor *nd); void NetDescriptor_setExtra(NetDescriptor *nd, void *extra); void *NetDescriptor_getExtra(const NetDescriptor *nd); void NetDescriptor_setReadCallback(NetDescriptor *nd, NetDescriptor_ReadCallback callback); void NetDescriptor_setWriteCallback(NetDescriptor *nd, NetDescriptor_WriteCallback callback); void NetDescriptor_setExceptionCallback(NetDescriptor *nd, NetDescriptor_ExceptionCallback callback); void NetDescriptor_setCloseCallback(NetDescriptor *nd, NetDescriptor_CloseCallback callback); #endif /* _NDESC_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/ndesc.c0000644000175000017500000001205410545477400021632 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define NETDESCRIPTOR_INTERNAL #include "ndesc.h" #include "netmanager.h" #include "libs/callback.h" #include #include #include #undef DEBUG_NETDESCRIPTOR_REF #ifdef DEBUG_NETDESCRIPTOR_REF # include "libs/log.h" # include #endif static NetDescriptor * NetDescriptor_alloc(void) { return malloc(sizeof (NetDescriptor)); } static void NetDescriptor_free(NetDescriptor *nd) { free(nd); } // Sets the ref count to 1. NetDescriptor * NetDescriptor_new(Socket *socket, void *extra) { NetDescriptor *nd; nd = NetDescriptor_alloc(); nd->refCount = 1; #ifdef DEBUG_NETDESCRIPTOR_REF log_add(log_Debug, "NetDescriptor %08" PRIxPTR ": ref=1 (%d)\n", (uintptr_t) nd, nd->refCount); #endif nd->flags.closed = false; nd->readCallback = NULL; nd->writeCallback = NULL; nd->exceptionCallback = NULL; nd->closeCallback = NULL; nd->socket = socket; nd->smd = NULL; nd->extra = extra; if (NetManager_addDesc(nd) == -1) { int savedErrno = errno; NetDescriptor_free(nd); errno = savedErrno; return NULL; } return nd; } static void NetDescriptor_delete(NetDescriptor *nd) { assert(nd->socket == Socket_noSocket); assert(nd->smd == NULL); NetDescriptor_free(nd); } // Called from the callback handler. static void NetDescriptor_closeCallback(NetDescriptor *nd) { if (nd->closeCallback != NULL) { // The check is necessary because the close callback may have // been removed before it is triggered. (*nd->closeCallback)(nd); } NetDescriptor_decRef(nd); } void NetDescriptor_close(NetDescriptor *nd) { assert(!nd->flags.closed); assert(nd->socket != Socket_noSocket); NetManager_removeDesc(nd); (void) Socket_close(nd->socket); nd->socket = Socket_noSocket; nd->flags.closed = true; if (nd->closeCallback != NULL) { // Keep one reference around until the close callback has been // called. (void) Callback_add( (CallbackFunction) NetDescriptor_closeCallback, (CallbackArg) nd); } else NetDescriptor_decRef(nd); } void NetDescriptor_incRef(NetDescriptor *nd) { assert(nd->refCount < REFCOUNT_MAX); nd->refCount++; #ifdef DEBUG_NETDESCRIPTOR_REF log_add(log_Debug, "NetDescriptor %08" PRIxPTR ": ref++ (%d)\n", (uintptr_t) nd, nd->refCount); #endif } // returns true iff the ref counter has reached 0. bool NetDescriptor_decRef(NetDescriptor *nd) { assert(nd->refCount > 0); nd->refCount--; #ifdef DEBUG_NETDESCRIPTOR_REF log_add(log_Debug, "NetDescriptor %08" PRIxPTR ": ref-- (%d)\n", (uintptr_t) nd, nd->refCount); #endif if (nd->refCount == 0) { NetDescriptor_delete(nd); return true; } return false; } // The socket will no longer be managed by the NetManager. void NetDescriptor_detach(NetDescriptor *nd) { NetManager_removeDesc(nd); nd->socket = Socket_noSocket; nd->flags.closed = true; NetDescriptor_decRef(nd); } Socket * NetDescriptor_getSocket(NetDescriptor *nd) { return nd->socket; } void NetDescriptor_setExtra(NetDescriptor *nd, void *extra) { nd->extra = extra; } void * NetDescriptor_getExtra(const NetDescriptor *nd) { return nd->extra; } void NetDescriptor_setReadCallback(NetDescriptor *nd, NetDescriptor_ReadCallback callback) { nd->readCallback = callback; if (!nd->flags.closed) { if (nd->readCallback != NULL) { NetManager_activateReadCallback(nd); } else NetManager_deactivateReadCallback(nd); } } void NetDescriptor_setWriteCallback(NetDescriptor *nd, NetDescriptor_WriteCallback callback) { nd->writeCallback = callback; if (!nd->flags.closed) { if (nd->writeCallback != NULL) { NetManager_activateWriteCallback(nd); } else NetManager_deactivateWriteCallback(nd); } } void NetDescriptor_setExceptionCallback(NetDescriptor *nd, NetDescriptor_ExceptionCallback callback) { nd->exceptionCallback = callback; if (!nd->flags.closed) { if (nd->exceptionCallback != NULL) { NetManager_activateExceptionCallback(nd); } else NetManager_deactivateExceptionCallback(nd); } } // The close callback is called as a result of a socket being closed, either // because of a local command or a remote disconnect. // The close callback will only be scheduled when this happens. The // callback will not be called until the Callback_process() is called. void NetDescriptor_setCloseCallback(NetDescriptor *nd, NetDescriptor_CloseCallback callback) { nd->closeCallback = callback; } uqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/Makeinfo0000600000175000017500000000023010543202040022007 0ustar joeyjoeyuqm_CFILES="ndesc.c" if [ -n "$uqm_USE_WINSOCK" ]; then uqm_CFILES="$uqm_CFILES netmanager_win.c" else uqm_CFILES="$uqm_CFILES netmanager_bsd.c" fi uqm-0.6.2/sc2/src/sc2code/libs/network/netmanager/netmanager_common.ci0000600000175000017500000000311610543202040024347 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // This file is part of netmanager_bsd.ci and netmanager_win.ci, // from where it is #included. static bool NetManager_doReadCallback(NetDescriptor *nd) { bool closed; assert(nd->readCallback != NULL); NetDescriptor_incRef(nd); (*nd->readCallback)(nd); closed = nd->flags.closed; NetDescriptor_decRef(nd); return closed; } static bool NetManager_doWriteCallback(NetDescriptor *nd) { bool closed; assert(nd->writeCallback != NULL); NetDescriptor_incRef(nd); (*nd->writeCallback)(nd); closed = nd->flags.closed; NetDescriptor_decRef(nd); return closed; } static bool NetManager_doExceptionCallback(NetDescriptor *nd) { bool closed; assert(nd->exceptionCallback != NULL); NetDescriptor_incRef(nd); (*nd->exceptionCallback)(nd); closed = nd->flags.closed; NetDescriptor_decRef(nd); return closed; } uqm-0.6.2/sc2/src/sc2code/libs/network/network_bsd.c0000600000175000017500000000161610543202041020711 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "network.h" void Network_init(void) { // Nothing to do. } void Network_uninit(void) { // Nothing to do. } uqm-0.6.2/sc2/src/sc2code/libs/network/wspiapiwrap.h0000600000175000017500000000250310543202041020737 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _WSPIAPIWRAP_H #define _WSPIAPIWRAP_H // HACK. See wspiapiwrap.c # define getaddrinfo WspiapiGetAddrInfo # define getnameinfo WspiapiGetNameInfo # define freeaddrinfo WspiapiFreeAddrInfo void WINAPI WspiapiFreeAddrInfo (struct addrinfo *ai); int WINAPI WspiapiGetAddrInfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res); int WINAPI WspiapiGetNameInfo (const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); #endif /* _WSPIAPIWRAP_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/wspiapiwrap.c0000600000175000017500000000242410543202041020734 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // Only used for MinGW // HACK. MinGW misses some functionality, so we're #including // the actual Windows wspiapi.h file. Because that file includes // inline functions that aren't static, it can only be included // once per executable when using gcc (for MSVC this is apparently // not a problem), so this file is it. The prototypes of these // functions are added to wspiapiwrap.h #include "netport.h" #if defined(USE_WINSOCK) && defined(__MINGW32__) # include # include #endif uqm-0.6.2/sc2/src/sc2code/libs/network/connect/0000755000175000017500000000000010552600274017673 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/network/connect/connect.h0000600000175000017500000000651010543202041021455 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CONNECT_CONNECT_H #define _CONNECT_CONNECT_H typedef struct ConnectFlags ConnectFlags; typedef struct ConnectError ConnectError; typedef struct ConnectState ConnectState; typedef enum { Connect_closed, Connect_resolving, Connect_connecting } ConnectStateState; #include "../netmanager/netmanager.h" #include "../socket/socket.h" #include "resolve.h" // For connectHost() struct ConnectFlags { ProtocolFamily familyDemand; // Only accept a protocol family of this type. // One of PF_inet, PF_inet6, or PF_unspec. ProtocolFamily familyPrefer; // Prefer a protocol family of this type. // One of PF_inet, PF_inet6, or PF_unspec. int timeout; /* Number of milliseconds before timing out a connection attempt. * Note that if a host has multiple addresses, a connect to that * host will have this timeout *per address*. */ int retryDelayMs; /* Retry connecting this many ms after connecting to the last * address for the specified host fails. Set to Connect_noRetry * to give up after one try. */ #define Connect_noRetry -1 }; struct ConnectError { ConnectStateState state; // State where the error occured. int err; // errno value. Not relevant if state == resolving unless // gaiRes == EAI_SYSTEM. const ResolveError *resolveError; // Only relevant if state == resolving. }; typedef void (*ConnectConnectCallback)(ConnectState *connectState, NetDescriptor *nd, const struct sockaddr *addr, socklen_t addrLen); typedef void (*ConnectErrorCallback)(ConnectState *connectState, const ConnectError *error); #ifdef CONNECT_INTERNAL #include "libs/alarm.h" struct ConnectState { RefCount refCount; ConnectStateState state; ConnectFlags flags; ConnectConnectCallback connectCallback; ConnectErrorCallback errorCallback; void *extra; struct addrinfo *info; struct addrinfo *infoPtr; ResolveState *resolveState; NetDescriptor *nd; Alarm *alarm; // Used for both the timeout for a connection attempt // and to retry after all addresses have been tried. }; #endif /* CONNECT_INTERNAL */ ConnectState *connectHostByName(const char *host, const char *service, Protocol proto, const ConnectFlags *flags, ConnectConnectCallback connectCallback, ConnectErrorCallback errorCallback, void *extra); void ConnectState_incRef(ConnectState *connectState); bool ConnectState_decRef(ConnectState *connectState); void ConnectState_close(ConnectState *connectState); void ConnectState_setExtra(ConnectState *connectState, void *extra); void *ConnectState_getExtra(ConnectState *connectState); #endif /* _CONNECT_CONNECT_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/connect/resolve.c0000600000175000017500000001432110543202041021475 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define RESOLVE_INTERNAL #include "resolve.h" #include #include #include #define DEBUG_RESOLVE_REF #ifdef DEBUG_RESOLVE_REF # include "types.h" # include "libs/log.h" # include #endif static ResolveState * ResolveState_new(void) { return (ResolveState *) malloc(sizeof (ResolveState)); }; static void ResolveState_free(ResolveState *resolveState) { free(resolveState); } static void ResolveState_delete(ResolveState *resolveState) { assert(resolveState->callbackID == CallbackID_invalid); ResolveState_free(resolveState); } void ResolveState_incRef(ResolveState *resolveState) { assert(resolveState->refCount < REFCOUNT_MAX); resolveState->refCount++; #ifdef DEBUG_RESOLVE_REF log_add(log_Debug, "ResolveState %08" PRIxPTR ": ref++ (%d)\n", (uintptr_t) resolveState, resolveState->refCount); #endif } bool ResolveState_decRef(ResolveState *resolveState) { assert(resolveState->refCount > 0); resolveState->refCount--; #ifdef DEBUG_RESOLVE_REF log_add(log_Debug, "ResolveState %08" PRIxPTR ": ref-- (%d)\n", (uintptr_t) resolveState, resolveState->refCount); #endif if (resolveState->refCount == 0) { ResolveState_delete(resolveState); return true; } return false; } void ResolveState_setExtra(ResolveState *resolveState, void *extra) { resolveState->extra = extra; } void * ResolveState_getExtra(ResolveState *resolveState) { return resolveState->extra; } static void doResolveCallback(ResolveState *resolveState) { ResolveState_incRef(resolveState); (*resolveState->callback)(resolveState, resolveState->result); { bool released = ResolveState_decRef(resolveState); assert(released); (void) released; // In case assert() evaluates to nothing. } } static void doResolveErrorCallback(ResolveState *resolveState) { ResolveState_incRef(resolveState); resolveState->errorCallback(resolveState, &resolveState->error); { bool released = ResolveState_decRef(resolveState); assert(released); (void) released; // In case assert() evaluates to nothing. } } static void resolveCallback(ResolveState *resolveState) { resolveState->callbackID = CallbackID_invalid; if (resolveState->error.gaiRes == 0) { // Successful lookup. doResolveCallback(resolveState); } else { // Lookup failed. doResolveErrorCallback(resolveState); } } // Function that does getaddrinfo() and calls the callback function when // the result is available. // TODO: actually make this function asynchronous. Right now it just calls // getaddrinfo() (which blocks) and then schedules the callback. ResolveState * getaddrinfoAsync(const char *node, const char *service, const struct addrinfo *hints, ResolveFlags *flags, ResolveCallback callback, ResolveErrorCallback errorCallback, ResolveCallbackArg extra) { ResolveState *resolveState; resolveState = ResolveState_new(); resolveState->refCount = 1; #ifdef DEBUG_RESOLVE_REF log_add(log_Debug, "ResolveState %08" PRIxPTR ": ref=1 (%d)\n", (uintptr_t) resolveState, resolveState->refCount); #endif resolveState->state = Resolve_resolving; resolveState->flags = *flags; resolveState->callback = callback; resolveState->errorCallback = errorCallback; resolveState->extra = extra; resolveState->result = NULL; resolveState->error.gaiRes = getaddrinfo(node, service, hints, &resolveState->result); resolveState->error.err = errno; resolveState->callbackID = Callback_add( (CallbackFunction) resolveCallback, (CallbackArg) resolveState); return resolveState; } void Resolve_close(ResolveState *resolveState) { if (resolveState->callbackID != CallbackID_invalid) { Callback_remove(resolveState->callbackID); resolveState->callbackID = CallbackID_invalid; } resolveState->state = Resolve_closed; ResolveState_decRef(resolveState); } // Split an addrinfo list into two separate lists, one with structures with // the specified value for the ai_family field, the other with the other // structures. The order of entries in the resulting lists will remain // the same as in the original list. // info - the original list // family - the family for the first list // selected - pointer to where the list of selected structures should be // stored // selectedEnd - pointer to where the end of 'selected' should be stored // rest - pointer to where the list of not-selected structures should be // stored // restEnd - pointer to where the end of 'rest' should be stored // // Yes, it is allowed to modify the ai_next field of addrinfo structures. // Or at least, it's not disallowed by RFC 3493, and the following // text from that RFC seems to suggest it should be possible: // ] The freeaddrinfo() function must support the freeing of arbitrary // ] sublists of an addrinfo list originally returned by getaddrinfo(). void splitAddrInfoOnFamily(struct addrinfo *info, int family, struct addrinfo **selected, struct addrinfo ***selectedEnd, struct addrinfo **rest, struct addrinfo ***restEnd) { struct addrinfo *selectedFirst; struct addrinfo **selectedNext; struct addrinfo *restFirst; struct addrinfo **restNext; selectedNext = &selectedFirst; restNext = &restFirst; while (info != NULL) { if (info->ai_family == family) { *selectedNext = info; selectedNext = &(*selectedNext)->ai_next; } else { *restNext = info; restNext = &(*restNext)->ai_next; } info = info->ai_next; } *selectedNext = NULL; *restNext = NULL; // Fill in the result parameters. *selected = selectedFirst; *selectedEnd = selectedNext; *rest = restFirst; *restEnd = restNext; } uqm-0.6.2/sc2/src/sc2code/libs/network/connect/listen.h0000600000175000017500000000623610543202041021327 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CONNECT_LISTEN_H #define _CONNECT_LISTEN_H typedef struct ListenFlags ListenFlags; typedef enum { Listen_closed, Listen_resolving, Listen_listening } ListenStateState; typedef struct ListenError ListenError; typedef struct ListenState ListenState; #include "port.h" #ifdef USE_WINSOCK // I do not want to include winsock2.h, because of possible conflicts with // code that includes this file. // Note that listen.c itself includes winsock2.h; SOCKLEN_T is used there // only where necessary to keep the API consistent. # define SOCKLEN_T size_t struct sockaddr; #else # include # define SOCKLEN_T socklen_t #endif #include "resolve.h" #include "../socket/socket.h" #include "../netmanager/netmanager.h" // For listenPort() struct ListenFlags { ProtocolFamily familyDemand; // Only accept a protocol family of this type. // One of PF_inet, PF_inet6, or PF_unspec. ProtocolFamily familyPrefer; // Prefer a protocol family of this type. // One of PF_inet, PF_inet6, or PF_unspec. int backlog; // As the 2rd parameter to listen(); }; struct ListenError { ListenStateState state; // State where the error occured. int err; // errno value. Not relevant if state == resolving unless // gaiRes == EAI_SYSTEM. const ResolveError *resolveError; // Only relevant if state == resolving. }; typedef void (*ListenConnectCallback)(ListenState *listenState, NetDescriptor *listenNd, NetDescriptor *newNd, const struct sockaddr *addr, SOCKLEN_T addrLen); typedef void (*ListenErrorCallback)(ListenState *listenState, const ListenError *error); #ifdef LISTEN_INTERNAL struct ListenState { RefCount refCount; ListenStateState state; ListenFlags flags; ListenConnectCallback connectCallback; ListenErrorCallback errorCallback; void *extra; ResolveState *resolveState; NetDescriptor **nds; size_t numNd; // INV: (numNd == NULL) == (nds == NULL) }; #endif /* defined(LISTEN_INTERNAL) */ ListenState *listenPort(const char *service, Protocol proto, const ListenFlags *flags, ListenConnectCallback connectCallback, ListenErrorCallback errorCallback, void *extra); void ListenState_close(ListenState *listenState); void ListenState_incRef(ListenState *listenState); bool ListenState_decRef(ListenState *listenState); void ListenState_setExtra(ListenState *listenState, void *extra); void *ListenState_getExtra(ListenState *listenState); #endif /* _CONNECT_LISTEN_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/connect/listen.c0000600000175000017500000003063610543202041021323 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PORT_WANT_ERRNO #include "port.h" #include "../netport.h" #define LISTEN_INTERNAL #define SOCKET_INTERNAL #include "listen.h" #include "resolve.h" #include "../socket/socket.h" #include "../netmanager/netmanager.h" #include "libs/misc.h" #include "libs/log.h" #include #include #ifdef USE_WINSOCK # include # include # include "../wspiapiwrap.h" #else # include #endif #include #include #define DEBUG_LISTEN_REF #ifdef DEBUG_LISTEN_REF # include "types.h" #endif static void acceptCallback(NetDescriptor *nd); static void doListenErrorCallback(ListenState *listenState, const ListenError *error); static ListenState * ListenState_alloc(void) { return (ListenState *) malloc(sizeof (ListenState)); }; static void ListenState_free(ListenState *listenState) { free(listenState); } static void ListenState_delete(ListenState *listenState) { assert(listenState->nds == NULL); ListenState_free(listenState); } void ListenState_incRef(ListenState *listenState) { assert(listenState->refCount < REFCOUNT_MAX); listenState->refCount++; #ifdef DEBUG_LISTEN_REF log_add(log_Debug, "ListenState %08" PRIxPTR ": ref++ (%d)\n", (uintptr_t) listenState, listenState->refCount); #endif } bool ListenState_decRef(ListenState *listenState) { assert(listenState->refCount > 0); listenState->refCount--; #ifdef DEBUG_LISTEN_REF log_add(log_Debug, "ListenState %08" PRIxPTR ": ref-- (%d)\n", (uintptr_t) listenState, listenState->refCount); #endif if (listenState->refCount == 0) { ListenState_delete(listenState); return true; } return false; } // Decrements ref count byh 1 void ListenState_close(ListenState *listenState) { if (listenState->resolveState != NULL) { Resolve_close(listenState->resolveState); listenState->resolveState = NULL; } if (listenState->nds != NULL) { while (listenState->numNd > 0) { listenState->numNd--; NetDescriptor_close(listenState->nds[listenState->numNd]); } free(listenState->nds); listenState->nds = NULL; } listenState->state = Listen_closed; ListenState_decRef(listenState); } void ListenState_setExtra(ListenState *listenState, void *extra) { listenState->extra = extra; } void * ListenState_getExtra(ListenState *listenState) { return listenState->extra; } static NetDescriptor * listenPortSingle(struct ListenState *listenState, struct addrinfo *info) { Socket *sock; int bindResult; int listenResult; NetDescriptor *nd; sock = Socket_openNative(info->ai_family, info->ai_socktype, info->ai_protocol); if (sock == Socket_noSocket) { int savedErrno = errno; log_add(log_Error, "socket() failed: %s.\n", strerror(errno)); errno = savedErrno; return NULL; } (void) Socket_setReuseAddr(sock); // Ignore errors; it's not a big deal. if (Socket_setNonBlocking(sock) == -1) { int savedErrno = errno; // Error message is already printed. Socket_close(sock); errno = savedErrno; return NULL; } bindResult = Socket_bind(sock, info->ai_addr, info->ai_addrlen); if (bindResult == -1) { int savedErrno = errno; if (errno == EADDRINUSE) { #ifdef DEBUG log_add(log_Warning, "bind() failed: %s.\n", strerror(errno)); #endif } else log_add(log_Error, "bind() failed: %s.\n", strerror(errno)); Socket_close(sock); errno = savedErrno; return NULL; } listenResult = Socket_listen(sock, listenState->flags.backlog); if (listenResult == -1) { int savedErrno = errno; log_add(log_Error, "listen() failed: %s.\n", strerror(errno)); Socket_close(sock); errno = savedErrno; return NULL; } nd = NetDescriptor_new(sock, (void *) listenState); if (nd == NULL) { int savedErrno = errno; log_add(log_Error, "NetDescriptor_new() failed: %s.\n", strerror(errno)); Socket_close(sock); errno = savedErrno; return NULL; } NetDescriptor_setReadCallback(nd, acceptCallback); return nd; } static void listenPortMulti(struct ListenState *listenState, struct addrinfo *info) { struct addrinfo *addrPtr; size_t addrCount; size_t addrOkCount; NetDescriptor **nds; // Count how many addresses we've got. addrCount = 0; for (addrPtr = info; addrPtr != NULL; addrPtr = addrPtr->ai_next) addrCount++; // This is where we intend to store the file descriptors of the // listening sockets. nds = malloc(addrCount * sizeof listenState->nds[0]); // Bind to each address. addrOkCount = 0; for (addrPtr = info; addrPtr != NULL; addrPtr = addrPtr->ai_next) { NetDescriptor *nd; nd = listenPortSingle(listenState, addrPtr); if (nd == NULL) { // Failed. On to the next. // An error message is already printed for serious errors. // If the address is already in use, we here also print // a message when we are not already listening on one of // the other addresses. // This is because on some IPv6 capabable systems (like Linux), // IPv6 sockets also handle IPv4 connections, which means // that a separate IPv4 socket won't be able to bind to the // port. // BUG: if the IPv4 socket is in the list before the // IPv6 socket, it will be the IPv6 which will fail to bind, // so only IPv4 connections will be handled, as v4 sockets can't // accept v6 connections. // In practice, on Linux, I haven't seen it happen, but // it's a real possibility. if (errno == EADDRINUSE && addrOkCount == 0) { log_add(log_Error, "Error while preparing a network socket " "for incoming connections: %s\n", strerror(errno)); } continue; } nds[addrOkCount] = nd; addrOkCount++; } freeaddrinfo(info); listenState->nds = realloc(nds, addrOkCount * sizeof listenState->nds[0]); listenState->numNd = addrOkCount; if (addrOkCount == 0) { // Could not listen on any port. ListenError error; error.state = Listen_listening; error.err = EIO; // Nothing better to offer. doListenErrorCallback(listenState, &error); return; } } static void listenPortResolveCallback(ResolveState *resolveState, struct addrinfo *result) { ListenState *listenState = (ListenState *) ResolveState_getExtra(resolveState); Resolve_close(listenState->resolveState); listenState->resolveState = NULL; listenState->state = Listen_listening; listenPortMulti(listenState, result); } static void listenPortResolveErrorCallback(ResolveState *resolveState, const ResolveError *resolveError) { ListenState *listenState = (ListenState *) ResolveState_getExtra(resolveState); ListenError listenError; assert(resolveError->gaiRes != 0); listenError.state = Listen_resolving; listenError.resolveError = resolveError; listenError.err = resolveError->err; doListenErrorCallback(listenState, &listenError); } // 'proto' is one of IPProto_tcp or IPProto_udp. ListenState * listenPort(const char *service, Protocol proto, const ListenFlags *flags, ListenConnectCallback connectCallback, ListenErrorCallback errorCallback, void *extra) { struct addrinfo hints; ListenState *listenState; ResolveFlags resolveFlags; // Structure is empty (for now). assert(flags->familyDemand == PF_inet || flags->familyDemand == PF_inet6 || flags->familyDemand == PF_unspec); assert(flags->familyPrefer == PF_inet || flags->familyPrefer == PF_inet6 || flags->familyPrefer == PF_unspec); assert(proto == IPProto_tcp || proto == IPProto_udp); // Acquire a list of addresses to bind to. memset(&hints, '\0', sizeof hints); hints.ai_family = protocolFamilyTranslation[flags->familyDemand]; hints.ai_protocol = protocolTranslation[proto]; if (proto == IPProto_tcp) { hints.ai_socktype = SOCK_STREAM; } else { assert(proto == IPProto_udp); hints.ai_socktype = SOCK_DGRAM; } hints.ai_flags = AI_PASSIVE; listenState = ListenState_alloc(); listenState->refCount = 1; #ifdef DEBUG_LISTEN_REF log_add(log_Debug, "ListenState %08" PRIxPTR ": ref=1 (%d)\n", (uintptr_t) listenState, listenState->refCount); #endif listenState->state = Listen_resolving; listenState->flags = *flags; listenState->connectCallback = connectCallback; listenState->errorCallback = errorCallback; listenState->extra = extra; listenState->nds = NULL; listenState->numNd = 0; listenState->resolveState = getaddrinfoAsync(NULL, service, &hints, &resolveFlags, listenPortResolveCallback, listenPortResolveErrorCallback, (ResolveCallbackArg) listenState); return listenState; } // NB: The callback function becomes the owner of newNd. static void doListenConnectCallback(ListenState *listenState, NetDescriptor *listenNd, NetDescriptor *newNd, const struct sockaddr *addr, SOCKLEN_T addrLen) { assert(listenState->connectCallback != NULL); ListenState_incRef(listenState); // No need to increment listenNd, as there's guaranteed to be one // reference from listenState. And no need to increment newNd, // as the callback function takes over ownership. (*listenState->connectCallback)(listenState, listenNd, newNd, addr, (socklen_t) addrLen); ListenState_decRef(listenState); } static void doListenErrorCallback(ListenState *listenState, const ListenError *error) { assert(listenState->errorCallback != NULL); ListenState_incRef(listenState); (*listenState->errorCallback)(listenState, error); ListenState_decRef(listenState); } static void acceptSingleConnection(ListenState *listenState, NetDescriptor *nd) { Socket *sock; Socket *acceptResult; struct sockaddr_storage addr; socklen_t addrLen; NetDescriptor *newNd; sock = NetDescriptor_getSocket(nd); addrLen = sizeof (addr); acceptResult = Socket_accept(sock, (struct sockaddr *) &addr, &addrLen); if (acceptResult == Socket_noSocket) { switch (errno) { case EWOULDBLOCK: case ECONNABORTED: // Nothing serious. Keep listening. return; case EMFILE: case ENFILE: case ENOBUFS: case ENOMEM: #ifdef ENOSR case ENOSR: #endif // Serious problems, but future connections may still // be possible. log_add(log_Warning, "accept() reported '%s'\n", strerror(errno)); return; default: // Should not happen. log_add(log_Fatal, "Internal error: accept() reported " "'%s'\n", strerror(errno)); explode(); } } (void) Socket_setReuseAddr(acceptResult); // Ignore errors; it's not a big deal. if (Socket_setNonBlocking(acceptResult) == -1) { int savedErrno = errno; log_add(log_Error, "Could not make socket non-blocking: %s.\n", strerror(errno)); Socket_close(acceptResult); errno = savedErrno; return; } (void) Socket_setInlineOOB(acceptResult); // Ignore errors; it's not a big deal as the other // party is not not supposed to send any OOB data. (void) Socket_setKeepAlive(sock); // Ignore errors; it's not a big deal. #ifdef DEBUG { char hostname[NI_MAXHOST]; int gniRes; gniRes = getnameinfo((struct sockaddr *) &addr, addrLen, hostname, sizeof hostname, NULL, 0, 0); if (gniRes != 0) { log_add(log_Error, "Error while performing hostname " "lookup for incoming connection: %s\n", (gniRes == EAI_SYSTEM) ? strerror(errno) : gai_strerror(gniRes)); } else { log_add(log_Debug, "Accepted incoming connection from '%s'.\n", hostname); } } #endif newNd = NetDescriptor_new(acceptResult, NULL); if (newNd == NULL) { int savedErrno = errno; log_add(log_Error, "NetDescriptor_new() failed: %s.\n", strerror(errno)); Socket_close(acceptResult); errno = savedErrno; return; } doListenConnectCallback(listenState, nd, newNd, (struct sockaddr *) &addr, addrLen); // NB: newNd is now handed over to the callback function, and should // no longer be referenced from here. } // Called when select() has indicated readability on a listening socket, // i.e. when a connection is in the queue. static void acceptCallback(NetDescriptor *nd) { ListenState *listenState = (ListenState *) NetDescriptor_getExtra(nd); acceptSingleConnection(listenState, nd); } uqm-0.6.2/sc2/src/sc2code/libs/network/connect/Makeinfo0000600000175000017500000000005310543202041021323 0ustar joeyjoeyuqm_CFILES="connect.c listen.c resolve.c" uqm-0.6.2/sc2/src/sc2code/libs/network/connect/connect.c0000600000175000017500000003244510552435024021467 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PORT_WANT_ERRNO #include "port.h" #define CONNECT_INTERNAL #define SOCKET_INTERNAL #include "connect.h" #include "resolve.h" #include "libs/alarm.h" #include "../socket/socket.h" #include "libs/misc.h" #include "libs/log.h" #include #include #include #include #ifdef USE_WINSOCK # include # include # include "../wspiapiwrap.h" #else # include #endif #define DEBUG_CONNECT_REF #ifdef DEBUG_CONNECT_REF # include "types.h" #endif static void connectHostNext(ConnectState *connectState); static void doConnectCallback(ConnectState *connectState, NetDescriptor *nd, const struct sockaddr *addr, socklen_t addrLen); static void doConnectErrorCallback(ConnectState *connectState, const ConnectError *error); static ConnectState * ConnectState_alloc(void) { return (ConnectState *) malloc(sizeof (ConnectState)); }; static void ConnectState_free(ConnectState *connectState) { free(connectState); } static void ConnectState_delete(ConnectState *connectState) { assert(connectState->nd == NULL); assert(connectState->alarm == NULL); assert(connectState->info == NULL); assert(connectState->infoPtr == NULL); ConnectState_free(connectState); } void ConnectState_incRef(ConnectState *connectState) { assert(connectState->refCount < REFCOUNT_MAX); connectState->refCount++; #ifdef DEBUG_CONNECT_REF log_add(log_Debug, "ConnectState %08" PRIxPTR ": ref++ (%d)\n", (uintptr_t) connectState, connectState->refCount); #endif } bool ConnectState_decRef(ConnectState *connectState) { assert(connectState->refCount > 0); connectState->refCount--; #ifdef DEBUG_CONNECT_REF log_add(log_Debug, "ConnectState %08" PRIxPTR ": ref-- (%d)\n", (uintptr_t) connectState, connectState->refCount); #endif if (connectState->refCount == 0) { ConnectState_delete(connectState); return true; } return false; } // decrements ref count by 1 void ConnectState_close(ConnectState *connectState) { if (connectState->resolveState != NULL) { Resolve_close(connectState->resolveState); connectState->resolveState = NULL; } if (connectState->alarm != NULL) { Alarm_remove(connectState->alarm); connectState->alarm = NULL; } if (connectState->nd != NULL) { NetDescriptor_close(connectState->nd); connectState->nd = NULL; } if (connectState->info != NULL) { freeaddrinfo(connectState->info); connectState->info = NULL; connectState->infoPtr = NULL; } connectState->state = Connect_closed; ConnectState_decRef(connectState); } void ConnectState_setExtra(ConnectState *connectState, void *extra) { connectState->extra = extra; } void * ConnectState_getExtra(ConnectState *connectState) { return connectState->extra; } static void connectCallback(NetDescriptor *nd) { // Called by the NetManager when a connection has been established. ConnectState *connectState = (ConnectState *) NetDescriptor_getExtra(nd); int err; if (connectState->alarm != NULL) { Alarm_remove(connectState->alarm); connectState->alarm = NULL; } if (connectState->state == Connect_closed) { // The connection attempt has been aborted. #ifdef DEBUG log_add(log_Debug, "Connection attempt was aborted.\n"); #endif ConnectState_decRef(connectState); return; } if (Socket_getError(NetDescriptor_getSocket(nd), &err) == -1) { log_add(log_Fatal, "Socket_getError() failed: %s.\n", strerror(errno)); explode(); } if (err != 0) { #ifdef DEBUG log_add(log_Debug, "connect() failed: %s.\n", strerror(err)); #endif NetDescriptor_close(nd); connectState->nd = NULL; connectState->infoPtr = connectState->infoPtr->ai_next; connectHostNext(connectState); return; } // Notify the higher layer. connectState->nd = NULL; // The callback function takes over ownership of the // NetDescriptor. NetDescriptor_setWriteCallback(nd, NULL); // Note that connectState->info and connectState->infoPtr are cleaned up // when ConnectState_close() is called by the callback function. ConnectState_incRef(connectState); doConnectCallback(connectState, nd, connectState->infoPtr->ai_addr, connectState->infoPtr->ai_addrlen); { // The callback called should release the last reference to // the connectState, by calling ConnectState_close(). bool released = ConnectState_decRef(connectState); assert(released); (void) released; // In case assert() evaluates to nothing. } } static void connectTimeoutCallback(ConnectState *connectState) { connectState->alarm = NULL; NetDescriptor_close(connectState->nd); connectState->nd = NULL; connectState->infoPtr = connectState->infoPtr->ai_next; connectHostNext(connectState); } static void setConnectTimeout(ConnectState *connectState) { assert(connectState->alarm == NULL); connectState->alarm = Alarm_addRelativeMs(connectState->flags.timeout, (AlarmCallback) connectTimeoutCallback, connectState); } // Try connecting to the next address. static Socket * tryConnectHostNext(ConnectState *connectState) { struct addrinfo *info; Socket *sock; int connectResult; assert(connectState->nd == NULL); info = connectState->infoPtr; sock = Socket_openNative(info->ai_family, info->ai_socktype, info->ai_protocol); if (sock == Socket_noSocket) { int savedErrno = errno; log_add(log_Error, "socket() failed: %s.\n", strerror(errno)); errno = savedErrno; return Socket_noSocket; } if (Socket_setNonBlocking(sock) == -1) { int savedErrno = errno; log_add(log_Error, "Could not make socket non-blocking: %s.\n", strerror(errno)); errno = savedErrno; return Socket_noSocket; } (void) Socket_setReuseAddr(sock); // Ignore errors; it's not a big deal. (void) Socket_setInlineOOB(sock); // Ignore errors; it's not a big deal as the other party is not // not supposed to send any OOB data. (void) Socket_setKeepAlive(sock); // Ignore errors; it's not a big deal. connectResult = Socket_connect(sock, info->ai_addr, info->ai_addrlen); if (connectResult == 0) { // Connection has already succeeded. // We just wait for the writability callback anyhow, so that // we can use one code path. return sock; } switch (errno) { case EINPROGRESS: // Connection in progress; wait for the write callback. return sock; } // Connection failed immediately. This is just for one of the addresses, // so this does not have to be final. // Note that as the socket is non-blocking, most failed connection // errors will usually not be reported immediately. { int savedErrno = errno; Socket_close(sock); #ifdef DEBUG log_add(log_Debug, "connect() immediately failed for one address: " "%s.\n", strerror(errno)); // TODO: add the address in the status message. #endif errno = savedErrno; } return Socket_noSocket; } static void connectRetryCallback(ConnectState *connectState) { connectState->alarm = NULL; connectState->infoPtr = connectState->info; connectHostNext(connectState); } static void setConnectRetryAlarm(ConnectState *connectState) { assert(connectState->alarm == NULL); assert(connectState->flags.retryDelayMs != Connect_noRetry); connectState->alarm = Alarm_addRelativeMs(connectState->flags.retryDelayMs, (AlarmCallback) connectRetryCallback, connectState); } static void connectHostReportAllFailed(ConnectState *connectState) { // Could not connect to any host. ConnectError error; freeaddrinfo(connectState->info); connectState->info = NULL; connectState->infoPtr = NULL; connectState->state = Connect_closed; error.state = Connect_connecting; error.err = ETIMEDOUT; // No errno code is exactly suitable. We have been unable // to connect to any host, but the reasons may vary // (unreachable, refused, ...). // ETIMEDOUT is the least specific portable errno code that // seems appropriate. doConnectErrorCallback(connectState, &error); } static void connectHostNext(ConnectState *connectState) { Socket *sock; while (connectState->infoPtr != NULL) { sock = tryConnectHostNext(connectState); if (sock != Socket_noSocket) { // Connection succeeded or connection in progress connectState->nd = NetDescriptor_new(sock, (void *) connectState); if (connectState->nd == NULL) { ConnectError error; int savedErrno = errno; log_add(log_Error, "NetDescriptor_new() failed: %s.\n", strerror(errno)); Socket_close(sock); freeaddrinfo(connectState->info); connectState->info = NULL; connectState->infoPtr = NULL; connectState->state = Connect_closed; error.state = Connect_connecting; error.err = savedErrno; doConnectErrorCallback(connectState, &error); return; } NetDescriptor_setWriteCallback(connectState->nd, connectCallback); setConnectTimeout(connectState); return; } connectState->infoPtr = connectState->infoPtr->ai_next; } // Connect failed to all addresses. if (connectState->flags.retryDelayMs == Connect_noRetry) { connectHostReportAllFailed(connectState); return; } setConnectRetryAlarm(connectState); } static void connectHostResolveCallback(ResolveState *resolveState, struct addrinfo *info) { ConnectState *connectState = (ConnectState *) ResolveState_getExtra(resolveState); connectState->state = Connect_connecting; Resolve_close(resolveState); connectState->resolveState = NULL; if (connectState->flags.familyPrefer != PF_UNSPEC) { // Reorganise the 'info' list to put the structures of the // prefered family in front. struct addrinfo *preferred; struct addrinfo **preferredEnd; struct addrinfo *rest; struct addrinfo **restEnd; splitAddrInfoOnFamily(info, connectState->flags.familyPrefer, &preferred, &preferredEnd, &rest, &restEnd); info = preferred; *preferredEnd = rest; } connectState->info = info; connectState->infoPtr = info; connectHostNext(connectState); } static void connectHostResolveErrorCallback(ResolveState *resolveState, const ResolveError *resolveError) { ConnectState *connectState = (ConnectState *) ResolveState_getExtra(resolveState); ConnectError connectError; assert(resolveError->gaiRes != 0); Resolve_close(resolveState); connectState->resolveState = NULL; connectError.state = Connect_resolving; connectError.resolveError = resolveError; connectError.err = resolveError->err; doConnectErrorCallback(connectState, &connectError); } ConnectState * connectHostByName(const char *host, const char *service, Protocol proto, const ConnectFlags *flags, ConnectConnectCallback connectCallback, ConnectErrorCallback errorCallback, void *extra) { struct addrinfo hints; ConnectState *connectState; ResolveFlags resolveFlags; // Structure is empty (for now). assert(flags->familyDemand == PF_inet || flags->familyDemand == PF_inet6 || flags->familyDemand == PF_unspec); assert(flags->familyPrefer == PF_inet || flags->familyPrefer == PF_inet6 || flags->familyPrefer == PF_unspec); assert(proto == IPProto_tcp || proto == IPProto_udp); memset(&hints, '\0', sizeof hints); hints.ai_family = protocolFamilyTranslation[flags->familyDemand]; hints.ai_protocol = protocolTranslation[proto]; if (proto == IPProto_tcp) { hints.ai_socktype = SOCK_STREAM; } else { assert(proto == IPProto_udp); hints.ai_socktype = SOCK_DGRAM; } hints.ai_flags = 0; connectState = ConnectState_alloc(); connectState->refCount = 1; #ifdef DEBUG_CONNECT_REF log_add(log_Debug, "ConnectState %08" PRIxPTR ": ref=1 (%d)\n", (uintptr_t) connectState, connectState->refCount); #endif connectState->state = Connect_resolving; connectState->flags = *flags; connectState->connectCallback = connectCallback; connectState->errorCallback = errorCallback; connectState->extra = extra; connectState->info = NULL; connectState->infoPtr = NULL; connectState->nd = NULL; connectState->alarm = NULL; connectState->resolveState = getaddrinfoAsync( host, service, &hints, &resolveFlags, (ResolveCallback) connectHostResolveCallback, (ResolveErrorCallback) connectHostResolveErrorCallback, (ResolveCallbackArg) connectState); return connectState; } // NB: The callback function becomes the owner of nd static void doConnectCallback(ConnectState *connectState, NetDescriptor *nd, const struct sockaddr *addr, socklen_t addrLen) { assert(connectState->connectCallback != NULL); ConnectState_incRef(connectState); // No need to increment nd as the callback function takes over ownership. (*connectState->connectCallback)(connectState, nd, addr, addrLen); ConnectState_decRef(connectState); } static void doConnectErrorCallback(ConnectState *connectState, const ConnectError *error) { assert(connectState->errorCallback != NULL); ConnectState_incRef(connectState); (*connectState->errorCallback)(connectState, error); ConnectState_decRef(connectState); } uqm-0.6.2/sc2/src/sc2code/libs/network/connect/resolve.h0000600000175000017500000000577110543202041021513 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CONNECT_RESOLVE_H #define _CONNECT_RESOLVE_H typedef struct ResolveFlags ResolveFlags; typedef struct ResolveError ResolveError; typedef enum { Resolve_closed, Resolve_resolving } ResolveStateState; typedef struct ResolveState ResolveState; #include "port.h" #include "../netport.h" // For addrinfo. #ifdef USE_WINSOCK // Not including because of possible conflicts with files // including this file. struct addrinfo; #else # include #endif #include "libs/callback.h" #include "../netmanager/netmanager.h" struct ResolveFlags { // Nothing yet. int dummy; // empty struct declarations are not allowed by C'99. }; struct ResolveError { int gaiRes; int err; // errno value. Only relevant if gaiRes == EAI_SYSTEM. }; typedef void *ResolveCallbackArg; typedef void (*ResolveCallback)(ResolveState *resolveState, struct addrinfo *result); // The receiver of the callback is owner of 'result' and // should call freeaddrinfo(). typedef void (*ResolveErrorCallback)(ResolveState *resolveState, const ResolveError *error); #ifdef RESOLVE_INTERNAL #ifdef USE_WINSOCK # include # include # include "../wspiapiwrap.h" #else /* !defined(USE_WINSOCK) */ # include #endif /* !defined(USE_WINSOCK) */ struct ResolveState { RefCount refCount; ResolveStateState state; ResolveFlags flags; ResolveCallback callback; ResolveErrorCallback errorCallback; void *extra; CallbackID callbackID; ResolveError error; struct addrinfo *result; }; #endif /* RESOLVE_INTERNAL */ void ResolveState_incRef(ResolveState *resolveState); bool ResolveState_decRef(ResolveState *resolveState); void ResolveState_setExtra(ResolveState *resolveState, void *extra); void *ResolveState_getExtra(ResolveState *resolveState); ResolveState *getaddrinfoAsync(const char *node, const char *service, const struct addrinfo *hints, ResolveFlags *flags, ResolveCallback callback, ResolveErrorCallback errorCallback, ResolveCallbackArg extra); void Resolve_close(ResolveState *resolveState); void splitAddrInfoOnFamily(struct addrinfo *info, int family, struct addrinfo **selected, struct addrinfo ***selectedEnd, struct addrinfo **rest, struct addrinfo ***restEnd); #endif /* _CONNECT_RESOLVE_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/socket/0000755000175000017500000000000010552600274017532 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/network/socket/socket_bsd.h0000600000175000017500000000173610543202041022010 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SOCKET_BSD_H #define _SOCKET_BSD_H #include "types.h" #include #ifdef SOCKET_INTERNAL struct Socket { int fd; }; #endif /* SOCKET_INTERNAL */ #endif /* _SOCKET_BSD_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/socket/socket_bsd.c0000600000175000017500000001315310543202041021777 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // Socket functions for BSD sockets. #define SOCKET_INTERNAL #include "socket.h" #include "libs/log.h" #include #include #include #include #include #include #include #if defined(__FreeBSD__) || defined(__OpenBSD__) # include # include #endif #include #include #include #include Socket * Socket_alloc(void) { return malloc(sizeof (Socket)); } void Socket_free(Socket *sock) { free(sock); } Socket * Socket_openNative(int domain, int type, int protocol) { Socket *result; int fd; fd = socket(domain, type, protocol); if (fd == -1) { // errno is set return Socket_noSocket; } result = Socket_alloc(); result->fd = fd; return result; } int Socket_close(Socket *sock) { int closeResult; do { closeResult = close(sock->fd); if (closeResult == 0) { Socket_free(sock); return 0; } } while (errno == EINTR); return -1; } int Socket_connect(Socket *sock, const struct sockaddr *addr, socklen_t addrLen) { int connectResult; do { connectResult = connect(sock->fd, addr, addrLen); } while (connectResult == -1 && errno == EINTR); return connectResult; } int Socket_bind(Socket *sock, const struct sockaddr *addr, socklen_t addrLen) { return bind(sock->fd, addr, addrLen); } int Socket_listen(Socket *sock, int backlog) { return listen(sock->fd, backlog); } Socket * Socket_accept(Socket *sock, struct sockaddr *addr, socklen_t *addrLen) { int acceptResult; socklen_t tempAddrLen; do { tempAddrLen = *addrLen; acceptResult = accept(sock->fd, addr, &tempAddrLen); if (acceptResult != -1) { Socket *result = Socket_alloc(); result->fd = acceptResult; *addrLen = tempAddrLen; return result; } } while (errno == EINTR); // errno is set return Socket_noSocket; } ssize_t Socket_send(Socket *sock, const void *buf, size_t len, int flags) { return send(sock->fd, buf, len, flags); } ssize_t Socket_recv(Socket *sock, void *buf, size_t len, int flags) { return recv(sock->fd, buf, len, flags); } int Socket_setNonBlocking(Socket *sock) { int flags; flags = fcntl(sock->fd, F_GETFL); if (flags == -1) { int savedErrno = errno; log_add(log_Error, "Getting file descriptor flags of socket failed: " "%s.\n", strerror(errno)); errno = savedErrno; return -1; } if (fcntl(sock->fd, F_SETFL, flags | O_NONBLOCK) == -1) { int savedErrno = errno; log_add(log_Error, "Setting non-blocking mode on socket failed: " "%s.\n", strerror(errno)); errno = savedErrno; return -1; } return 0; } int Socket_setReuseAddr(Socket *sock) { int flag = 1; if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof flag) == -1) { int savedErrno = errno; log_add(log_Error, "Setting socket reuse failed: %s.\n", strerror(errno)); errno = savedErrno; return -1; } return 0; } // Send data as soon as it is available. Do not collect data to send at // once. int Socket_setNodelay(Socket *sock) { int flag = 1; if (setsockopt(sock->fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof flag) == -1) { #ifdef DEBUG int savedErrno = errno; log_add(log_Warning, "Disabling Nagle algorithm failed: %s.\n", strerror(errno)); errno = savedErrno; #endif return -1; } return 0; } // 'tos' should be IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_THROUGHPUT, // IPTOS_RELIABILITY, or IPTOS_MINCOST. int Socket_setTOS(Socket *sock, int tos) { if (setsockopt(sock->fd, IPPROTO_IP, IP_TOS, &tos, sizeof tos) == -1) { #ifdef DEBUG int savedErrno = errno; log_add(log_Warning, "Setting socket type-of-service failed: %s.\n", strerror(errno)); errno = savedErrno; #endif return -1; } return 0; } // This function setups the socket for optimal configuration for an // interactive connection. int Socket_setInteractive(Socket *sock) { if (Socket_setNodelay(sock) == -1) { // errno is set return -1; } if (Socket_setTOS(sock, IPTOS_LOWDELAY) == -1) { // errno is set return -1; } return 0; } int Socket_setInlineOOB(Socket *sock) { int flag = 1; if (setsockopt(sock->fd, SOL_SOCKET, SO_OOBINLINE, &flag, sizeof flag) == -1) { int savedErrno = errno; log_add(log_Error, "Setting inline OOB on socket failed: %s\n", strerror(errno)); errno = savedErrno; return -1; } return 0; } int Socket_setKeepAlive(Socket *sock) { int flag = 1; if (setsockopt(sock->fd, IPPROTO_TCP, SO_KEEPALIVE, &flag, sizeof flag) == -1) { int savedErrno = errno; log_add(log_Error, "Setting keep-alive on socket failed: %s\n", strerror(errno)); errno = savedErrno; return -1; } return 0; } int Socket_getError(Socket *sock, int *err) { socklen_t errLen = sizeof(*err); if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, err, &errLen) == -1) { // errno is set return -1; } assert(errLen == sizeof(*err)); // err is set return 0; } uqm-0.6.2/sc2/src/sc2code/libs/network/socket/socket.c0000600000175000017500000000324610543202041021151 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "port.h" #define SOCKET_INTERNAL #include "socket.h" #ifdef USE_WINSOCK # include #else # include # include #endif //////////////////////////////////////////////////////////////////////////// const int protocolFamilyTranslation[] = { /* .[PF_unspec] = */ PF_UNSPEC, /* .[PF_inet] = */ PF_INET, /* .[PF_inet6] = */ PF_INET6, }; const int protocolTranslation[] = { /* .[IPProto_tcp] = */ IPPROTO_TCP, /* .[IPProto_udp] = */ IPPROTO_UDP, }; const int socketTypeTranslation[] = { /* .[Sock_stream] = */ SOCK_STREAM, /* .[Sock_dgram] = */ SOCK_DGRAM, }; Socket * Socket_open(ProtocolFamily domain, SocketType type, Protocol protocol) { return Socket_openNative(protocolFamilyTranslation[domain], socketTypeTranslation[type], protocolTranslation[protocol]); } //////////////////////////////////////////////////////////////////////////// uqm-0.6.2/sc2/src/sc2code/libs/network/socket/socket.h0000600000175000017500000000524410543202041021156 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _UQM_SOCKET_H #define _UQM_SOCKET_H typedef struct Socket Socket; #define Socket_noSocket ((Socket *) NULL) #include "port.h" #ifdef USE_WINSOCK # include "socket_win.h" #else # include "socket_bsd.h" #endif //////////////////////////////////////////////////////////////////////////// // Defining our own types for protocol families and protocols instead of // using the system defines, so that the layer using this API does not have // to have anything to do with the system layer. typedef enum { PF_unspec, PF_inet, PF_inet6, } ProtocolFamily; typedef ProtocolFamily AddressFamily; typedef enum { IPProto_tcp, IPProto_udp, } Protocol; typedef enum { Sock_stream, Sock_dgram, } SocketType; #ifdef SOCKET_INTERNAL extern const int protocolFamilyTranslation[]; #define addressFamilyTranslation protocolFamilyTranslation; extern const int protocolTranslation[]; extern const int socketTypeTranslation[]; #endif //////////////////////////////////////////////////////////////////////////// Socket *Socket_open(ProtocolFamily domain, SocketType type, Protocol protocol); #ifdef SOCKET_INTERNAL Socket *Socket_openNative(int domain, int type, int protocol); #endif int Socket_close(Socket *sock); int Socket_connect(Socket *sock, const struct sockaddr *addr, socklen_t addrLen); int Socket_bind(Socket *sock, const struct sockaddr *addr, socklen_t addrLen); int Socket_listen(Socket *sock, int backlog); Socket *Socket_accept(Socket *sock, struct sockaddr *addr, socklen_t *addrLen); ssize_t Socket_send(Socket *sock, const void *buf, size_t len, int flags); ssize_t Socket_recv(Socket *sock, void *buf, size_t len, int flags); int Socket_setNonBlocking(Socket *sock); int Socket_setReuseAddr(Socket *sock); int Socket_setInteractive(Socket *sock); int Socket_setInlineOOB(Socket *sock); int Socket_setKeepAlive(Socket *sock); int Socket_getError(Socket *sock, int *err); #endif /* _UQM_SOCKET_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/socket/Makeinfo0000600000175000017500000000022010543202041021156 0ustar joeyjoeyuqm_CFILES="socket.c" if [ -n "$uqm_USE_WINSOCK" ]; then uqm_CFILES="$uqm_CFILES socket_win.c" else uqm_CFILES="$uqm_CFILES socket_bsd.c" fi uqm-0.6.2/sc2/src/sc2code/libs/network/socket/socket_win.c0000600000175000017500000001355410543202041022031 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // Socket functions for Winsock sockets. #define PORT_WANT_ERRNO #include "port.h" #include "../netport.h" #define SOCKET_INTERNAL #include "socket.h" #include "libs/log.h" #include #include #include Socket * Socket_alloc(void) { return malloc(sizeof (Socket)); } void Socket_free(Socket *sock) { free(sock); } Socket * Socket_openNative(int domain, int type, int protocol) { Socket *result; SOCKET sock; sock = socket(domain, type, protocol); if (sock == INVALID_SOCKET) { errno = getWinsockErrno(); return Socket_noSocket; } result = Socket_alloc(); result->sock = sock; return result; } int Socket_close(Socket *sock) { int closeResult; do { closeResult = closesocket(sock->sock); if (closeResult != SOCKET_ERROR) { Socket_free(sock); return 0; } errno = getWinsockErrno(); } while (errno == EINTR); return -1; } int Socket_connect(Socket *sock, const struct sockaddr *addr, socklen_t addrLen) { int connectResult; do { connectResult = connect(sock->sock, addr, addrLen); if (connectResult == 0) return 0; errno = getWinsockErrno(); } while (errno == EINTR); if (errno == EWOULDBLOCK) { // Windows returns (WSA)EWOULDBLOCK when a connection is being // initiated on a non-blocking socket, while other platforms // use EINPROGRESS in such cases. errno = EINPROGRESS; } return -1; } int Socket_bind(Socket *sock, const struct sockaddr *addr, socklen_t addrLen) { int bindResult; bindResult = bind(sock->sock, addr, addrLen); if (bindResult == SOCKET_ERROR) { errno = getWinsockErrno(); return -1; } return 0; } int Socket_listen(Socket *sock, int backlog) { int listenResult; listenResult = listen(sock->sock, backlog); if (listenResult == SOCKET_ERROR) { errno = getWinsockErrno(); return -1; } return 0; } Socket * Socket_accept(Socket *sock, struct sockaddr *addr, socklen_t *addrLen) { SOCKET acceptResult; socklen_t tempAddrLen; do { tempAddrLen = *addrLen; acceptResult = accept(sock->sock, addr, &tempAddrLen); if (acceptResult != INVALID_SOCKET) { Socket *result = Socket_alloc(); result->sock = acceptResult; *addrLen = tempAddrLen; return result; } errno = getWinsockErrno(); } while (errno == EINTR); // errno is set return Socket_noSocket; } ssize_t Socket_send(Socket *sock, const void *buf, size_t len, int flags) { int sendResult; sendResult = send(sock->sock, buf, len, flags); if (sendResult == SOCKET_ERROR) { errno = getWinsockErrno(); return -1; } return sendResult; } ssize_t Socket_recv(Socket *sock, void *buf, size_t len, int flags) { int recvResult; recvResult = recv(sock->sock, buf, len, flags); if (recvResult == SOCKET_ERROR) { errno = getWinsockErrno(); return -1; } return recvResult; } int Socket_setNonBlocking(Socket *sock) { unsigned long flag = 1; if (ioctlsocket(sock->sock, FIONBIO, &flag) == SOCKET_ERROR) { int savedErrno = getWinsockErrno(); log_add(log_Error, "Setting non-block mode on socket failed: %s.\n", strerror(errno)); errno = savedErrno; return -1; } return 0; } int Socket_setReuseAddr(Socket *sock) { BOOL flag = 1; if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &flag, sizeof flag) == SOCKET_ERROR) { int savedErrno = getWinsockErrno(); log_add(log_Error, "Setting socket reuse failed: %s.\n", strerror(errno)); errno = savedErrno; return -1; } return 0; } // Send data as soon as it is available. Do not collect data to send at // once. int Socket_setNodelay(Socket *sock) { BOOL flag = 1; if (setsockopt(sock->sock, IPPROTO_TCP, TCP_NODELAY, (const char *) &flag, sizeof flag) == SOCKET_ERROR) { #ifdef DEBUG int savedErrno = getWinsockErrno(); log_add(log_Warning, "Disabling Nagle algorithm failed: %s.\n", strerror(errno)); errno = savedErrno; #endif return -1; } return 0; } // This function setups the socket for optimal configuration for an // interactive connection. int Socket_setInteractive(Socket *sock) { if (Socket_setNodelay(sock) == -1) { // errno is set return -1; } #if 0 if (Socket_setTOS(sock, IPTOS_LOWDELAY) == -1) { // errno is set return -1; } #endif return 0; } int Socket_setInlineOOB(Socket *sock) { BOOL flag = 1; if (setsockopt(sock->sock, SOL_SOCKET, SO_OOBINLINE, (const char *) &flag, sizeof flag) == SOCKET_ERROR) { int savedErrno = getWinsockErrno(); log_add(log_Error, "Setting inline OOB on socket failed: %s\n", strerror(errno)); errno = savedErrno; return -1; } return 0; } int Socket_setKeepAlive(Socket *sock) { BOOL flag = 1; if (setsockopt(sock->sock, IPPROTO_TCP, SO_KEEPALIVE, (const char *) &flag, sizeof flag) == SOCKET_ERROR) { int savedErrno = getWinsockErrno(); log_add(log_Error, "Setting keep-alive on socket failed: %s\n", strerror(errno)); errno = savedErrno; return -1; } return 0; } int Socket_getError(Socket *sock, int *err) { int errLen = sizeof(*err); if (getsockopt(sock->sock, SOL_SOCKET, SO_ERROR, (char *) err, &errLen) == SOCKET_ERROR) { errno = getWinsockErrno(); return -1; } assert(errLen == sizeof(*err)); // err is set return 0; } uqm-0.6.2/sc2/src/sc2code/libs/network/socket/socket_win.h0000600000175000017500000000176610543202041022040 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SOCKET_WIN_H #define _SOCKET_WIN_H #ifdef SOCKET_INTERNAL #include struct Socket { SOCKET sock; }; #endif /* SOCKET_INTERNAL */ typedef int socklen_t; struct sockaddr; #endif /* _SOCKET_WIN_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/bytesex.h0000600000175000017500000000414610543202041020061 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // Routines for changing the endianness of values. // I'm not using ntohs() etc. as those would require include files that may // have conflicting definitions. This is a problem on Windows, where these // functions are in winsock2.h, which includes windows.h, which includes // pretty much Microsoft's complete collection of .h files. #ifndef _BYTESEX_H #define _BYTESEX_H #include "port.h" // for inline #include "endian_uqm.h" // for WORDS_BIGENDIAN #include "types.h" static inline uint16 swapBytes16(uint16 x) { return (x << 8) | (x >> 8); } static inline uint32 swapBytes32(uint32 x) { return (x << 24) | ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) >> 8) | (x >> 24); } #ifdef WORDS_BIGENDIAN // Already in network order. static inline uint16 hton16(uint16 x) { return x; } static inline uint32 hton32(uint32 x) { return x; } static inline uint16 ntoh16(uint16 x) { return x; } static inline uint32 ntoh32(uint32 x) { return x; } #else /* !defined(WORDS_BIGENDIAN) */ // Need to swap bytes static inline uint16 hton16(uint16 x) { return swapBytes16(x); } static inline uint32 hton32(uint32 x) { return swapBytes32(x); } static inline uint16 ntoh16(uint16 x) { return swapBytes16(x); } static inline uint32 ntoh32(uint32 x) { return swapBytes32(x); } #endif /* defined(WORDS_BIGENDIAN) */ #endif /* _BYTESEX_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/network.h0000600000175000017500000000161510543202041020065 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NETWORK_H #define _NETWORK_H void Network_init(void); void Network_uninit(void); #endif /* _NETWORK_H */ uqm-0.6.2/sc2/src/sc2code/libs/network/Makeinfo0000600000175000017500000000041610543202041017675 0ustar joeyjoeyuqm_SUBDIRS="connect netmanager socket" uqm_CFILES="netport.c" if [ -n "$uqm_USE_WINSOCK" ]; then uqm_CFILES="$uqm_CFILES network_win.c" if [ -n "$MACRO___MINGW32__" ]; then uqm_CFILES="$uqm_CFILES wspiapiwrap.c" fi else uqm_CFILES="$uqm_CFILES network_bsd.c" fi uqm-0.6.2/sc2/src/sc2code/libs/network/network_win.c0000600000175000017500000000415610543202041020740 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "netport.h" #include "network.h" #include "libs/misc.h" #include "libs/log.h" #include #include void Network_init(void) { WSADATA data; int startupResult; WORD requestVersion = MAKEWORD(2, 2); startupResult = WSAStartup(requestVersion, &data); if (startupResult != 0) { int savedErrno = winsockErrorToErrno(startupResult); log_add(log_Fatal, "WSAStartup failed.\n"); errno = savedErrno; explode(); } #ifdef DEBUG log_add(log_Debug, "Winsock version %d.%d found: \"%s\".\n", LOBYTE(data.wHighVersion), HIBYTE(data.wHighVersion), data.szDescription); log_add(log_Debug, "Requesting to use Winsock version %d.%d, got " "version %d.%d.\n", LOBYTE(requestVersion), HIBYTE(requestVersion), LOBYTE(data.wVersion), HIBYTE(data.wVersion)); #endif if (data.wVersion != requestVersion) { log_add(log_Fatal, "Winsock version %d.%d presented, requested " "%d.%d.\n", LOBYTE(data.wVersion), HIBYTE(data.wVersion), LOBYTE(requestVersion), HIBYTE(requestVersion)); (void) WSACleanup(); // Ignoring errors; we're going to abort anyhow. explode(); } } void Network_uninit(void) { int cleanupResult; cleanupResult = WSACleanup(); if (cleanupResult == SOCKET_ERROR) { int savedErrno = getWinsockErrno(); log_add(log_Fatal, "WSACleanup failed.\n"); errno = savedErrno; explode(); } } uqm-0.6.2/sc2/src/sc2code/libs/network/FILES0000600000175000017500000000214310543202041017005 0ustar joeyjoeyIn libs/network/: netport.{c,h} Portability definitions. bytesex.h Functions for endianness conversions. network.h Functions for initialising the network subsystem. network_bsd.c Network subsystem functions for BSD sockets. network_win.c Network subsystem functions for Winsock sockets. wspiapiwrap.{c,h} Hack to make sure is #included in exactly one file. In libs/network/netmanager/: ndesc.{c,h} Defines network descriptors. netmanager.h Handles callbacks for network activity. netmanager_bsd.{c,h} NetManager for systems with BSD sockets. netmanager_win.{c,h} NetManager for Winsock systems. In libs/network/socket/: socket.{c,h} Platform-independant socket layer. socket_bsd.{c,h} Socket operations for BSD sockets. socket_win.{c,h} Socket operations for Winsock sockets. In libs/network/connect/: connect.{c,h} Routines for establishing outgoing connections. listen.{c,h} Routines for receiving incoming connections. resolve.{c,h} Routines for hostname lookups. uqm-0.6.2/sc2/src/sc2code/libs/cdp/0000755000175000017500000000000010552600274015317 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/cdp/windl.h0000600000175000017500000000244510543202054016574 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP dlopen() & Co. WIN32 implementation */ #ifndef _WINDL_H #define _WINDL_H #include "types.h" extern void *dlopen (const char *filename, int flag); extern void *dlsym (void *handle, const char *symbol); extern int dlclose (void *handle); extern char *dlerror (void); /* these dlopen() flags are meaningless on win32 */ #define RTLD_LAZY 1 /* lazy function call binding */ #define RTLD_NOW 2 /* immediate function call binding */ #define RTLD_GLOBAL 4 /* symbols in this dlopen'ed obj are visible to other dlopen'ed objs */ #endif /* _WINDL_H */ uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdpapi.h0000600000175000017500000001172510543202054016720 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP API declarations * the API is used by both the engine and modules */ #ifndef _CDPAPI_H #define _CDPAPI_H #include "types.h" typedef enum { CDPAPI_VERSION_1 = 0x00000001, // version 0.1 CDPAPI_VERSION = CDPAPI_VERSION_1, CDPAPI_VERSION_MIN = CDPAPI_VERSION_1, } cdp_ApiVersion; typedef enum { CDPERR_NONE = 0, CDPERR_UKNOWN = 1, CDPERR_NOT_FOUND = 2, CDPERR_BAD_MODULE = 3, CDPERR_OLD_VER = 4, CDPERR_UNKNOWN_VER = 5, CDPERR_TOO_MANY = 6, CDPERR_INIT_FAILED = 7, CDPERR_NO_ITF = 8, CDPERR_DUPE_ITF = 9, CDPERR_NO_EVENT = 10, CDPERR_DUPE_EVENT = 11, CDPERR_OTHER = 1000, } cdp_Error; typedef struct cdp_Module cdp_Module; typedef void cdp_Itf; typedef struct cdp_ItfReg cdp_ItfReg; // Interface KINDs - for convinience and uniformity #define CDPITF_KIND_INVALID NULL #define CDPITF_KIND_HOST "UQM.Host" #define CDPITF_KIND_MEMORY "UQM.Memory" #define CDPITF_KIND_IO "UQM.IO" #define CDPITF_KIND_THREADS "UQM.Threads" #define CDPITF_KIND_TIME "UQM.Time" #define CDPITF_KIND_INPUT "UQM.Input" #define CDPITF_KIND_TASK "UQM.Task" #define CDPITF_KIND_RESOURCE "UQM.Resource" #define CDPITF_KIND_SOUND "UQM.Sound" #define CDPITF_KIND_VIDEO "UQM.Video" #define CDPITF_KIND_GFX "UQM.Gfx" #define CDPITF_KIND_MIXER "UQM.Mixer" // Interface definition structure // pass an array of these to Host->GetItfs() for batch lookup // pass an array of these to Host->RegisterItfs() for batch registration typedef struct { // fill in the first 4 members for batch registration // fill in the 1st member for batch lookup // terminate an array of these defs with name == NULL const char* name; // interface ID cdp_Itf* itf; // interface pointer cdp_ApiVersion ver_from; // lowest supported version cdp_ApiVersion ver_to; // highest supported version cdp_Module* module; // owner module // the following member is only set during registration cdp_ItfReg* reg; // registration handle (not set on lookup) } cdp_ItfDef; typedef unsigned int cdp_Event; typedef struct cdp_EventReg cdp_EventReg; typedef intptr_t cdp_EventResult; #define CDP_EVENT_INVALID (-1) // used with cdp_Event typedef cdp_EventResult (* cdp_EventProc) (cdp_Event, uint32, void*, bool* pbHandled); // Event definition structure // pass an array of these to Host->GetItfs() for batch lookup typedef struct { // fill in the 1st member for batch lookup or registration // also fill in the 2nd member for batch subscription // terminate an array of these defs with name == NULL const char* name; // event ID cdp_EventProc proc; // event proc, set to NULL for no bind cdp_Event event; // subscribable event handle cdp_Module* module; // owner module // the following member is only set during registration cdp_EventReg* reg; // registration handle (not set on lookup) } cdp_EventDef; // Host Interface // the main itf of the API, it is passed to a loaded module // module does everything else through this itf and itfs // acquired through this itf typedef struct { uint32 (* GetApiVersion) (void); uint32 (* GetVersion) (void); cdp_Error (* GetApiError) (void); cdp_Itf* (* GetItf) (const char* name); bool (* GetItfs) (cdp_ItfDef* defs); cdp_ItfReg* (* RegisterItf) (const char* name, cdp_ApiVersion ver_from, cdp_ApiVersion ver_to, cdp_Itf*, cdp_Module*); void (* UnregisterItf) (cdp_ItfReg*); bool (* RegisterItfs) (cdp_ItfDef* defs, cdp_Module*); void (* UnregisterItfs) (cdp_ItfDef* defs); cdp_Event (* GetEvent) (const char* name); bool (* GetEvents) (cdp_EventDef* defs); cdp_EventReg* (* RegisterEvent) (const char* name, cdp_Module*); void (* UnregisterEvent) (cdp_EventReg*); bool (* RegisterEvents) (cdp_EventDef* defs, cdp_Module*); void (* UnregisterEvents) (cdp_EventDef* defs); bool (* SubscribeEvent) (cdp_Event, cdp_EventProc, cdp_Module*); void (* UnsubscribeEvent) (cdp_Event, cdp_EventProc); bool (* SubscribeEvents) (cdp_EventDef* defs, cdp_Module*); void (* UnsubscribeEvents) (cdp_EventDef* defs); cdp_EventResult (* FireEvent) (cdp_EventReg*, uint32, void*); } cdp_Itf_HostVtbl_v1; typedef cdp_Itf_HostVtbl_v1 cdp_Itf_HostVtbl; typedef cdp_Itf_HostVtbl cdp_Itf_Host; #endif /* _CDPAPI_H */ uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdp_ivid.h0000600000175000017500000000253710543202054017242 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP Video Interface */ #ifndef _CDPIVID_H #define _CDPIVID_H #include "types.h" #include "libs/video/video.h" #include "libs/video/videodec.h" // CDP Video Interface entry points typedef struct { TFB_RegVideoDecoder* (* RegisterDecoder) (const char* fileext, TFB_VideoDecoderFuncs*); void (* UnregisterDecoder) (TFB_RegVideoDecoder*); const TFB_VideoDecoderFuncs* (* LookupDecoder) (const char* fileext); } cdp_Itf_VideoVtbl_v1; // the following are for the sake of module writers typedef cdp_Itf_VideoVtbl_v1 cdp_Itf_VideoVtbl; typedef cdp_Itf_VideoVtbl cdp_Itf_Video; #endif /* _CDPIVID_H */ uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdpapi.c0000600000175000017500000004364310543202054016717 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP API definitions * the API is used by both the engine and modules */ #include "cdp.h" #include "port.h" #include "cdpint.h" #include "uqmversion.h" #define MAX_REG_ITFS 255 #define MAX_REG_EVENTS 1023 static cdp_Error cdp_api_error = CDPERR_NONE; static uint32 cdp_Host_GetApiVersion (void); static uint32 cdp_Host_GetVersion (void); static cdp_Error cdp_Host_GetApiError (void); static cdp_Itf* cdp_Host_GetItf (const char* name); static bool cdp_Host_GetItfs (cdp_ItfDef* defs); static cdp_ItfReg* cdp_Host_RegisterItf (const char* name, cdp_ApiVersion ver_from, cdp_ApiVersion ver_to, cdp_Itf*, cdp_Module*); static void cdp_Host_UnregisterItf (cdp_ItfReg*); static bool cdp_Host_RegisterItfs (cdp_ItfDef* defs, cdp_Module*); static void cdp_Host_UnregisterItfs (cdp_ItfDef* defs); static cdp_Event cdp_Host_GetEvent (const char* name); static bool cdp_Host_GetEvents (cdp_EventDef* defs); static cdp_EventReg* cdp_Host_RegisterEvent (const char* name, cdp_Module*); static void cdp_Host_UnregisterEvent (cdp_EventReg*); static bool cdp_Host_RegisterEvents (cdp_EventDef* defs, cdp_Module*); static void cdp_Host_UnregisterEvents (cdp_EventDef* defs); static bool cdp_Host_SubscribeEvent (cdp_Event, cdp_EventProc, cdp_Module*); static void cdp_Host_UnsubscribeEvent (cdp_Event, cdp_EventProc); static bool cdp_Host_SubscribeEvents (cdp_EventDef* defs, cdp_Module*); static void cdp_Host_UnsubscribeEvents (cdp_EventDef* defs); static cdp_EventResult cdp_Host_FireEvent (cdp_EventReg*, uint32, void*); // Interfaces cdp_Itf_HostVtbl_v1 cdp_host_itf_v1 = { cdp_Host_GetApiVersion, cdp_Host_GetVersion, cdp_Host_GetApiError, cdp_Host_GetItf, cdp_Host_GetItfs, cdp_Host_RegisterItf, cdp_Host_UnregisterItf, cdp_Host_RegisterItfs, cdp_Host_UnregisterItfs, cdp_Host_GetEvent, cdp_Host_GetEvents, cdp_Host_RegisterEvent, cdp_Host_UnregisterEvent, cdp_Host_RegisterEvents, cdp_Host_UnregisterEvents, cdp_Host_SubscribeEvent, cdp_Host_UnsubscribeEvent, cdp_Host_SubscribeEvents, cdp_Host_UnsubscribeEvents, cdp_Host_FireEvent, }; cdp_Itf_MemoryVtbl_v1 cdp_memory_itf_v1 = { HMalloc, HFree, HCalloc, HRealloc, }; cdp_Itf_IoVtbl_v1 cdp_io_itf_v1 = { uio_fopen, uio_fclose, uio_fread, uio_fwrite, uio_fseek, uio_ftell, uio_fflush, uio_feof, uio_ferror, }; cdp_Itf_SoundVtbl_v1 cdp_sound_itf_v1 = { SoundDecoder_Register, SoundDecoder_Unregister, SoundDecoder_Lookup, }; cdp_Itf_VideoVtbl_v1 cdp_video_itf_v1 = { VideoDecoder_Register, VideoDecoder_Unregister, VideoDecoder_Lookup, }; // the actual interface registration struct/handle struct cdp_ItfReg { bool builtin; bool used; const char* name; cdp_ApiVersion ver_from; cdp_ApiVersion ver_to; cdp_Itf* itfvtbl; cdp_Module* module; }; #define CDP_DECLARE_ITF(kind,vf,vt,vtbl) \ {true, true, CDPITF_KIND_##kind, \ CDPAPI_VERSION_##vf, CDPAPI_VERSION_##vt, vtbl, NULL} // Built-in interfaces + space for loadable cdp_ItfReg cdp_itfs[MAX_REG_ITFS + 1] = { CDP_DECLARE_ITF (HOST, 1, 1, &cdp_host_itf_v1), CDP_DECLARE_ITF (MEMORY, 1, 1, &cdp_memory_itf_v1), CDP_DECLARE_ITF (IO, 1, 1, &cdp_io_itf_v1), CDP_DECLARE_ITF (SOUND, 1, 1, &cdp_sound_itf_v1), CDP_DECLARE_ITF (VIDEO, 1, 1, &cdp_video_itf_v1), // TODO: put newly defined built-in interfaces here {false, false, "", 0, 0, NULL} // term }; // event bind descriptor typedef struct { cdp_EventProc proc; cdp_Module* module; } cdp_EventBind; #define EVENT_BIND_GROW 16 // the actual event registration struct/handle struct cdp_EventReg { bool builtin; bool used; const char* name; cdp_EventBind* binds; uint32 bindslots; cdp_Module* module; }; #define CDP_DECLARE_EVENT(name) \ {true, true, "UQM." #name, NULL, 0, NULL} // Built-in events + space for loadable // a cdp_Event handle is an index into this array cdp_EventReg cdp_evts[MAX_REG_EVENTS + 1] = { // sample - no real events defined yet CDP_DECLARE_EVENT (PlanetSide.TouchDown), CDP_DECLARE_EVENT (PlanetSide.LiftOff), // TODO: put newly defined built-in events here {false, false, "", NULL, 0, NULL} // term }; cdp_Error cdp_GetApiError (void) { cdp_Error ret = cdp_api_error; cdp_api_error = CDPERR_NONE; return ret; } bool cdp_InitApi (void) { int i; cdp_Module* kernel; // preprocess built-in itfs kernel = cdp_LoadModule (NULL); for (i = 0; cdp_itfs[i].builtin; ++i) { cdp_itfs[i].module = kernel; } // clear the rest //memset (cdp_itfs + i, 0, // sizeof (cdp_itfs) - sizeof (cdp_ItfReg) * i); for (i = 0; cdp_evts[i].builtin; ++i) { cdp_evts[i].module = kernel; cdp_evts[i].bindslots = 0; cdp_evts[i].binds = NULL; } return true; } void cdp_UninitApi (void) { cdp_ItfReg* itf; // unregister custom interfaces for (itf = cdp_itfs; itf->used; ++itf) { if (!itf->builtin) { itf->used = false; if (itf->name) HFree ((void*) itf->name); itf->name = NULL; itf->itfvtbl = NULL; itf->module = NULL; } } } static uint32 cdp_Host_GetApiVersion (void) { return CDPAPI_VERSION; } static uint32 cdp_Host_GetVersion (void) { return (UQM_MAJOR_VERSION << 20) | (UQM_MINOR_VERSION << 15) | UQM_PATCH_VERSION; } static cdp_Error cdp_Host_GetApiError (void) { return cdp_GetApiError (); } static char* cdp_MakeContextName (const char* ctx, const char* name) { int namelen; char* id_name; namelen = strlen(ctx) + strlen(name) + 2; id_name = HMalloc (namelen); strcpy(id_name, ctx); strcat(id_name, "."); strcat(id_name, name); return id_name; } /*********************************************************** * Interface system * ***********************************************************/ cdp_ItfReg* cdp_GetInterfaceReg (const char* name, cdp_ApiVersion api_ver) { cdp_ItfReg* itf; for (itf = cdp_itfs; itf->used && (!itf->name || stricmp(itf->name, name) != 0 || api_ver < itf->ver_from || api_ver > itf->ver_to); itf++) ; if (!itf->name) { cdp_api_error = CDPERR_NO_ITF; return NULL; } return itf; } cdp_Itf* cdp_GetInterface (const char* name, cdp_ApiVersion api_ver) { cdp_ItfReg* reg; reg = cdp_GetInterfaceReg (name, api_ver); return reg ? reg->itfvtbl : NULL; } static cdp_Itf* cdp_Host_GetItf (const char* name) { return cdp_GetInterface (name, CDPAPI_VERSION_1); } static bool cdp_Host_GetItfs (cdp_ItfDef* defs) { cdp_ItfDef* def; cdp_ItfReg* reg; int errors = 0; for (def = defs; def->name; ++def) { // registration handle is not returned def->reg = NULL; reg = cdp_GetInterfaceReg (def->name, CDPAPI_VERSION_1); if (reg) { def->itf = reg->itfvtbl; def->name = reg->name; // set to cannonical name def->ver_from = reg->ver_from; def->ver_to = reg->ver_to; def->module = reg->module; } else { def->itf = NULL; def->module = NULL; def->ver_from = 0; def->ver_to = 0; ++errors; } } return !errors; } static cdp_ItfReg* cdp_Host_RegisterItf (const char* name, cdp_ApiVersion ver_from, cdp_ApiVersion ver_to, cdp_Itf* itfvtbl, cdp_Module* owner) { cdp_ItfReg* itfreg; cdp_ItfReg* newslot = NULL; char* id_name; const char* ctx; if (!owner) { fprintf (stderr, "cdp_Host_RegisterItf(): " "No owner info supplied\n"); //return NULL; } if (!name || !*name || !itfvtbl) { fprintf (stderr, "cdp_Host_RegisterItf(): " "Null or invalid interface (from %s)\n", cdp_GetModuleName (owner, true)); return NULL; } ctx = cdp_GetModuleContext (owner, false); if (!ctx) { fprintf (stderr, "cdp_Host_RegisterItf(): " "Null or invalid context (from %s)\n", cdp_GetModuleName (owner, true)); return NULL; } // TODO: review version policy (below) // enforce version policy and do not allow obsolete interfaces // POLICY: all modules MUST be aware of recent API changes and will not // be allowed to expose interfaces that support and/or utilize obsoleted // API versions if (ver_from < CDPAPI_VERSION_MIN) ver_from = CDPAPI_VERSION_MIN; if (ver_to < CDPAPI_VERSION_MIN) { fprintf (stderr, "cdp_Host_RegisterItf(): " "Obsolete interface %s (from %s)\n", name, cdp_GetModuleName (owner, true)); return NULL; } id_name = cdp_MakeContextName (ctx, name); // check if interface already registered for (itfreg = cdp_itfs; itfreg->used && (!itfreg->name || stricmp(itfreg->name, id_name) != 0 || ver_from < itfreg->ver_from || ver_to > itfreg->ver_to); ++itfreg) { // and pick up an empty slot (where available) if (!newslot && !itfreg->name) newslot = itfreg; } if (itfreg >= cdp_itfs + MAX_REG_ITFS) { fprintf (stderr, "cdp_Host_RegisterItf(): " "Interfaces limit reached\n"); HFree (id_name); return NULL; } else if (itfreg->name) { fprintf (stderr, "cdp_Host_RegisterItf(): " "Interface %s already registered for these versions, " "%s denied\n", name, cdp_GetModuleName (owner, true)); HFree (id_name); return NULL; } if (!newslot) { newslot = itfreg; newslot->used = true; // make next one a term itfreg[1].builtin = false; itfreg[1].used = false; itfreg[1].name = NULL; itfreg[1].itfvtbl = NULL; } newslot->name = id_name; newslot->ver_from = ver_from; newslot->ver_to = ver_to; newslot->itfvtbl = itfvtbl; newslot->module = owner; return newslot; } static void cdp_Host_UnregisterItf (cdp_ItfReg* itfreg) { if (itfreg < cdp_itfs || itfreg >= cdp_itfs + MAX_REG_ITFS || !itfreg->name || !itfreg->itfvtbl) { fprintf (stderr, "cdp_Host_UnregisterItf(): " "Invalid or expired interface passed\n"); return; } if (!itfreg->builtin) { HFree ((void*) itfreg->name); } itfreg->module = NULL; itfreg->name = NULL; itfreg->itfvtbl = NULL; } static bool cdp_Host_RegisterItfs (cdp_ItfDef* defs, cdp_Module* owner) { cdp_ItfDef* def; int errors = 0; for (def = defs; def->name; ++def) { def->reg = cdp_Host_RegisterItf (def->name, def->ver_from, def->ver_to, def->itf, owner); if (def->reg) { def->module = owner; } else { def->module = NULL; ++errors; } } return !errors; } static void cdp_Host_UnregisterItfs (cdp_ItfDef* defs) { cdp_ItfDef* def; for (def = defs; def->name; ++def) { if (def->reg) cdp_Host_UnregisterItf (def->reg); } } /*********************************************************** * Event system * ***********************************************************/ cdp_EventReg* cdp_GetEventReg (const char* name) { cdp_EventReg* evt; for (evt = cdp_evts; evt->used && (!evt->name || stricmp(evt->name, name) != 0); evt++) ; if (!evt->name) { cdp_api_error = CDPERR_NO_EVENT; return NULL; } return evt; } // hopefully inlinable static cdp_Event cdp_EventFromReg (cdp_EventReg* reg) { return (reg - cdp_evts) / sizeof (cdp_EventReg); } // hopefully inlinable static cdp_EventReg* cdp_RegFromEvent (cdp_Event event) { return cdp_evts + event; } cdp_Event cdp_GetEvent (const char* name) { cdp_EventReg* reg; reg = cdp_GetEventReg (name); return reg ? cdp_EventFromReg (reg) : CDP_EVENT_INVALID; } static cdp_EventBind* cdp_AllocEventBinds (cdp_EventBind* binds, uint32 ccur, uint32 cnew) { cdp_EventBind* newbinds; uint32 newsize; newsize = cnew * sizeof (cdp_EventBind); if (binds) newbinds = HRealloc (binds, newsize); else newbinds = HMalloc (newsize); if (cnew > ccur) memset (newbinds + ccur, 0, (cnew - ccur) * sizeof (cdp_EventBind)); return newbinds; } static cdp_Event cdp_Host_GetEvent (const char* name) { return cdp_GetEvent (name); } static bool cdp_Host_GetEvents (cdp_EventDef* defs) { cdp_EventDef* def; cdp_EventReg* reg; int errors = 0; for (def = defs; def->name; ++def) { // registration handle is not returned def->reg = NULL; reg = cdp_GetEventReg (def->name); if (reg) { def->event = cdp_EventFromReg(reg); def->name = reg->name; // set to cannonical name def->module = reg->module; } else { def->event = CDP_EVENT_INVALID; def->module = NULL; ++errors; } } return !errors; } static cdp_EventReg* cdp_Host_RegisterEvent (const char* name, cdp_Module* owner) { cdp_EventReg* evtreg; cdp_EventReg* newslot = NULL; char* id_name; const char* ctx; if (!owner) { fprintf (stderr, "cdp_Host_RegisterEvent(): " "No owner info supplied\n"); //return NULL; } if (!name || !*name) { fprintf (stderr, "cdp_Host_RegisterEvent(): " "Null or invalid event (from %s)\n", cdp_GetModuleName (owner, true)); return NULL; } ctx = cdp_GetModuleContext (owner, false); if (!ctx) { fprintf (stderr, "cdp_Host_RegisterEvent(): " "Null or invalid context (from %s)\n", cdp_GetModuleName (owner, true)); return NULL; } id_name = cdp_MakeContextName (ctx, name); // check if event already registered for (evtreg = cdp_evts; evtreg->used && (!evtreg->name || stricmp(evtreg->name, id_name) != 0); ++evtreg) { // and pick up an empty slot (where available) if (!newslot && !evtreg->name) newslot = evtreg; } if (evtreg >= cdp_evts + MAX_REG_EVENTS) { fprintf (stderr, "cdp_Host_RegisterEvent(): " "Event limit reached\n"); HFree (id_name); return NULL; } else if (evtreg->name) { fprintf (stderr, "cdp_Host_RegisterEvent(): " "Event %s already registered, " "%s denied\n", name, cdp_GetModuleName (owner, true)); HFree (id_name); return NULL; } if (!newslot) { newslot = evtreg; newslot->used = true; // make next one a term evtreg[1].builtin = false; evtreg[1].used = false; evtreg[1].name = NULL; } newslot->name = id_name; newslot->module = owner; newslot->binds = NULL; newslot->bindslots = 0; return newslot; } static void cdp_Host_UnregisterEvent (cdp_EventReg* evtreg) { if (evtreg < cdp_evts || evtreg >= cdp_evts + MAX_REG_EVENTS || !evtreg->name) { fprintf (stderr, "cdp_Host_UnregisterEvent(): " "Invalid or expired event passed\n"); return; } if (!evtreg->builtin) { HFree ((void*) evtreg->name); } evtreg->module = NULL; evtreg->name = NULL; if (evtreg->binds) HFree (evtreg->binds); evtreg->binds = NULL; evtreg->bindslots = 0; } static bool cdp_Host_RegisterEvents (cdp_EventDef* defs, cdp_Module* owner) { cdp_EventDef* def; int errors = 0; for (def = defs; def->name; ++def) { def->reg = cdp_Host_RegisterEvent (def->name, owner); if (def->reg) { def->module = owner; } else { def->module = NULL; ++errors; } } return !errors; } static void cdp_Host_UnregisterEvents (cdp_EventDef* defs) { cdp_EventDef* def; for (def = defs; def->name; ++def) { if (def->reg) cdp_Host_UnregisterEvent (def->reg); } } static bool cdp_Host_SubscribeEvent (cdp_Event event, cdp_EventProc proc, cdp_Module* module) { cdp_EventReg* reg = cdp_RegFromEvent (event); cdp_EventBind* bind = NULL; uint32 i; if (reg < cdp_evts || reg >= cdp_evts + MAX_REG_EVENTS || !reg->name) { fprintf (stderr, "cdp_Host_SubscribeEvent(): " "Invalid or expired event passed\n"); return false; } if (reg->binds) { // check for duplicate or find a new slot for (i = 0, bind = reg->binds; i < reg->bindslots && (!bind->proc || bind->proc != proc); ++i, ++bind) ; if (i >= reg->bindslots) { // full - add more slots reg->binds = cdp_AllocEventBinds (reg->binds, reg->bindslots, reg->bindslots + EVENT_BIND_GROW); bind = reg->binds + reg->bindslots; reg->bindslots += EVENT_BIND_GROW; } else if (bind->proc == proc) { // already bound return true; } } else { reg->binds = cdp_AllocEventBinds (NULL, 0, EVENT_BIND_GROW); reg->bindslots = EVENT_BIND_GROW; bind = reg->binds; } bind->proc = proc; bind->module = module; return true; } static void cdp_Host_UnsubscribeEvent (cdp_Event event, cdp_EventProc proc) { cdp_EventReg* reg = cdp_RegFromEvent (event); cdp_EventBind* bind = NULL; uint32 i; if (reg < cdp_evts || reg >= cdp_evts + MAX_REG_EVENTS || !reg->name) { // event either expired or invalid return; } if (!reg->binds || !reg->bindslots) return; // hmm, no bindings // check for duplicate or find a new slot for (i = 0, bind = reg->binds; i < reg->bindslots && bind->proc != proc; ++i, ++bind) ; if (i >= reg->bindslots) return; // binding not found bind->proc = NULL; bind->module = NULL; } static bool cdp_Host_SubscribeEvents (cdp_EventDef* defs, cdp_Module* module) { cdp_EventDef* def; int errors = 0; for (def = defs; def->name; ++def) { if (def->event != CDP_EVENT_INVALID && def->proc) if (!cdp_Host_SubscribeEvent (def->event, def->proc, module)) ++errors; } return !errors; } static void cdp_Host_UnsubscribeEvents (cdp_EventDef* defs) { cdp_EventDef* def; for (def = defs; def->name; ++def) { if (def->event != CDP_EVENT_INVALID && def->proc) cdp_Host_UnsubscribeEvent (def->event, def->proc); } } static cdp_EventResult cdp_Host_FireEvent (cdp_EventReg* evtreg, uint32 iparam, void* pparam) { bool bHandled = false; cdp_EventResult ret = 0; cdp_Event event; cdp_EventBind* bind; uint32 i; if (evtreg < cdp_evts || evtreg >= cdp_evts + MAX_REG_EVENTS || !evtreg->name) { #ifdef DEBUG fprintf (stderr, "cdp_Host_FireEvent(): Invalid event\n"); #endif return 0; } if (!evtreg->binds) return 0; // no subscribers event = cdp_EventFromReg (evtreg); // call event procs in opposite order of binding for (i = evtreg->bindslots, bind = evtreg->binds + i - 1; !bHandled && i > 0; --i, --bind) { if (bind->proc) ret = bind->proc (event, iparam, pparam, &bHandled); } return ret; } uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdp_imem.h0000600000175000017500000000234710543202054017235 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP Memory Interface */ #ifndef _CDPIMEM_H #define _CDPIMEM_H #include "types.h" #include "libs/memlib.h" // CDP Memory Interface entry points typedef struct { void* (* malloc) (int size); void (* free) (void *p); void* (* calloc) (int size); void* (* realloc) (void *p, int size); } cdp_Itf_MemoryVtbl_v1; // the following are for the sake of module writers typedef cdp_Itf_MemoryVtbl_v1 cdp_Itf_MemoryVtbl; typedef cdp_Itf_MemoryVtbl cdp_Itf_Memory; #endif /* _CDPIMEM_H */ uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdp.c0000600000175000017500000002152510543202054016220 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP library definitions */ #include #include #include "cdp.h" #include "port.h" #include "cdpint.h" #include "cdpmod.h" #include "uio.h" #include "uqmversion.h" #ifdef WIN32 # include "windl.h" #else # include #endif #define MAX_CDPS 63 #define CDPDIR "cdps" // internal CDP module representation struct cdp_Module { bool builtin; // used at least once indicator bool used; // used at least once indicator void* hmodule; // loaded module handle uint32 refcount; // reference count cdp_ModuleInfo* info; // cdp exported info }; // Kernel module info // not a real module, and not loadable either // this just provides information to other modules cdp_ModuleInfo cdp_kernel_info = { sizeof (cdp_ModuleInfo), CDPAPI_VERSION, // API version we are using UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, CDP_MODINFO_RESERVED1, "UQM", // CDP context cannonical name "UQM Kernel", // CDP mod name # define S(i) #i // CDP mod version S(UQM_MAJOR_VERSION) "." S(UQM_MINOR_VERSION) UQM_EXTRA_VERSION, # undef S "UQM Team", // CDP mod author "http://sc2.sf.net", // CDP mod URL "Eternal doctrine executor", // CDP mod comment CDP_MODINFO_RESERVED2, NULL, NULL // no entrypoints defined/needed }; static cdp_Module cdp_modules[MAX_CDPS + 1] = { {true, true, NULL, 1, &cdp_kernel_info}, {false, false, NULL, 0, NULL} // term }; extern uio_DirHandle *cdpDir; static bool cdp_inited = false; static cdp_Error cdp_last_error = CDPERR_NONE; static char cdp_path[PATH_MAX] = ""; cdp_Error cdp_GetError (void) { cdp_Error ret = cdp_last_error; cdp_last_error = CDPERR_NONE; return ret; } bool cdp_Init (void) { int i; void* hkernel; if (cdp_inited) { fprintf (stderr, "cdp_Init(): called when already inited\n"); return true; } // preprocess built-in modules hkernel = dlopen (NULL, RTLD_LAZY); for (i = 0; cdp_modules[i].builtin; ++i) cdp_modules[i].hmodule = hkernel; // clear the rest //memset (cdp_modules + i, 0, // sizeof (cdp_modules) - sizeof (cdp_Module) * i); //strcpy (cdp_path, cdpDir->path); cdp_InitApi (); cdp_inited = true; return true; } void cdp_Uninit (void) { if (!cdp_inited) { fprintf (stderr, "cdp_Uninit(): called when not inited\n"); return; } cdp_UninitApi (); cdp_FreeAllModules (); cdp_inited = false; } cdp_Module* cdp_LoadModule (const char* modname) // special value for modname: NULL - refers to kernel (UQM exe) { void* mod; char modpath[PATH_MAX]; const char* errstr; cdp_ModuleInfo* info; int i; cdp_Module* cdp; cdp_Module* newslot = 0; cdp_Itf* ihost; if (modname == NULL) return cdp_modules; if (!cdp_inited) { fprintf (stderr, "cdp_LoadModule(): called when not inited\n"); return 0; } // load dynamic lib sprintf (modpath, "%s/%s%s", CDPDIR, modname, CDPEXT); mod = dlopen (modpath, RTLD_NOW); if (!mod) { cdp_last_error = CDPERR_NOT_FOUND; return NULL; } // look it up in already loaded for (i = 0, cdp = cdp_modules; cdp->used && cdp->hmodule != mod; ++cdp, ++i) { // and pick up an empty slot (where available) if (!newslot && !cdp->hmodule) newslot = cdp; } if (i >= MAX_CDPS) { fprintf (stderr, "cdp_LoadModule(): " "CDPs limit reached while loading %s\n", modname); dlclose (mod); cdp_last_error = CDPERR_TOO_MANY; return NULL; } if (cdp->hmodule) { // module has already been loaded cdp->refcount++; return cdp; } dlerror (); // clear any error info = dlsym (mod, CDP_INFO_SYM_NAME); if (!info && (errstr = dlerror ())) { dlclose (mod); cdp_last_error = CDPERR_BAD_MODULE; return NULL; } if (info->size < CDP_MODINFO_MIN_SIZE || info->api_ver > CDPAPI_VERSION) { fprintf (stderr, "cdp_LoadModule(): " "CDP %s is invalid or newer API version\n", modname); dlclose (mod); cdp_last_error = CDPERR_UNKNOWN_VER; return NULL; } ihost = cdp_GetInterface (CDPITF_KIND_HOST, info->api_ver); if (!ihost) { fprintf (stderr, "cdp_LoadModule(): " "CDP %s requested unsupported API version 0x%08x\n", modname, info->api_ver); dlclose (mod); cdp_last_error = CDPERR_UNKNOWN_VER; return NULL; } if (!newslot) { newslot = cdp; newslot->used = true; // make next one a term cdp[1].builtin = false; cdp[1].used = false; cdp[1].hmodule = NULL; cdp[1].refcount = 0; } newslot->hmodule = mod; newslot->refcount = 1; newslot->info = info; if (!info->module_init (newslot, (cdp_Itf_Host*)ihost)) { fprintf (stderr, "cdp_LoadModule(): " "CDP %s failed to init\n", modname); dlclose (mod); newslot->hmodule = NULL; newslot->info = NULL; newslot->refcount = 0; cdp_last_error = CDPERR_INIT_FAILED; return NULL; } return newslot; } cdp_Module* cdp_CheckModule (cdp_Module* module) { if (module < cdp_modules || module >= cdp_modules + MAX_CDPS || !module->hmodule || !module->info) return NULL; else return module; } void cdp_FreeModule (cdp_Module* module) { cdp_Module* modslot = cdp_CheckModule (module); if (!modslot || modslot->builtin) return; modslot->refcount--; if (modslot->refcount == 0) modslot->info->module_term (); dlclose (modslot->hmodule); if (modslot->refcount == 0) { modslot->hmodule = NULL; modslot->info = NULL; } } const char* cdp_GetModuleContext (cdp_Module* module, bool bMetaString) { cdp_Module* modslot = cdp_CheckModule (module); if (bMetaString) { if (!modslot) return "(Error)"; if (!modslot->info->context_name) return "(Null)"; } else if (!modslot) { return NULL; } return modslot->info->context_name; } const char* cdp_GetModuleName (cdp_Module* module, bool bMetaString) { cdp_Module* modslot = cdp_CheckModule (module); if (bMetaString) { if (!modslot) return "(Error)"; if (!modslot->info->name) return "(Null)"; } else if (!modslot) { return NULL; } return modslot->info->name; } uint32 cdp_GetModuleVersion (cdp_Module* module) { cdp_Module* modslot = cdp_CheckModule (module); if (!modslot) return 0; return (modslot->info->ver_major << 16) | modslot->info->ver_minor; } const char* cdp_GetModuleVersionString (cdp_Module* module, bool bMetaString) { cdp_Module* modslot = cdp_CheckModule (module); if (bMetaString) { if (!modslot) return "(Error)"; if (!modslot->info->ver_string) return "(Null)"; } else if (!modslot) { return NULL; } return modslot->info->ver_string; } const char* cdp_GetModuleComment (cdp_Module* module, bool bMetaString) { cdp_Module* modslot = cdp_CheckModule (module); if (bMetaString) { if (!modslot) return "(Error)"; if (!modslot->info->comments) return "(Null)"; } else if (!modslot) { return NULL; } return modslot->info->comments; } // load-all and free-all are here temporarily until // configs are in place int cdp_LoadAllModules (void) { uio_DirList *dirList; int nummods = 0; int i; if (!cdp_inited) { fprintf (stderr, "cdp_LoadAllModules(): called when not inited\n"); return 0; } if (!cdpDir) return 0; fprintf (stderr, "Loading all CDPs...\n"); dirList = uio_getDirList (cdpDir, "", CDPEXT, match_MATCH_SUFFIX); if (!dirList) return 0; for (i = 0; i < dirList->numNames; i++) { char modname[PATH_MAX]; char* pext; cdp_Module* mod; fprintf (stderr, "Loading CDP %s...\n", dirList->names[i]); strcpy (modname, dirList->names[i]); pext = strrchr (modname, '.'); if (pext) // strip extension *pext = 0; mod = cdp_LoadModule (modname); if (mod) { nummods++; fprintf (stderr, "\tloaded CDP: %s v%s (%s)\n", cdp_GetModuleName (mod, true), cdp_GetModuleVersionString (mod, true), cdp_GetModuleComment (mod, true)); } else { fprintf (stderr, "\tload failed, error %u\n", cdp_GetError ()); } } uio_freeDirList (dirList); return nummods; } void cdp_FreeAllModules (void) { cdp_Module* cdp; if (!cdp_inited) { fprintf (stderr, "cdp_FreeAllModules(): called when not inited\n"); return; } for (cdp = cdp_modules; cdp->used; ++cdp) { if (!cdp->builtin && cdp->hmodule) cdp_FreeModule (cdp); } } uqm-0.6.2/sc2/src/sc2code/libs/cdp/windl.c0000600000175000017500000000324210543202054016563 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP dlopen() & Co. WIN32 implementation */ #include "windl.h" #include "port.h" #define WIN32_LEAN_AND_MEAN //#include #include #include #include static uint32 wdl_last_error = 0; static char wdl_errstr[128] = ""; void* dlopen (const char *filename, int flag) // all defined flags are not possible on win32 { HMODULE hlib; if (filename == NULL) hlib = GetModuleHandleA(NULL); else hlib = LoadLibraryA (filename); if (!hlib) wdl_last_error = GetLastError (); return hlib; } void* dlsym (void *handle, const char *symbol) { void* ptr = GetProcAddress (handle, symbol); if (!ptr) wdl_last_error = GetLastError (); return ptr; } int dlclose (void *handle) { return FreeLibrary (handle); } char* dlerror (void) { if (wdl_last_error) { sprintf (wdl_errstr, "Windows error %u", wdl_last_error); wdl_last_error = 0; return wdl_errstr; } else return NULL; } uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdp_isnd.h0000600000175000017500000000254710543202054017245 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP Sound Interface */ #ifndef _CDPISND_H #define _CDPISND_H #include "types.h" #include "libs/sound/sound.h" #include "libs/sound/decoders/decoder.h" // CDP Sound Interface entry points typedef struct { TFB_RegSoundDecoder* (* RegisterDecoder) (const char* fileext, TFB_SoundDecoderFuncs*); void (* UnregisterDecoder) (TFB_RegSoundDecoder*); const TFB_SoundDecoderFuncs* (* LookupDecoder) (const char* fileext); } cdp_Itf_SoundVtbl_v1; // the following are for the sake of module writers typedef cdp_Itf_SoundVtbl_v1 cdp_Itf_SoundVtbl; typedef cdp_Itf_SoundVtbl cdp_Itf_Sound; #endif /* _CDPISND_H */ uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdp.h0000600000175000017500000000321710543202054016223 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP library declarations */ #ifndef _CDP_H #define _CDP_H #include "types.h" #include "cdpapi.h" // these will be called by the UQM engine // and plugins manager bool cdp_Init (void); void cdp_Uninit (void); cdp_Error cdp_GetError (void); cdp_Module* cdp_LoadModule (const char* modname); void cdp_FreeModule (cdp_Module* module); // in the following calls when bMetaString is set // function will never return a NULL, instead it will // return a valid string -- error meta-string const char* cdp_GetModuleContext (cdp_Module* module, bool bMetaString); const char* cdp_GetModuleName (cdp_Module* module, bool bMetaString); uint32 cdp_GetModuleVersion (cdp_Module* module); const char* cdp_GetModuleVersionString (cdp_Module* module, bool bMetaString); const char* cdp_GetModuleComment (cdp_Module* module, bool bMetaString); int cdp_LoadAllModules (void); void cdp_FreeAllModules (void); #endif /* _CDP_H */ uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdpmod.h0000600000175000017500000000563210543202054016726 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP module definitions * all CDP modules should #include this .h */ #ifndef _CDPMOD_H #define _CDPMOD_H #include "types.h" #include "cdpapi.h" #define CDP_INFO_SYM cdpmodinfo #define CDP_INFO_SYM_NAME "cdpmodinfo" // this struct will be exported from the module // under 'cdpmodinfo' typedef struct { // mandatory, version control uint32 size; // size of this structure cdp_ApiVersion api_ver; // version of cdp API used, set to CDPAPI_VERSION uint16 ver_major; // module version, somewhat informational uint16 ver_minor; uint16 ver_patch; uint16 host_ver_major; // minimum host version required, purely informational uint16 host_ver_minor; uint16 host_ver_patch; // reserved members: set all to 0 or use CDP_MODINFO_RESERVED1 uint32 _32_reserved1; uint32 _32_reserved2; uint32 _32_reserved3; uint32 _32_reserved4; const char* context_name; // cannonical context name (in proper case) // this context will be used with all exposed objects // English preferred; try to keep it below 32 chars // informational, human-only; these fields have no real size // restriction other than to keep it reasonable const char* name; // descriptive name const char* ver_string; // descriptive version const char* author; // go nuts const char* url; // go nuts const char* comments; // go nuts // reserved members, set all to 0 or use CDP_MODINFO_RESERVED2 const char* _sz_reserved1; const char* _sz_reserved2; const char* _sz_reserved3; const char* _sz_reserved4; // mandatory, CDP entry points // TODO: decide whether more EPs are necessary and if not move // EPs above info-string members, abolishing _sz_reservedX bool (* module_init) (cdp_Module* module, cdp_Itf_Host* hostitf); void (* module_term) (); } cdp_ModuleInfo; #define CDP_MODINFO_RESERVED1 0,0,0,0 #define CDP_MODINFO_RESERVED2 0,0,0,0 // the following is defined via the last mandatory member #define CDP_MODINFO_MIN_SIZE \ ( ((uint32) &((cdp_ModuleInfo*)0)->module_term) + \ sizeof (((cdp_ModuleInfo*)0)->module_term) ) #if defined(WIN32) # define CDPEXPORT __declspec(dllexport) #else # define CDPEXPORT #endif #endif /* _CDPMOD_H */ uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdpint.h0000600000175000017500000000263610543202054016742 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP common internal definitions */ #ifndef _CDPINT_H #define _CDPINT_H #include "cdpapi.h" #include "cdp_imem.h" #include "cdp_iio.h" #include "cdp_isnd.h" #include "cdp_ivid.h" #ifdef WIN32 # define CDPEXT ".dll" #else # define CDPEXT ".so" #endif extern cdp_Itf_HostVtbl_v1 cdp_host_itf_v1; extern cdp_Itf_MemoryVtbl_v1 cdp_memory_itf_v1; extern cdp_Itf_IoVtbl_v1 cdp_io_itf_v1; extern cdp_Itf_SoundVtbl_v1 cdp_sound_itf_v1; bool cdp_InitApi (void); void cdp_UninitApi (void); cdp_Error cdp_GetApiError (void); cdp_Itf* cdp_GetInterface (const char* name, cdp_ApiVersion); cdp_ItfReg* cdp_GetInterfaceReg (const char* name, cdp_ApiVersion); #endif /* _CDPISND_H */ uqm-0.6.2/sc2/src/sc2code/libs/cdp/Makeinfo0000600000175000017500000000003410543202054016752 0ustar joeyjoeyuqm_CFILES="cdp.c cdpapi.c" uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdp_iio.h0000600000175000017500000000310610543202054017060 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP Unified IO Interface */ #ifndef _CDPIIO_H #define _CDPIIO_H #include "types.h" #include "libs/uio.h" // CDP IO Interface entry points typedef struct { uio_Stream* (* fopen) (uio_DirHandle *dir, const char *path, const char *mode); int (* fclose) (uio_Stream *stream); size_t (* fread) (void *buf, size_t size, size_t nmemb, uio_Stream *stream); size_t (* fwrite) (const void *buf, size_t size, size_t nmemb, uio_Stream *stream); int (* fseek) (uio_Stream *stream, long offset, int whence); long (* ftell) (uio_Stream *stream); int (* fflush) (uio_Stream *stream); int (* feof) (uio_Stream *stream); int (* ferror) (uio_Stream *stream); } cdp_Itf_IoVtbl_v1; // the following are for the sake of module writers typedef cdp_Itf_IoVtbl_v1 cdp_Itf_IoVtbl; typedef cdp_Itf_IoVtbl cdp_Itf_Io; #endif /* _CDPIIO_H */ uqm-0.6.2/sc2/src/sc2code/libs/cdp/cdp_alli.h0000600000175000017500000000176610543202054017233 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* * CDP All-interface list (for simplicity) */ #ifndef _CDPALLI_H #define _CDPALLI_H #include "cdp_iio.h" #include "cdp_imem.h" #include "cdp_isnd.h" #include "cdp_ivid.h" // TODO: add more cdp_iXXX.h here as they are defined #endif /* _CDPALLI_H */ uqm-0.6.2/sc2/src/sc2code/libs/platform.h0000644000175000017500000000264310552135701016551 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef PLATFORM_H_ #define PLATFORM_H_ #if defined(USE_PLATFORM_ACCEL) # if defined(__GNUC__) && (defined(i386) || defined(__x86_64__)) # define MMX_ASM # define GCC_ASM # elif (_MSC_VER >= 1100) && defined(_M_IX86) // All 32bit AMD chips are IX86 equivalents // We do not enable MSVC/MMX_ASM for _M_AMD64 as of now # define MMX_ASM # define MSVC_ASM # endif // other realistic possibilities for MSVC compiler are // _M_AMD64 (AMD x86-64), _M_IA64 (Intel Arch 64) #endif typedef enum { PLATFORM_NULL = 0, PLATFORM_C, PLATFORM_MMX, PLATFORM_SSE, PLATFORM_3DNOW, PLATFORM_ALTIVEC, PLATFORM_LAST = PLATFORM_ALTIVEC } PLATFORM_TYPE; extern PLATFORM_TYPE force_platform; #endif /* PLATFORM_H_ */ uqm-0.6.2/sc2/src/sc2code/libs/heap/0000755000175000017500000000000010552600274015466 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/heap/heap.h0000600000175000017500000000375110543202055016545 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _HEAP_H #define _HEAP_H #include "types.h" #include #include typedef struct Heap Heap; typedef struct HeapValue HeapValue; // The actual value stored should "inherit" from this. struct HeapValue { size_t index; }; typedef int (*HeapValue_Comparator)(HeapValue *v1, HeapValue *v2); struct Heap { HeapValue_Comparator comparator; // Comparison function to determine the order of the // elements. size_t minSize; // Never resize below this many number of entries. double minFillQuotient; // How much of half of the heap needs to be filled before // resizing to size/2. HeapValue **entries; // Actual values size_t numEntries; size_t size; // Number of entries that fit in the heap as it is now. size_t minFill; // Resize to size/2 when below this size. }; Heap *Heap_new(HeapValue_Comparator comparator, size_t initialSize, size_t minSize, double minFillQuotient); void Heap_delete(Heap *heap); void Heap_add(Heap *heap, HeapValue *value); HeapValue *Heap_first(const Heap *heap); HeapValue *Heap_pop(Heap *heap); size_t Heap_count(const Heap *heap); bool Heap_hasMore(const Heap *heap); void Heap_remove(Heap *heap, HeapValue *value); #endif /* _HEAP_H */ uqm-0.6.2/sc2/src/sc2code/libs/heap/heap.c0000600000175000017500000001053210543202055016533 0ustar joeyjoey/* * Copyright 2006 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "heap.h" #include #include #include #include "port.h" static inline size_t nextPower2(size_t x); static void Heap_resize(Heap *heap, size_t size) { heap->entries = realloc(heap->entries, size * sizeof (HeapValue *)); heap->size = size; } // Heap inv: comparator(parent, child) <= 0 for every child of every parent. Heap * Heap_new(HeapValue_Comparator comparator, size_t initialSize, size_t minSize, double minFillQuotient) { Heap *heap; assert(minFillQuotient >= 0.0); heap = malloc(sizeof (Heap)); if (initialSize < minSize) initialSize = minSize; heap->comparator = comparator; heap->minSize = minSize; heap->minFillQuotient = minFillQuotient; heap->size = nextPower2(initialSize); heap->minFill = (size_t) ceil(((double) (heap->size >> 1)) * heap->minFillQuotient); heap->entries = malloc(heap->size * sizeof (HeapValue *)); heap->numEntries = 0; return heap; } void Heap_delete(Heap *heap) { free(heap->entries); free(heap); } void Heap_add(Heap *heap, HeapValue *value) { size_t i; if (heap->numEntries >= heap->size) Heap_resize(heap, heap->size * 2); i = heap->numEntries; heap->numEntries++; while (i > 0) { size_t parentI = (i - 1) / 2; if (heap->comparator(heap->entries[parentI], value) <= 0) break; heap->entries[i] = heap->entries[parentI]; heap->entries[i]->index = i; i = parentI; } heap->entries[i] = value; heap->entries[i]->index = i; } HeapValue * Heap_first(const Heap *heap) { assert(heap->numEntries > 0); return heap->entries[0]; } static void Heap_removeByIndex(Heap *heap, size_t i) { assert(heap->numEntries > i); heap->numEntries--; if (heap->numEntries != 0) { // Restore the heap invariant. We're shifting entries into the // gap that was created until we find the place where we can // insert the last entry. for (;;) { size_t childI = i * 2 + 1; // The two children are childI and 'childI + 1'. if (childI + 1 >= heap->numEntries) { // There is no right child. if (childI >= heap->numEntries) { // There is no left child either. break; } if (heap->comparator(heap->entries[childI + 1], heap->entries[childI]) < 0) { // The right child is the child with the lowest value. childI++; } } // childI is now the child with the lowest value. if (heap->comparator(heap->entries[heap->numEntries], heap->entries[childI]) <= 0) { // The last entry goes here. break; } // Move the child into the gap. heap->entries[i] = heap->entries[childI]; heap->entries[i]->index = i; // and repeat for the child. i = childI; } // Fill the gap with the last entry. heap->entries[i] = heap->entries[heap->numEntries]; heap->entries[i]->index = i; } // Resize if necessary: if (heap->numEntries < heap->minFill && heap->numEntries > heap->minSize) Heap_resize(heap, heap->size / 2); } HeapValue * Heap_pop(Heap *heap) { HeapValue *result; assert(heap->numEntries > 0); result = heap->entries[0]; Heap_removeByIndex(heap, 0); return result; } size_t Heap_count(const Heap *heap) { return heap->numEntries; } bool Heap_hasMore(const Heap *heap) { return heap->numEntries > 0; } void Heap_remove(Heap *heap, HeapValue *value) { Heap_removeByIndex(heap, value->index); } // Adapted from "Hackers Delight" // Returns the smallest power of two greater or equal to x. static inline size_t nextPower2(size_t x) { x--; x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; # if (SIZE_MAX > 0xffff) x |= x >> 16; # if (SIZE_MAX > 0xffffffff) x |= x >> 32; # endif # endif return x + 1; } uqm-0.6.2/sc2/src/sc2code/libs/heap/Makeinfo0000600000175000017500000000002510543202055017122 0ustar joeyjoeyuqm_CFILES="heap.c" uqm-0.6.2/sc2/src/sc2code/libs/Makeinfo0000600000175000017500000000053510543202055016213 0ustar joeyjoeyuqm_SUBDIRS="callback decomp file graphics heap input list math memory resource sound strings task threads time uio video log" if [ -n "$uqm_USE_INTERNAL_MIKMOD" ]; then uqm_SUBDIRS="$uqm_SUBDIRS mikmod" fi if [ -n "$uqm_NETPLAY" ]; then uqm_SUBDIRS="$uqm_SUBDIRS network" fi #if [ "$DEBUG" = 1 ]; then # uqm_SUBDIRS="$UQM_SUBDIRS debug" #fi uqm-0.6.2/sc2/src/sc2code/libs/task/0000755000175000017500000000000010552600274015513 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/task/tasklib.c0000600000175000017500000000621310543202043017272 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Michael Martin, 2002-09-21 */ #include #include #include "libs/tasklib.h" #include "libs/log.h" #define TASK_MAX 64 static struct taskstruct task_array[TASK_MAX]; Task AssignTask (ThreadFunction task_func, SDWORD stackSize, const char *name) { int i; for (i = 0; i < TASK_MAX; ++i) { if (!Task_SetState (task_array+i, TASK_INUSE)) { // log_add (log_Debug, "Assigning Task #%i: %s", i+1, name); Task_ClearState (task_array+i, ~TASK_INUSE); task_array[i].name = name; task_array[i].thread = CreateThread (task_func, task_array+i, stackSize, name); return task_array+i; } } log_add (log_Error, "Task error! Task array exhausted. Check for thread leaks."); return NULL; } void FinishTask (Task task) { // log_add (log_Debug, "Releasing Task: %s", task->name); task->thread = 0; if (!Task_ClearState (task, TASK_INUSE)) { log_add (log_Debug, "Task error! Attempted to FinishTask '%s'... " "but it was already done!", task->name); } } /* This could probably be done better with a condition variable of some kind. */ void ConcludeTask (Task task) { Thread old = task->thread; // log_add (log_Debug, "Awaiting conclusion of %s", task->name); if (old) { Task_SetState (task, TASK_EXIT); while (task->thread == old) { TaskSwitch (); } } } DWORD Task_SetState (Task task, DWORD state_mask) { DWORD old_state; LockMutex (task->state_mutex); old_state = task->state; task->state |= state_mask; UnlockMutex (task->state_mutex); old_state &= state_mask; return old_state; } DWORD Task_ClearState (Task task, DWORD state_mask) { DWORD old_state; LockMutex (task->state_mutex); old_state = task->state; task->state &= ~state_mask; UnlockMutex (task->state_mutex); old_state &= state_mask; return old_state; } DWORD Task_ToggleState (Task task, DWORD state_mask) { DWORD old_state; LockMutex (task->state_mutex); old_state = task->state; task->state ^= state_mask; UnlockMutex (task->state_mutex); old_state &= state_mask; return old_state; } DWORD Task_ReadState (Task task, DWORD state_mask) { return task->state & state_mask; } void InitTaskSystem (void) { int i; for (i = 0; i < TASK_MAX; ++i) { task_array[i].state_mutex = CreateMutex ("task manager lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_RESOURCE); } atexit (CleanupTaskSystem); } void CleanupTaskSystem (void) { int i; for (i = 0; i < TASK_MAX; ++i) { DestroyMutex (task_array[i].state_mutex); } } uqm-0.6.2/sc2/src/sc2code/libs/task/Makeinfo0000600000175000017500000000002710543202043017146 0ustar joeyjoeyuqm_CFILES="tasklib.c" uqm-0.6.2/sc2/src/sc2code/libs/inplib.h0000600000175000017500000000340710543202055016166 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _INPLIB_H #define _INPLIB_H #include "memlib.h" #include #include "libs/uio.h" typedef DWORD INPUT_STATE; extern BOOLEAN InitInput (void); extern BOOLEAN UninitInput (void); extern BOOLEAN AnyButtonPress (BOOLEAN DetectSpecial); extern void FlushInput (void); /* * Not used right now extern BOOLEAN FindMouse (void); extern void MoveMouse (SWORD x, SWORD y); extern BYTE LocateMouse (PSWORD px, PSWORD py); */ extern volatile int MouseButtonDown; /* Functions for dealing with Character Mode */ void EnableCharacterMode (void); void DisableCharacterMode (void); wchar_t GetNextCharacter (void); wchar_t GetLastCharacter (void); /* Interrogating the current key configuration */ void InterrogateInputState (int template, int control, int index, char *buffer, int maxlen); void RemoveInputState (int template, int control, int index); void RebindInputState (int template, int control, int index); void SaveKeyConfiguration (uio_DirHandle *path, const char *fname); #endif /* _INPLIB_H */ uqm-0.6.2/sc2/src/sc2code/libs/file.h0000644000175000017500000000477310546776502015667 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Contains file handling code #ifndef _FILE_H #define _FILE_H #include "port.h" // for bool #include "types.h" // from temp.h #include "libs/uio.h" void initTempDir (void); void unInitTempDir (void); char *tempFilePath (const char *filename); extern uio_DirHandle *tempDir; // from dirs.h int mkdirhier (const char *path); const char *getHomeDir (void); int createDirectory (const char *dir, int mode); int expandPath (char *dest, size_t len, const char *src, int what); // values for 'what': #define EP_HOME 1 // Expand '~' for home dirs. #define EP_ABSOLUTE 2 // Make paths absolute #define EP_ENVVARS 4 // Expand environment variables. #define EP_DOTS 8 // Process ".." and "." #define EP_SLASHES 16 // Consider backslashes as path component separators. // They will be replaced by slashes. Windows UNC paths will always // start with "\\server\share", with backslashes. #define EP_SINGLESEP 32 // Replace multiple consecutive path separators by a single one. #define EP_ALL (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | EP_SLASHES \ EP_SINGLESEP) // Everything // Everything except Windows style backslashes on Unix Systems: #ifdef WIN32 # define EP_ALL_SYSTEM (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | \ EP_SLASHES | EP_SINGLESEP) #else # define EP_ALL_SYSTEM (EP_HOME | EP_ENVVARS | EP_ABSOLUTE | EP_DOTS | \ EP_SINGLESEP) #endif // from files.h int copyFile (uio_DirHandle *srcDir, const char *srcName, uio_DirHandle *dstDir, const char *newName); bool fileExists (const char *name); bool fileExists2(uio_DirHandle *dir, const char *fileName); #ifdef WIN32 size_t skipUNCServerShare(const char *inPath); #endif #ifdef WIN32 static inline int isDriveLetter(int c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } #endif #endif /* _FILE_H */ uqm-0.6.2/sc2/src/sc2code/libs/uioutils.h0000600000175000017500000000157710543202055016574 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _UIOUTILS_H #define _UIOUTILS_H #include "uio/utils.h" #endif /* _UIOUTILS_H */ uqm-0.6.2/sc2/src/sc2code/libs/threadlib.h0000600000175000017500000001314210543202055016644 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* By Serge van den Boom, 2002-09-12 */ #ifndef _THREADLIB_H #define _THREADLIB_H #define THREADLIB SDL #define NAMED_SYNCHRO /* Should synchronizable objects have names? */ #define TRACK_CONTENTION /* Should we report when a thread sleeps on synchronize? */ /* TRACK_CONTENTION implies NAMED_SYNCHRO. */ #ifdef TRACK_CONTENTION # ifndef NAMED_SYNCHRO # define NAMED_SYNCHRO # endif #endif /* TRACK_CONTENTION */ #ifdef DEBUG # ifndef DEBUG_THREADS # define DEBUG_THREADS # endif #endif /* DEBUG */ #ifdef DEBUG_THREADS //# ifndef PROFILE_THREADS //# define PROFILE_THREADS //# endif #endif /* DEBUG_THREADS */ #include #include "libs/timelib.h" #if defined (PROFILE_THREADS) || defined (DEBUG_THREADS) #define THREAD_NAMES #endif void InitThreadSystem (void); void UnInitThreadSystem (void); typedef int (*ThreadFunction) (void *); typedef void *Thread; typedef void *Mutex; typedef void *Semaphore; typedef void *RecursiveMutex; typedef void *CondVar; /* Local data associated with each thread */ typedef struct _threadLocal { Semaphore flushSem; } ThreadLocal; /* The classes of synchronization objects */ enum { SYNC_CLASS_TOPLEVEL = (1 << 0), /* Exposed to the game logic */ SYNC_CLASS_AUDIO = (1 << 1), /* Involves the audio system */ SYNC_CLASS_VIDEO = (1 << 2), /* Involves the video system. Very noisy because of FlushGraphics(). */ SYNC_CLASS_RESOURCE = (1 << 3) /* Involves system resources (_MemoryLock) */ }; /* Note. NEVER call CreateThread from the main thread, or deadlocks are guaranteed. Use StartThread instead (which doesn't wait around for the main thread to actually create the thread and return it). */ #ifdef NAMED_SYNCHRO /* Logical OR of all classes we want to track. */ #define TRACK_CONTENTION_CLASSES (SYNC_CLASS_TOPLEVEL) /* Prototypes with the "name" field */ Thread CreateThread_Core (ThreadFunction func, void *data, SDWORD stackSize, const char *name); void StartThread_Core (ThreadFunction func, void *data, SDWORD stackSize, const char *name); Semaphore CreateSemaphore_Core (DWORD initial, const char *name, DWORD syncClass); Mutex CreateMutex_Core (const char *name, DWORD syncClass); RecursiveMutex CreateRecursiveMutex_Core (const char *name, DWORD syncClass); CondVar CreateCondVar_Core (const char *name, DWORD syncClass); /* Preprocessor directives to forward to the appropriate routines */ #define CreateThread(func, data, stackSize, name) \ CreateThread_Core ((func), (data), (stackSize), (name)) #define StartThread(func, data, stackSize, name) \ StartThread_Core ((func), (data), (stackSize), (name)) #define CreateSemaphore(initial, name, syncClass) \ CreateSemaphore_Core ((initial), (name), (syncClass)) #define CreateMutex(name, syncClass) \ CreateMutex_Core ((name), (syncClass)) #define CreateRecursiveMutex(name, syncClass) \ CreateRecursiveMutex_Core((name), (syncClass)) #define CreateCondVar(name, syncClass) \ CreateCondVar_Core ((name), (syncClass)) #else /* Prototypes without the "name" field. */ Thread CreateThread_Core (ThreadFunction func, void *data, SDWORD stackSize); void StartThread_Core (ThreadFunction func, void *data, SDWORD stackSize); Semaphore CreateSemaphore_Core (DWORD initial); Mutex CreateMutex_Core (void); RecursiveMutex CreateRecursiveMutex_Core (void); CondVar CreateCondVar_Core (void); /* Preprocessor directives to forward to the appropriate routines. The "name" field is stripped away in preprocessing. */ #define CreateThread(func, data, stackSize, name) \ CreateThread_Core ((func), (data), (stackSize)) #define StartThread(func, data, stackSize, name) \ StartThread_Core ((func), (data), (stackSize)) #define CreateSemaphore(initial, name, syncClass) \ CreateSemaphore_Core ((initial)) #define CreateMutex(name, syncClass) \ CreateMutex_Core () #define CreateRecursiveMutex(name, syncClass) \ CreateRecursiveMutex_Core() #define CreateCondVar(name, syncClass) \ CreateCondVar_Core () #endif ThreadLocal *CreateThreadLocal (void); void DestroyThreadLocal (ThreadLocal *tl); ThreadLocal *GetMyThreadLocal (void); void SleepThread (TimePeriod timePeriod); void SleepThreadUntil (TimeCount wakeTime); void DestroyThread (Thread); void TaskSwitch (void); void WaitThread (Thread thread, int *status); void FinishThread (Thread); void ProcessThreadLifecycles (void); #ifdef PROFILE_THREADS void PrintThreadsStats (void); #endif /* PROFILE_THREADS */ void DestroySemaphore (Semaphore sem); void SetSemaphore (Semaphore sem); void ClearSemaphore (Semaphore sem); void DestroyMutex (Mutex sem); void LockMutex (Mutex sem); void UnlockMutex (Mutex sem); void DestroyRecursiveMutex (RecursiveMutex m); void LockRecursiveMutex (RecursiveMutex m); void UnlockRecursiveMutex (RecursiveMutex m); int GetRecursiveMutexDepth (RecursiveMutex m); void DestroyCondVar (CondVar); void WaitCondVar (CondVar); void SignalCondVar (CondVar); void BroadcastCondVar (CondVar); #endif /* _THREADLIB_H */ uqm-0.6.2/sc2/src/sc2code/libs/uio.h0000600000175000017500000000155510543202055015507 0ustar joeyjoey/* * Copyright (C) 2003 Serge van den Boom * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * Nota bene: later versions of the GNU General Public License do not apply * to this program. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifndef _UIO_H #define _UIO_H #include "uio/io.h" #endif /* _UIO_H */ uqm-0.6.2/sc2/src/sc2code/libs/gfxlib.h0000644000175000017500000002051310552135701016174 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GFXLIB_H #define _GFXLIB_H #include "memlib.h" #define CONTEXT PVOID #define FRAME PVOID #define FONT PVOID typedef CONTEXT *PCONTEXT; typedef FRAME *PFRAME; typedef FONT *PFONT; typedef UWORD TIME_VALUE; typedef TIME_VALUE *PTIME_VALUE; #define TIME_SHIFT 8 #define MAX_TIME_VALUE ((1 << TIME_SHIFT) + 1) typedef SWORD COORD; typedef COORD *PCOORD; typedef DWORD COLOR; typedef COLOR *PCOLOR; #define BUILD_COLOR(c32k,c256) \ (COLOR)(((DWORD)(c32k)<<8)|(BYTE)(c256)) // BUILD_COLOR combines a 15-bit RGB color tripple with a // destination VGA palette index into a 32-bit value. // It is a remnant of 8bpp hardware paletted display (VGA). // The palette index would be overwritten with the RGB value // and the drawing op would use this index on screen. // The palette indices 0-15, as used in DOS SC2, are unchanged // from the standard VGA palette and are identical to 16-color EGA. // Various frames, borders, menus, etc. frequently refer to these // first 16 colors and normally do not change the RGB values from // the standard ones (see colors.h; most likely unchanged from SC1) // The palette index is meaningless in UQM for the most part. // New code should just use index 0. #define COLOR_32k(c) (UWORD)((COLOR)(c)>>8) #define COLOR_256(c) LOBYTE((COLOR)c) #define MAKE_RGB15(r,g,b) (UWORD)(((r)<<10)|((g)<<5)|(b)) #define BUILD_COLOR_RGBA(r,g,b,a) (DWORD)(((r)<<24)|((g)<<16)|((b)<<8)|(a)) typedef BYTE CREATE_FLAGS; #define WANT_MASK (CREATE_FLAGS)(1 << 0) #define WANT_PIXMAP (CREATE_FLAGS)(1 << 1) #define MAPPED_TO_DISPLAY (CREATE_FLAGS)(1 << 2) #define WANT_ALPHA (CREATE_FLAGS)(1 << 3) typedef struct extent { COORD width, height; } EXTENT; typedef EXTENT *PEXTENT; typedef struct point { COORD x, y; } POINT; typedef POINT *PPOINT; typedef struct stamp { POINT origin; FRAME frame; } STAMP; typedef STAMP *PSTAMP; typedef struct rect { POINT corner; EXTENT extent; } RECT; typedef RECT *PRECT; typedef struct line { POINT first, second; } LINE; typedef LINE *PLINE; typedef enum { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT } TEXT_ALIGN; typedef enum { VALIGN_TOP, VALIGN_MIDDLE, VALIGN_BOTTOM } TEXT_VALIGN; typedef struct text { POINT baseline; const UNICODE *pStr; TEXT_ALIGN align; COUNT CharCount; } TEXT; typedef TEXT *PTEXT; #include "strlib.h" typedef STRING_TABLE COLORMAP_REF; typedef STRING COLORMAP; typedef STRINGPTR COLORMAPPTR; #include "graphics/prim.h" typedef BYTE BATCH_FLAGS; #define BATCH_BUILD_PAGE (BATCH_FLAGS)(1 << 0) #define BATCH_SINGLE (BATCH_FLAGS)(1 << 1) typedef struct { TIME_VALUE last_time_val; POINT EndPoint; STAMP IntersectStamp; } INTERSECT_CONTROL; typedef INTERSECT_CONTROL *PINTERSECT_CONTROL; typedef MEM_HANDLE CONTEXT_REF; typedef CONTEXT_REF *PCONTEXT_REF; typedef DWORD DRAWABLE; typedef DRAWABLE *PDRAWABLE; #define BUILD_DRAWABLE(h,i) ((DRAWABLE)MAKE_DWORD(h,i)) typedef MEM_HANDLE FONT_REF; typedef FONT_REF *PFONT_REF; typedef BYTE INTERSECT_CODE; #define INTERSECT_LEFT (INTERSECT_CODE)(1 << 0) #define INTERSECT_TOP (INTERSECT_CODE)(1 << 1) #define INTERSECT_RIGHT (INTERSECT_CODE)(1 << 2) #define INTERSECT_BOTTOM (INTERSECT_CODE)(1 << 3) #define INTERSECT_NOCLIP (INTERSECT_CODE)(1 << 7) #define INTERSECT_ALL_SIDES (INTERSECT_CODE)(INTERSECT_LEFT | \ INTERSECT_TOP | \ INTERSECT_RIGHT | \ INTERSECT_BOTTOM) typedef POINT HOT_SPOT; extern HOT_SPOT MAKE_HOT_SPOT (COORD, COORD); extern INTERSECT_CODE BoxIntersect (PRECT pr1, PRECT pr2, PRECT printer); extern void BoxUnion (PRECT pr1, PRECT pr2, PRECT punion); enum { FadeAllToWhite = 250, FadeSomeToWhite, FadeAllToBlack, FadeAllToColor, FadeSomeToBlack, FadeSomeToColor }; #endif /* _GFXLIB_H */ #ifndef _GFX_PROTOS #define _GFX_PROTOS extern BOOLEAN InitGraphics (int argc, char *argv[], COUNT KbytesRequired); extern void UninitGraphics (void); extern CONTEXT SetContext (CONTEXT Context); extern CONTEXT CaptureContext (CONTEXT_REF ContextRef); extern CONTEXT_REF ReleaseContext (CONTEXT Context); extern COLOR SetContextForeGroundColor (COLOR Color); extern COLOR SetContextBackGroundColor (COLOR Color); extern FRAME SetContextFGFrame (FRAME Frame); extern BOOLEAN SetContextClipping (BOOLEAN ClipStatus); extern BOOLEAN SetContextClipRect (PRECT pRect); extern BOOLEAN GetContextClipRect (PRECT pRect); extern TIME_VALUE DrawablesIntersect (PINTERSECT_CONTROL pControl0, PINTERSECT_CONTROL pControl1, TIME_VALUE max_time_val); extern void DrawStamp (PSTAMP pStamp); extern void DrawFilledStamp (PSTAMP pStamp); extern void DrawPoint (PPOINT pPoint); extern void DrawRectangle (PRECT pRect); extern void DrawFilledRectangle (PRECT pRect); extern void DrawLine (PLINE pLine); extern void font_DrawText (PTEXT pText); extern void DrawBatch (PPRIMITIVE pBasePrim, PRIM_LINKS PrimLinks, BATCH_FLAGS BatchFlags); extern void BatchGraphics (void); extern void UnbatchGraphics (void); extern void FlushGraphics (void); extern void ClearBackGround (PRECT pClipRect); extern void ClearDrawable (void); extern CONTEXT_REF CreateContext (void); extern BOOLEAN DestroyContext (CONTEXT_REF ContextRef); extern DRAWABLE CreateDisplay (CREATE_FLAGS CreateFlags, PSIZE pwidth, PSIZE pheight); extern DRAWABLE CreateDrawable (CREATE_FLAGS CreateFlags, SIZE width, SIZE height, COUNT num_frames); extern BOOLEAN DestroyDrawable (DRAWABLE Drawable); extern BOOLEAN GetFrameRect (FRAME Frame, PRECT pRect); extern HOT_SPOT SetFrameHot (FRAME Frame, HOT_SPOT HotSpot); extern HOT_SPOT GetFrameHot (FRAME Frame); extern BOOLEAN InstallGraphicResTypes (COUNT cel_type, COUNT font_type); extern DWORD LoadCelFile (PVOID pStr); extern DWORD LoadFontFile (PVOID pStr); extern DWORD LoadGraphicInstance (DWORD res); extern DRAWABLE LoadDisplayPixmap (PRECT area, FRAME frame); extern FRAME SetContextFontEffect (FRAME EffectFrame); extern FONT SetContextFont (FONT Font); extern BOOLEAN DestroyFont (FONT_REF FontRef); extern FONT CaptureFont (FONT_REF FontRef); extern FONT_REF ReleaseFont (FONT Font); extern BOOLEAN TextRect (PTEXT pText, PRECT pRect, PBYTE pdelta); extern BOOLEAN GetContextFontLeading (PSIZE pheight); extern BOOLEAN GetContextFontLeadingWidth (PSIZE pwidth); extern COUNT GetFrameCount (FRAME Frame); extern COUNT GetFrameIndex (FRAME Frame); extern FRAME SetAbsFrameIndex (FRAME Frame, COUNT FrameIndex); extern FRAME SetRelFrameIndex (FRAME Frame, SIZE FrameOffs); extern FRAME SetEquFrameIndex (FRAME DstFrame, FRAME SrcFrame); extern FRAME IncFrameIndex (FRAME Frame); extern FRAME DecFrameIndex (FRAME Frame); extern DRAWABLE RotateFrame (FRAME Frame, COUNT angle); extern void SetFrameTransparentColor (FRAME Frame, COLOR c32k); extern FRAME CaptureDrawable (DRAWABLE Drawable); extern DRAWABLE ReleaseDrawable (FRAME Frame); extern MEM_HANDLE GetFrameHandle (FRAME Frame); extern BOOLEAN SetColorMap (COLORMAPPTR ColorMapPtr); extern DWORD XFormColorMap (COLORMAPPTR ColorMapPtr, SIZE TimeInterval); extern void FlushColorXForms (void); #define InitColorMapResources InitStringTableResources #define LoadColorMapFile LoadStringTableFile #define LoadColorMapInstance LoadStringTableInstance #define CaptureColorMap CaptureStringTable #define ReleaseColorMap ReleaseStringTable #define DestroyColorMap DestroyStringTable #define GetColorMapRef GetStringTable #define GetColorMapCount GetStringTableCount #define GetColorMapIndex GetStringTableIndex #define SetAbsColorMapIndex SetAbsStringTableIndex #define SetRelColorMapIndex SetRelStringTableIndex #define GetColorMapLength GetStringLengthBin #define GetColorMapAddress GetStringAddress #define GetColorMapContents GetStringContents void SetSystemRect (PRECT pRect); void ClearSystemRect (void); #endif /* _GFX_PROTOS */ uqm-0.6.2/sc2/src/sc2code/libs/math/0000755000175000017500000000000010552600274015502 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/math/random.c0000600000175000017500000000617610543202041017116 0ustar joeyjoey///Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /**************************************************************************** * FILE: random.c * DESC: a library of random number generators for general purpose use. * * References: * "Random Number Generators: Good ones are hard to find" S.K.Park & K.W.Miller * Communications of the ACM, Vol31 Number 10, October 1988, Pp 1192-1201 * * HISTORY: Created 1/23/1989 * LAST CHANGED: * * Copyright (c) 1989, Robert Leyland and Fred Ford ****************************************************************************/ /* ----------------------------INCLUDES----------------------------------- */ #include "mthintrn.h" /* get the externs for error checking */ /* ----------------------------DEFINES------------------------------------ */ /* constants for licongruential random number generator from CACM article referenced above */ #define A 16807 /* a relatively prime number -- also M div Q */ #define M 2147483647L /* 0xFFFFFFFF / 2 */ #define Q 127773L /* M div A */ #define R 2836 /* M mod A */ /* ----------------------------STATIC DATA-------------------------------- */ static DWORD seed = 12345L; /* random number seed */ /* ----------------------------CODE--------------------------------------- */ /***************************************************************************** * FUNC: DWORD TFB_Random() * * DESC: random number generator * * NOTES: * * HISTORY: Created By Robert leyland * *****************************************************************************/ DWORD TFB_Random (void) { if ((seed = A * (seed % Q) - R * (seed / Q)) > M) return (seed -= M); else if (seed) return (seed); else return (seed = 1L); } /***************************************************************************** * FUNC: DWORD TFB_SeedRandom(DWORD l) * * DESC: set the seed for the random number generator to parameter "l", and * return the value of the previously active seed, to allow for multiple * random number streams. * * NOTES: if the seed is not valid it will be coerced into a valid range * * HISTORY: Created By Robert leyland * *****************************************************************************/ DWORD TFB_SeedRandom (DWORD new_seed) { DWORD old_seed; /* coerce the seed to be in the range 1..M */ if (new_seed == 0L) /* 0 becomes 1 */ new_seed = 1; else if (new_seed > M) /* and less than M */ new_seed -= M; old_seed = seed; seed = new_seed; return (old_seed); } uqm-0.6.2/sc2/src/sc2code/libs/math/mthintrn.h0000600000175000017500000000154510543202041017501 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _MTHINTRN_H #define _MTHINTRN_H #include "mathlib.h" #endif /* _MTHINTRN_H */ uqm-0.6.2/sc2/src/sc2code/libs/math/random.h0000600000175000017500000000273210543202041017115 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /**************************************************************************** * FILE: random.h * DESC: definitions and externs for random number generators * * HISTORY: Created 6/ 6/1989 * LAST CHANGED: * * Copyright (c) 1989, Robert Leyland and Scott Anderson ****************************************************************************/ /* ----------------------------DEFINES------------------------------------ */ #define RAND(n) ( (int) ( (unsigned int)TFB_Random() % (n) ) ) #define SRAND(n) ( (int)TFB_Random() % (n) ) #define AND_RAND(n) ( (int)TFB_Random() & (n) ) /* ----------------------------GLOBALS/EXTERNS---------------------------- */ DWORD TFB_SeedRandom (DWORD seed); DWORD TFB_Random (void); uqm-0.6.2/sc2/src/sc2code/libs/math/sqrt.c0000600000175000017500000000413410543202042016620 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "mthintrn.h" COUNT square_root (DWORD value) { UWORD sig_word, mask; COUNT result, shift; if ((sig_word = HIWORD (value)) > 0) { DWORD mask_squared, result_shift; for (mask = 1 << 15, shift = 31; !(mask & sig_word); mask >>= 1, --shift) ; shift >>= 1; mask = 1 << shift; result = mask; mask_squared = result_shift = (DWORD)mask << shift; value -= mask_squared; while (mask >>= 1) { DWORD remainder; mask_squared >>= 1; mask_squared >>= 1; if ((remainder = result_shift + mask_squared) > value) result_shift >>= 1; else { value -= remainder; result_shift = (result_shift >> 1) + mask_squared; result |= mask; } } return (result); } else if ((sig_word = LOWORD (value)) > 0) { UWORD mask_squared, result_shift; for (mask = 1 << 15, shift = 15; !(mask & sig_word); mask >>= 1, --shift) ; shift >>= 1; mask = 1 << shift; result = mask; mask_squared = result_shift = mask << shift; sig_word -= mask_squared; while (mask >>= 1) { UWORD remainder; mask_squared >>= 1; mask_squared >>= 1; if ((remainder = result_shift + mask_squared) > sig_word) result_shift >>= 1; else { sig_word -= remainder; result_shift = (result_shift >> 1) + mask_squared; result |= mask; } } return (result); } return (0); } uqm-0.6.2/sc2/src/sc2code/libs/math/Makeinfo0000600000175000017500000000003510543202041017132 0ustar joeyjoeyuqm_CFILES="random.c sqrt.c" uqm-0.6.2/sc2/src/sc2code/libs/strlib.h0000600000175000017500000000704610543202055016213 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _STRLIB_H #define _STRLIB_H #include "compiler.h" #include "port.h" #include "libs/uio.h" #include typedef DWORD STRING_TABLE; typedef DWORD STRING; typedef PBYTE STRINGPTR; extern BOOLEAN InstallStringTableResType (COUNT string_type); extern STRING_TABLE LoadStringTableInstance (DWORD res); extern STRING_TABLE LoadStringTableFile (uio_DirHandle *dir, const char *fileName); extern BOOLEAN DestroyStringTable (STRING_TABLE StringTable); extern STRING CaptureStringTable (STRING_TABLE StringTable); extern STRING_TABLE ReleaseStringTable (STRING String); extern STRING_TABLE GetStringTable (STRING String); extern COUNT GetStringTableCount (STRING String); extern COUNT GetStringTableIndex (STRING String); extern STRING SetAbsStringTableIndex (STRING String, COUNT StringTableIndex); extern STRING SetRelStringTableIndex (STRING String, SIZE StringTableOffs); extern COUNT GetStringLength (STRING String); extern COUNT GetStringLengthBin (STRING String); extern STRINGPTR GetStringAddress (STRING String); extern STRINGPTR GetStringSoundClip (STRING String); extern STRINGPTR GetStringTimeStamp (STRING String); extern BOOLEAN GetStringContents (STRING String, STRINGPTR StringBuf, BOOLEAN AppendSpace); wchar_t getCharFromString(const unsigned char **ptr); wchar_t getCharFromStringN(const unsigned char **ptr, const unsigned char *end); unsigned char *getLineFromString(const unsigned char *start, const unsigned char **end, const unsigned char **startNext); size_t utf8StringCount(const unsigned char *start); size_t utf8StringCountN(const unsigned char *start, const unsigned char *end); int utf8StringPos (const unsigned char *pStr, wchar_t ch); unsigned char *utf8StringCopy (unsigned char *dst, size_t size, const unsigned char *src); int utf8StringCompare (const unsigned char *str1, const unsigned char *str2); unsigned char *skipUTF8Chars(const unsigned char *ptr, size_t num); size_t getWideFromString(wchar_t *wstr, size_t maxcount, const unsigned char *start); size_t getWideFromStringN(wchar_t *wstr, size_t maxcount, const unsigned char *start, const unsigned char *end); int getStringFromChar(unsigned char *ptr, size_t size, wchar_t ch); size_t getStringFromWideN(unsigned char *ptr, size_t size, const wchar_t *wstr, size_t count); size_t getStringFromWide(unsigned char *ptr, size_t size, const wchar_t *wstr); int isWideGraphChar(wchar_t ch); int isWidePrintChar(wchar_t ch); wchar_t toWideUpper(wchar_t ch); wchar_t toWideLower(wchar_t ch); #define WCHAR_DEGREE_SIGN 0x00b0 #define STR_DEGREE_SIGN "\xC2\xB0" #define WCHAR_INFINITY_SIGN 0x221e #define STR_INFINITY_SIGN "\xE2\x88\x9E" #define WCHAR_EARTH_SIGN 0x2641 #define STR_EARTH_SIGN "\xE2\x99\x81" #define WCHAR_MIDDLE_DOT 0x00b7 #define STR_MIDDLE_DOT "\xC2\xB7" #endif /* _STRLIB_H */ uqm-0.6.2/sc2/src/sc2code/libs/decomp/0000755000175000017500000000000010552600274016020 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/libs/decomp/lzencode.c0000600000175000017500000002231210543202054017751 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * LZHUF.C English version 1.0 * Based on Japanese version 29-NOV-1988 * LZSS coded by Haruhiko OKUMURA * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI * Edited and translated to English by Kenji RIKITAKE */ #include #include "lzh.h" static UWORD match_position, match_length; static PSWORD lson, rson, dad; #define AllocEncodeArrays() \ mem_allocate ( \ (MEM_SIZE)(((N + 1) + (N + 257) + (N + 1)) \ * sizeof (lson[0]) + sizeof (MEM_HANDLE)), \ MEM_ZEROINIT, DEFAULT_MEM_PRIORITY, MEM_SIMPLE \ ) #define LockCodeArrays (PSWORD)mem_lock #define UnlockCodeArrays mem_unlock #define FreeCodeArrays mem_release static BOOLEAN InitTree (void) { MEM_HANDLE h; if ((h = AllocEncodeArrays ()) == 0 || (lson = LockCodeArrays (h)) == 0) { FreeCodeArrays (h); return (FALSE); } else { SWORD i; *(MEM_HANDLE *)lson = h; lson = (PSWORD)((PBYTE)lson + sizeof (h)); rson = lson + (N + 1); dad = rson + (N + 257); for (i = N + 1; i <= N + 256; i++) rson[i] = NIL; /* root */ for (i = 0; i < N; i++) dad[i] = NIL; /* node */ return (TRUE); } } static void InsertNode (SWORD r) { SWORD p, cmp; PBYTE lpBuf; cmp = 1; lpBuf = _lpCurCodeDesc->text_buf; p = N + 1 + lpBuf[r]; rson[r] = lson[r] = NIL; match_length = 0; for (;;) { UWORD i; if (cmp >= 0) { if (rson[p] != NIL) p = rson[p]; else { rson[p] = r; dad[r] = p; return; } } else { if (lson[p] != NIL) p = lson[p]; else { lson[p] = r; dad[r] = p; return; } } i = F; { SWORD _r, _p; _r = r; _p = p; while (--i && (cmp = lpBuf[++_r] - lpBuf[++_p]) == 0) ; } if ((i = F - i) > THRESHOLD) { if (i > match_length) { match_position = ((r - p) & (N - 1)) - 1; if ((match_length = i) >= F) break; } else if (i == match_length) { if ((i = ((r - p) & (N - 1)) - 1) < match_position) { match_position = i; } } } } dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p]; dad[lson[p]] = r; dad[rson[p]] = r; if (rson[dad[p]] == p) rson[dad[p]] = r; else lson[dad[p]] = r; dad[p] = NIL; /* remove p */ } static void DeleteNode (SWORD p) { SWORD q; if (dad[p] == NIL) return; /* unregistered */ if (rson[p] == NIL) q = lson[p]; else if (lson[p] == NIL) q = rson[p]; else { q = lson[p]; if (rson[q] != NIL) { do { q = rson[q]; } while (rson[q] != NIL); rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q]; lson[q] = lson[p]; dad[lson[p]] = q; } rson[q] = rson[p]; dad[rson[p]] = q; } dad[q] = dad[p]; if (rson[dad[p]] == p) rson[dad[p]] = q; else lson[dad[p]] = q; dad[p] = NIL; } static void Putcode (SWORD l, UWORD c) { _workbuf |= c >> _workbuflen; if ((_workbuflen += l) >= 8) { OutChar ((BYTE)(_workbuf >> 8)); ++_lpCurCodeDesc->StreamIndex; if ((_workbuflen -= 8) >= 8) { OutChar ((BYTE)(_workbuf)); ++_lpCurCodeDesc->StreamIndex; _workbuflen -= 8; _workbuf = c << (l - _workbuflen); } else { _workbuf <<= 8; } _workbuf &= 0xFFFF; } } static void EncodeChar (UWORD c) { UWORD i; SWORD j, k; i = 0; j = 0; k = _lpCurCodeDesc->prnt[c + T]; /* search connections from leaf node to the root */ do { i >>= 1; /* if node's address is odd, output 1 else output 0 */ if (k & 1) i += 0x8000; j++; } while ((k = _lpCurCodeDesc->prnt[k]) != R); Putcode (j, i); _update (c + T); } static void EncodePosition (UWORD c) { UWORD i; /* * Tables for encoding/decoding upper 6 bits of * sliding dictionary pointer */ /* encoder table */ static const BYTE p_len[64] = { 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }; static const BYTE p_code[64] = { 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C, 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC, 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE, 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; /* output upper 6 bits with encoding */ i = c >> 6; Putcode (p_len[i], (UWORD)p_code[i] << 8); /* output lower 6 bits directly */ Putcode (6, (c & 0x3f) << 10); } static void UninitTree (void) { MEM_HANDLE h; if (_workbuflen) { OutChar ((BYTE)(_workbuf >> 8)); ++_lpCurCodeDesc->StreamIndex; } lson = (PSWORD)((PBYTE)lson - sizeof (h)); h = *(MEM_HANDLE *)lson; UnlockCodeArrays (h); FreeCodeArrays (h); } static void _encode_cleanup (void) { UWORD r, s, last_match_length, len; _StreamType = _lpCurCodeDesc->StreamType; _Stream = _lpCurCodeDesc->Stream; _workbuf = _lpCurCodeDesc->workbuf; _workbuflen = _lpCurCodeDesc->workbuflen; r = _lpCurCodeDesc->buf_index; s = _lpCurCodeDesc->restart_index; last_match_length = _lpCurCodeDesc->bytes_left; if (_lpCurCodeDesc->StreamLength >= F) len = F; else { UWORD i; for (i = 1; i <= F; i++) InsertNode (r - i); InsertNode (r); len = (UWORD)_lpCurCodeDesc->StreamLength; } while (1) { while (last_match_length--) { DeleteNode (s); if (--len == 0) { BYTE lobyte, hibyte; UWORD loword, hiword; UninitTree (); _lpCurCodeDesc->StreamIndex += 4; /* rewind */ if (_lpCurCodeDesc->StreamType == FILE_STREAM) SeekResFile ((uio_Stream *)_Stream, -(int)_lpCurCodeDesc->StreamIndex, SEEK_CUR); else /* _lpCurCodeDesc->StreamType == MEMORY_STREAM */ _Stream = (PBYTE)((BYTE *)_Stream - _lpCurCodeDesc->StreamIndex); loword = LOWORD (_lpCurCodeDesc->StreamLength); lobyte = LOBYTE (loword); hibyte = HIBYTE (loword); OutChar (lobyte); OutChar (hibyte); hiword = HIWORD (_lpCurCodeDesc->StreamLength); lobyte = LOBYTE (hiword); hibyte = HIBYTE (hiword); OutChar (lobyte); OutChar (hibyte); return; } s = (s + 1) & (N - 1); r = (r + 1) & (N - 1); InsertNode (r); } if (match_length > len) match_length = len; if (match_length <= THRESHOLD) { match_length = 1; EncodeChar (_lpCurCodeDesc->text_buf[r]); } else { EncodeChar (255 - THRESHOLD + match_length); EncodePosition (match_position); } last_match_length = match_length; } } COUNT cwrite (PVOID buf, COUNT size, COUNT count, PLZHCODE_DESC lpCodeDesc) { UWORD r, s, last_match_length; PBYTE lpBuf, lpStr; if ((_lpCurCodeDesc = lpCodeDesc) == 0 || (size *= count) == 0) return (0); _StreamType = lpCodeDesc->StreamType; _Stream = lpCodeDesc->Stream; _workbuf = lpCodeDesc->workbuf; _workbuflen = lpCodeDesc->workbuflen; lpStr = (PBYTE)buf; lpBuf = lpCodeDesc->text_buf; r = lpCodeDesc->buf_index; s = lpCodeDesc->restart_index; last_match_length = lpCodeDesc->bytes_left; if (last_match_length) { lpCodeDesc->StreamLength += size; goto EncodeRestart; } else if (lpCodeDesc->StreamLength < F) { UWORD i; if ((i = (UWORD)lpCodeDesc->StreamLength) == 0) { if (!InitTree ()) return (0); _lpCurCodeDesc->StreamIndex = 0; lpCodeDesc->CleanupFunc = _encode_cleanup; } lpCodeDesc->StreamLength += size; for (; i < F && size; ++i, --size) lpBuf[r + i] = *lpStr++; if (i < F) goto EncodeExit; for (i = 1; i <= F; i++) InsertNode (r - i); InsertNode (r); if (size == 0) goto EncodeExit; } else lpCodeDesc->StreamLength += size; do { if (match_length > F) match_length = F; if (match_length <= THRESHOLD) { match_length = 1; EncodeChar (lpBuf[r]); } else { EncodeChar (255 - THRESHOLD + match_length); EncodePosition (match_position); } last_match_length = match_length; EncodeRestart: while (last_match_length && size) { BYTE c; --size; --last_match_length; DeleteNode (s); c = *lpStr++; lpBuf[s] = c; if (s < F - 1) lpBuf[s + N] = c; s = (s + 1) & (N - 1); r = (r + 1) & (N - 1); InsertNode (r); } } while (last_match_length == 0); EncodeExit: lpCodeDesc->buf_index = r; lpCodeDesc->restart_index = s; lpCodeDesc->bytes_left = last_match_length; lpCodeDesc->Stream = _Stream; lpCodeDesc->workbuf = _workbuf; lpCodeDesc->workbuflen = _workbuflen; return (count); } uqm-0.6.2/sc2/src/sc2code/libs/decomp/lzdecode.c0000600000175000017500000002364210543202054017746 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * LZHUF.C English version 1.0 * Based on Japanese version 29-NOV-1988 * LZSS coded by Haruhiko OKUMURA * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI * Edited and translated to English by Kenji RIKITAKE */ #include #include #include #include #include "libs/decomp/lzh.h" PLZHCODE_DESC _lpCurCodeDesc; STREAM_TYPE _StreamType; PBYTE _Stream; UWORD _workbuf; BYTE _workbuflen; /* get one bit */ static SWORD GetBit (void) { SWORD i; while (_workbuflen <= 8) { if ((i = InChar ()) < 0) i = 0; _workbuf |= i << (8 - _workbuflen); _workbuflen += 8; } i = (_workbuf & 0xFFFF) >> (16 - 1); _workbuf = (_workbuf << 1) & 0xFFFF; _workbuflen--; return (i); } static UWORD GetBits (BYTE num_bits) { SWORD i; while (_workbuflen <= 8) { if ((i = InChar ()) < 0) i = 0; _workbuf |= i << (8 - _workbuflen); _workbuflen += 8; } i = (_workbuf & 0xFFFF) >> (16 - num_bits); _workbuf = (_workbuf << num_bits) & 0xFFFF; _workbuflen -= num_bits; return (i); } /* initialize freq tree */ void StartHuff (void) { COUNT i, j; for (i = 0; i < N_CHAR; i++) { _lpCurCodeDesc->freq[i] = 1; _lpCurCodeDesc->son[i] = i + T; _lpCurCodeDesc->prnt[i + T] = i; } i = 0; j = N_CHAR; while (j <= R) { _lpCurCodeDesc->freq[j] = _lpCurCodeDesc->freq[i] + _lpCurCodeDesc->freq[i + 1]; _lpCurCodeDesc->son[j] = i; _lpCurCodeDesc->prnt[i] = _lpCurCodeDesc->prnt[i + 1] = j; i += 2; j++; } _lpCurCodeDesc->freq[T] = 0xffff; _lpCurCodeDesc->prnt[R] = 0; } DECODE_REF copen (PVOID InStream, STREAM_TYPE SType, STREAM_MODE SMode) { MEM_HANDLE h; DWORD StreamLength; _StreamType = SType; _Stream = InStream; if (SMode == STREAM_WRITE) /* writing */ { OutChar (0); /* skip future StreamLength */ OutChar (0); OutChar (0); OutChar (0); StreamLength = 0; } else /* reading */ { BYTE lobyte, hibyte; UWORD loword, hiword; lobyte = (BYTE)InChar (); hibyte = (BYTE)InChar (); loword = MAKE_WORD (lobyte, hibyte); lobyte = (BYTE)InChar (); hibyte = (BYTE)InChar (); hiword = MAKE_WORD (lobyte, hibyte); StreamLength = MAKE_DWORD (loword, hiword); } h = 0; if (StreamLength == 0xFFFFFFFF || (h = AllocCodeDesc ()) == 0 || (_lpCurCodeDesc = LockCodeDesc (h)) == 0) { _lpCurCodeDesc = 0; FreeCodeDesc (h); } else { _lpCurCodeDesc->fh = h; _lpCurCodeDesc->Stream = _Stream; _lpCurCodeDesc->StreamType = _StreamType; _lpCurCodeDesc->StreamMode = SMode; _lpCurCodeDesc->StreamLength = StreamLength; _lpCurCodeDesc->buf_index = N - F; memset ((PBYTE)&_lpCurCodeDesc->text_buf[0], ' ', N - F); StartHuff (); } return ((DECODE_REF)_lpCurCodeDesc); } DWORD cclose (PLZHCODE_DESC lpCodeDesc) { _lpCurCodeDesc = lpCodeDesc; if (_lpCurCodeDesc) { DWORD StreamIndex; if (_lpCurCodeDesc->CleanupFunc) (*_lpCurCodeDesc->CleanupFunc) (); StreamIndex = lpCodeDesc->StreamIndex; UnlockCodeDesc (lpCodeDesc->fh); FreeCodeDesc (lpCodeDesc->fh); return (StreamIndex); } return (0); } void cfilelength (PLZHCODE_DESC lpCodeDesc, DWORD *pfilelen) { if (lpCodeDesc == 0) *pfilelen = 0; else *pfilelen = lpCodeDesc->StreamLength; } /* decoder table */ static const BYTE d_code[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, }; static const BYTE d_len[256] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, }; /* decode upper 6 bits from given table */ #define DecodePosition(p) \ { \ while (_workbuflen <= 8) \ { \ *(p) = InChar (); \ _workbuf |= *(p) << (8 - _workbuflen); \ _workbuflen += 8; \ } \ *(p) = HIBYTE (_workbuf); \ _workbuf = (_workbuf << 8) & 0xFFFF; \ _workbuflen -= 8; \ \ /* input lower 6 bits directly */ \ j = d_len[*(p)]; \ *(p) = ((UWORD)d_code[*(p)] << 6) \ | (((*(p) << j) | GetBits (j)) & 0x3f); \ } /* start searching tree from the root to leaves. * choose node #(son[]) if input bit == 0 * else choose #(son[]+1) (input bit == 1) */ #define DecodeChar(c) \ { \ for (*(c) = lpCodeDesc->son[R]; \ *(c) < T; \ *(c) = lpCodeDesc->son[*(c) + GetBit ()]) \ ; \ _update (*(c)); \ *(c) -= T; \ } COUNT cread (PVOID buf, COUNT size, COUNT count, PLZHCODE_DESC lpCodeDesc) { COUNT r, j, i; PBYTE lpStr; if ((_lpCurCodeDesc = lpCodeDesc) == 0) return (0); size *= count; if (lpCodeDesc->StreamIndex + size > lpCodeDesc->StreamLength) { size /= count; count = (COUNT)((lpCodeDesc->StreamLength - lpCodeDesc->StreamIndex) / size); size *= count; } if (size == 0) return (0); lpStr = (PBYTE)buf; _StreamType = lpCodeDesc->StreamType; _Stream = lpCodeDesc->Stream; _workbuf = lpCodeDesc->workbuf; _workbuflen = lpCodeDesc->workbuflen; lpCodeDesc->StreamIndex += size; r = lpCodeDesc->buf_index; j = lpCodeDesc->bytes_left; if (j) { lpCodeDesc->bytes_left = 0; i = lpCodeDesc->restart_index; goto ReenterRun; } do { COUNT c; DecodeChar (&c); if (c < 256) { size--; *lpStr++ = lpCodeDesc->text_buf[r++ & (N - 1)] = (BYTE)c; } else { COUNT copy_size; //i is a COUNT; DecodePosition(&i); i = r - i - 1; j = c - 255 + THRESHOLD; ReenterRun: if (j > size) { lpCodeDesc->bytes_left = j - size; lpCodeDesc->restart_index = i + size; j = size; } size -= j; do { COUNT loc_size; i &= (N - 1); r &= (N - 1); if ((i < r && i + j > r) || (i > r && i + j > r + N)) copy_size = (r - i) & (N - 1); else if ((copy_size = j) > N) copy_size = N; loc_size = copy_size; if (i + loc_size > N) { COUNT k; k = N - i; memcpy (lpStr, &lpCodeDesc->text_buf[i], k); lpStr += k; loc_size -= k; i = 0; } memcpy (lpStr, &lpCodeDesc->text_buf[i], loc_size); lpStr += loc_size; i += loc_size; lpStr -= copy_size; loc_size = copy_size; if (r + loc_size > N) { COUNT k; k = N - r; memcpy (&lpCodeDesc->text_buf[r], lpStr, k); lpStr += k; loc_size -= k; r = 0; } memcpy (&lpCodeDesc->text_buf[r], lpStr, loc_size); lpStr += loc_size; r += loc_size; } while (j -= copy_size); } } while (size); lpCodeDesc->buf_index = r; lpCodeDesc->Stream = _Stream; lpCodeDesc->workbuf = _workbuf; lpCodeDesc->workbuflen = _workbuflen; return (count); } uqm-0.6.2/sc2/src/sc2code/libs/decomp/update.c0000600000175000017500000000506010543202054017431 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "lzh.h" static void reconst (void) { COUNT i, j; /* halven cumulative freq for leaf nodes */ j = 0; for (i = 0; i < T; i++) { if (_lpCurCodeDesc->son[i] >= T) { _lpCurCodeDesc->freq[j] = (_lpCurCodeDesc->freq[i] + 1) >> 1; _lpCurCodeDesc->son[j] = _lpCurCodeDesc->son[i]; j++; } } /* make a tree : first, connect children nodes */ for (i = 0, j = N_CHAR; j < T; i += 2, j++) { SWORD k; UWORD f, l; k = i + 1; f = _lpCurCodeDesc->freq[j] = _lpCurCodeDesc->freq[i] + _lpCurCodeDesc->freq[k]; for (k = j - 1; f < _lpCurCodeDesc->freq[k]; k--) ; k++; l = (j - k); memmove (_lpCurCodeDesc->freq + k + 1, _lpCurCodeDesc->freq + k, sizeof(_lpCurCodeDesc->freq[0]) * l); _lpCurCodeDesc->freq[k] = f; memmove (_lpCurCodeDesc->son + k + 1, _lpCurCodeDesc->son + k, sizeof(_lpCurCodeDesc->son[0]) * l); _lpCurCodeDesc->son[k] = i; } /* connect parent nodes */ for (i = 0; i < T; i++) { if ((j = _lpCurCodeDesc->son[i]) >= T) _lpCurCodeDesc->prnt[j] = i; else _lpCurCodeDesc->prnt[j] = _lpCurCodeDesc->prnt[j + 1] = i; } } /* update freq tree */ void _update (COUNT c) { PLZHCODE_DESC lpCD; if ((lpCD = _lpCurCodeDesc)->freq[R] == MAX_FREQ) reconst (); c = lpCD->prnt[c]; do { COUNT i, l; i = ++lpCD->freq[c]; /* swap nodes to keep the tree freq-ordered */ if (i > lpCD->freq[l = c + 1]) { COUNT j; while (i > lpCD->freq[++l]) ; l--; lpCD->freq[c] = lpCD->freq[l]; lpCD->freq[l] = i; i = lpCD->son[c]; j = lpCD->son[l]; lpCD->son[l] = i; lpCD->son[c] = j; lpCD->prnt[i] = l; if (i < T) lpCD->prnt[i + 1] = l; lpCD->prnt[j] = c; if (j < T) lpCD->prnt[j + 1] = c; c = l; } } while ((c = lpCD->prnt[c]) != 0); /* do it until reaching the root */ } uqm-0.6.2/sc2/src/sc2code/libs/decomp/lzh.h0000600000175000017500000000536610543202054016762 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _LZH_H #define _LZH_H #include "reslib.h" #define _DEC_PROTOS #include "declib.h" /* LZSS Parameters */ #define N 4096 /* Size of string buffer */ #define F 16 /* Size of look-ahead buffer */ //#define F 60 /* Size of look-ahead buffer */ #define THRESHOLD 2 #define NIL N /* End of tree's node */ /* Huffman coding parameters */ #define N_CHAR (256 - THRESHOLD + F) /* character code (= 0..N_CHAR-1) */ #define T (N_CHAR * 2 - 1) /* Size of table */ #define R (T - 1) /* root position */ #define MAX_FREQ 0x8000 /* update when cumulative frequency */ typedef struct { MEM_HANDLE fh; COUNT buf_index, restart_index, bytes_left; BYTE text_buf[N + F - 1]; /* reconstruct freq tree */ COUNT freq[T + 1]; /* cumulative freq table */ /* * pointing parent nodes. * area [T..(T + N_CHAR - 1)] are pointers for leaves */ COUNT prnt[T + N_CHAR]; /* pointing children nodes (son[], son[] + 1)*/ COUNT son[T]; UWORD workbuf; BYTE workbuflen; STREAM_TYPE StreamType; PVOID Stream; DWORD StreamIndex, StreamLength; STREAM_MODE StreamMode; PVOIDFUNC CleanupFunc; } LZHCODE_DESC; typedef LZHCODE_DESC *PLZHCODE_DESC; #define InChar() (_StreamType == FILE_STREAM ? \ GetResFileChar ((uio_Stream *)_Stream) : \ (int)*_Stream++) #define OutChar(c) (_StreamType == FILE_STREAM ? \ PutResFileChar ((c), (uio_Stream *)_Stream) : \ (*_Stream++ = (BYTE)(c))) #define AllocCodeDesc() \ mem_allocate ((MEM_SIZE)sizeof (LZHCODE_DESC), \ MEM_ZEROINIT, DEFAULT_MEM_PRIORITY, MEM_SIMPLE) #define LockCodeDesc (PLZHCODE_DESC)mem_lock #define UnlockCodeDesc mem_unlock #define FreeCodeDesc mem_release extern void _update (COUNT c); extern void StartHuff (void); #undef DECODE_REF #define DECODE_REF PLZHCODE_DESC #undef _DEC_PROTOS #include "declib.h" extern PLZHCODE_DESC _lpCurCodeDesc; extern STREAM_TYPE _StreamType; extern PBYTE _Stream; extern UWORD _workbuf; extern BYTE _workbuflen; #endif /* _LZH_H */ uqm-0.6.2/sc2/src/sc2code/libs/decomp/Makeinfo0000600000175000017500000000005410543202054017455 0ustar joeyjoeyuqm_CFILES="lzdecode.c lzencode.c update.c" uqm-0.6.2/sc2/src/sc2code/ikey_con.h0000600000175000017500000000004410543202103015544 0ustar joeyjoey#define JOYSTICK_KEYS 0x00200001L uqm-0.6.2/sc2/src/sc2code/melee.c0000644000175000017500000024227510546255076015100 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "melee.h" #include "build.h" #include "colors.h" #include "comm.h" // for getLineWithinWidth #include "controls.h" #include "file.h" #include "fmv.h" #include "gamestr.h" #include "globdata.h" #include "intel.h" #include "nameref.h" #ifdef NETPLAY # include "netplay/netconnection.h" # include "netplay/netmelee.h" # include "netplay/notify.h" # include "libs/graphics/widgets.h" # include "cnctdlg.h" #endif #include "options.h" #include "races.h" #include "resinst.h" #include "save.h" #include "settings.h" #include "gameopt.h" #include "setup.h" #include "sounds.h" #include "util.h" #include "libs/graphics/drawable.h" #include "libs/gfxlib.h" #include "libs/inplib.h" #include "libs/mathlib.h" #include "libs/log.h" #include #include #include #include static void DrawMeleeShipStrings (PMELEE_STATE pMS, BYTE NewStarShip); static void StartMelee (PMELEE_STATE pMS); static ssize_t numPlayersReady (void); static int flash_selection_func (void *data); enum { #ifdef NETPLAY NET_TOP, #endif CONTROLS_TOP, SAVE_TOP, LOAD_TOP, START_MELEE, LOAD_BOT, SAVE_BOT, CONTROLS_BOT, #ifdef NETPLAY NET_BOT, #endif QUIT_BOT, EDIT_MELEE }; #ifdef NETPLAY #define TOP_ENTRY NET_TOP #else #define TOP_ENTRY CONTROLS_TOP #endif #define MELEE_X_OFFS 2 #define MELEE_Y_OFFS 21 #define MELEE_BOX_WIDTH 34 #define MELEE_BOX_HEIGHT 34 #define MELEE_BOX_SPACE 1 #define MENU_X_OFFS 29 #define NAME_AREA_HEIGHT 7 #define MELEE_WIDTH 149 #define MELEE_HEIGHT (48 + NAME_AREA_HEIGHT) #define INFO_ORIGIN_X 4 #define INFO_WIDTH 58 #define TEAM_INFO_ORIGIN_Y 3 #define TEAM_INFO_HEIGHT (SHIP_INFO_HEIGHT + 75) #define MODE_INFO_ORIGIN_Y (TEAM_INFO_HEIGHT + 6) #define MODE_INFO_HEIGHT ((STATUS_HEIGHT - 3) - MODE_INFO_ORIGIN_Y) #define RACE_INFO_ORIGIN_Y (SHIP_INFO_HEIGHT + 6) #define RACE_INFO_HEIGHT ((STATUS_HEIGHT - 3) - RACE_INFO_ORIGIN_Y) #define MELEE_STATUS_X_OFFS 1 #define MELEE_STATUS_Y_OFFS 201 #define MELEE_STATUS_WIDTH (NUM_MELEE_COLUMNS * \ (MELEE_BOX_WIDTH + MELEE_BOX_SPACE)) #define MELEE_STATUS_HEIGHT 38 #define MELEE_BACKGROUND_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) #define MELEE_TITLE_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C) #define MELEE_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C) #define MELEE_TEAM_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E) #define STATE_BACKGROUND_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) #define STATE_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03) #define ACTIVE_STATE_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B) #define UNAVAILABLE_STATE_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09) #define HI_STATE_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B) #define HI_STATE_BACKGROUND_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09) // XXX: The following entries are unused: #define LIST_INFO_BACKGROUND_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x14), 0x05) #define LIST_INFO_TITLE_COLOR \ WHITE_COLOR #define LIST_INFO_TEXT_COLOR \ LT_GRAY_COLOR #define LIST_INFO_CURENTRY_TEXT_COLOR \ WHITE_COLOR #define HI_LIST_INFO_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) #define HI_LIST_INFO_BACKGROUND_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x1F), 0x0D) #define TEAM_NAME_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x0F, 0x10, 0x1B), 0x00) #define TEAM_NAME_EDIT_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x17, 0x18, 0x1D), 0x00) #define TEAM_NAME_EDIT_RECT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x14), 0x05) #define TEAM_NAME_EDIT_CURS_COLOR \ WHITE_COLOR #define PICKSHIP_TEAM_NAME_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09) #define PICKSHIP_TEAM_START_VALUE_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x04, 0x05, 0x1F), 0x4B) #define SHIPBOX_TOPLEFT_COLOR_NORMAL \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x09), 0x56) #define SHIPBOX_BOTTOMRIGHT_COLOR_NORMAL \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x0E), 0x54) #define SHIPBOX_INTERIOR_COLOR_NORMAL \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x0C), 0x55) #define SHIPBOX_TOPLEFT_COLOR_HILITE \ BUILD_COLOR (MAKE_RGB15 (0x07, 0x00, 0x0C), 0x3E) #define SHIPBOX_BOTTOMRIGHT_COLOR_HILITE \ BUILD_COLOR (MAKE_RGB15 (0x0C, 0x00, 0x14), 0x3C) #define SHIPBOX_INTERIOR_COLOR_HILITE \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x00, 0x11), 0x3D) #define MELEE_STATUS_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02) FRAME PickMeleeFrame; static FRAME MeleeFrame; static FRAME BuildPickFrame; extern QUEUE master_q; DWORD InTime; PMELEE_STATE volatile pMeleeState; static BOOLEAN DoMelee (PMELEE_STATE pMS); static BOOLEAN DoEdit (PMELEE_STATE pMS); static BOOLEAN DoPickShip (PMELEE_STATE pMS); static BOOLEAN DoConfirmSettings (PMELEE_STATE pMS); #define DTSHS_NORMAL 0 #define DTSHS_EDIT 1 #define DTSHS_SELECTED 2 #define DTSHS_REPAIR 4 #define DTSHS_BLOCKCUR 8 static BOOLEAN DrawTeamString (PMELEE_STATE pMS, COUNT side, COUNT HiLiteState); static BOOLEAN DoLoadTeam (PMELEE_STATE pMS); static void DrawFileStrings (PMELEE_STATE pMS, int HiLiteState); static void DrawMeleeIcon (COUNT which_icon) { STAMP s; s.origin.x = s.origin.y = 0; s.frame = SetAbsFrameIndex (MeleeFrame, which_icon); DrawStamp (&s); } static void GetShipBox (PRECT pRect, COUNT side, COUNT row, COUNT col) { pRect->corner.x = MELEE_X_OFFS + (col * (MELEE_BOX_WIDTH + MELEE_BOX_SPACE)); pRect->corner.y = MELEE_Y_OFFS + (side * (MELEE_Y_OFFS + MELEE_BOX_SPACE + (NUM_MELEE_ROWS * (MELEE_BOX_HEIGHT + MELEE_BOX_SPACE)))) + (row * (MELEE_BOX_HEIGHT + MELEE_BOX_SPACE)); pRect->extent.width = MELEE_BOX_WIDTH; pRect->extent.height = MELEE_BOX_HEIGHT; } static FleetShipIndex GetShipIndex (BYTE row, BYTE col) { return row * NUM_MELEE_COLUMNS + col; } static BYTE GetShipRow (FleetShipIndex index) { return index / NUM_MELEE_COLUMNS; } static BYTE GetShipColumn (int index) { return index % NUM_MELEE_COLUMNS; } static void DrawShipBox (COUNT side, COUNT row, COUNT col, BYTE ship, BOOLEAN HiLite) { RECT r; GetShipBox (&r, side, row, col); BatchGraphics (); if (HiLite) DrawStarConBox (&r, 1, SHIPBOX_TOPLEFT_COLOR_HILITE, SHIPBOX_BOTTOMRIGHT_COLOR_HILITE, (BOOLEAN)(ship != MELEE_NONE), SHIPBOX_INTERIOR_COLOR_HILITE); else DrawStarConBox (&r, 1, SHIPBOX_TOPLEFT_COLOR_NORMAL, SHIPBOX_BOTTOMRIGHT_COLOR_NORMAL, (BOOLEAN)(ship != MELEE_NONE), SHIPBOX_INTERIOR_COLOR_NORMAL); if (ship != MELEE_NONE) { STAMP s; HSTARSHIP hStarShip; STARSHIPPTR StarShipPtr; hStarShip = GetStarShipFromIndex (&master_q, ship); StarShipPtr = LockStarShip (&master_q, hStarShip); s.origin.x = r.corner.x + (r.extent.width >> 1); s.origin.y = r.corner.y + (r.extent.height >> 1); s.frame = StarShipPtr->RaceDescPtr->ship_info.melee_icon; DrawStamp (&s); UnlockStarShip (&master_q, hStarShip); } UnbatchGraphics (); } static void DrawShipBoxCurrent (PMELEE_STATE pMS, BOOLEAN HiLite) { FleetShipIndex index = GetShipIndex (pMS->row, pMS->col); BYTE ship = pMS->TeamImage[pMS->side].ShipList[index]; DrawShipBox (pMS->side, pMS->row, pMS->col, ship, HiLite); } // Draw an image for one of the control method selection buttons. static void DrawControls (COUNT which_side, BOOLEAN HiLite) { COUNT which_icon; if (PlayerControl[which_side] & NETWORK_CONTROL) { DrawMeleeIcon (31 + (HiLite ? 1 : 0) + 2 * (1 - which_side)); return; } if (PlayerControl[which_side] & HUMAN_CONTROL) which_icon = 0; else { switch (PlayerControl[which_side] & (STANDARD_RATING | GOOD_RATING | AWESOME_RATING)) { case STANDARD_RATING: which_icon = 1; break; case GOOD_RATING: which_icon = 2; break; case AWESOME_RATING: which_icon = 3; break; default: // Should not happen. Satisfying compiler. which_icon = 0; break; } } DrawMeleeIcon (1 + (8 * (1 - which_side)) + (HiLite ? 4 : 0) + which_icon); } static void DrawPickFrame (PMELEE_STATE pMS) { RECT r, r0, r1, ship_r; STAMP s; GetShipBox (&r0, 0, 0, 0), GetShipBox (&r1, 1, NUM_MELEE_ROWS - 1, NUM_MELEE_COLUMNS - 1), BoxUnion (&r0, &r1, &ship_r); s.frame = SetAbsFrameIndex (BuildPickFrame, 0); GetFrameRect (s.frame, &r); r.corner.x = -(ship_r.corner.x + ((ship_r.extent.width - r.extent.width) >> 1)); if (pMS->side) r.corner.y = -ship_r.corner.y; else r.corner.y = -(ship_r.corner.y + (ship_r.extent.height - r.extent.height)); SetFrameHot (s.frame, MAKE_HOT_SPOT (r.corner.x, r.corner.y)); s.origin.x = 0; s.origin.y = 0; DrawStamp (&s); UnlockMutex (GraphicsLock); DrawMeleeShipStrings (pMS, (BYTE)pMS->CurIndex); LockMutex (GraphicsLock); } static void RepairMeleeFrame (PRECT pRect) { RECT r; CONTEXT OldContext; RECT OldRect; r.corner.x = pRect->corner.x + SAFE_X; r.corner.y = pRect->corner.y + SAFE_Y; r.extent = pRect->extent; if (r.corner.y & 1) { --r.corner.y; ++r.extent.height; } OldContext = SetContext (SpaceContext); GetContextClipRect (&OldRect); SetContextClipRect (&r); SetFrameHot (Screen, MAKE_HOT_SPOT (r.corner.x - SAFE_X, r.corner.y - SAFE_Y)); BatchGraphics (); DrawMeleeIcon (0); /* Entire melee screen */ #ifdef NETPLAY DrawMeleeIcon (35); DrawMeleeIcon (37); #endif DrawMeleeIcon (26); /* "Battle!" (highlighted) */ { COUNT side; COUNT row; COUNT col; for (side = 0; side < NUM_SIDES; side++) { DrawControls (side, FALSE); for (row = 0; row < NUM_MELEE_ROWS; row++) { for (col = 0; col < NUM_MELEE_COLUMNS; col++) { FleetShipIndex index = GetShipIndex (row, col); BYTE ship = pMeleeState->TeamImage[side].ShipList[index]; DrawShipBox (side, row, col, ship, FALSE); } } DrawTeamString (pMeleeState, side, DTSHS_NORMAL); } } if (pMeleeState->InputFunc == DoPickShip) DrawPickFrame (pMeleeState); UnbatchGraphics (); SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); SetContextClipRect (&OldRect); SetContext (OldContext); } static void RedrawMeleeFrame (void) { RECT r; r.corner.x = r.corner.y = 0; r.extent.width = SCREEN_WIDTH; r.extent.height = SCREEN_HEIGHT; RepairMeleeFrame (&r); } static BOOLEAN DrawTeamString (PMELEE_STATE pMS, COUNT side, COUNT HiLiteState) { RECT r; TEXT lfText; r.corner.x = MELEE_X_OFFS - 1; r.corner.y = (side + 1) * (MELEE_Y_OFFS + ((MELEE_BOX_HEIGHT + MELEE_BOX_SPACE) * NUM_MELEE_ROWS + 2)); r.extent.width = NUM_MELEE_COLUMNS * (MELEE_BOX_WIDTH + MELEE_BOX_SPACE); r.extent.height = 13; if (HiLiteState == DTSHS_REPAIR) { RepairMeleeFrame (&r); return (TRUE); } SetContextFont (MicroFont); lfText.pStr = pMS->TeamImage[side].TeamName; lfText.baseline.y = r.corner.y + r.extent.height - 3; lfText.baseline.x = r.corner.x + 1; lfText.align = ALIGN_LEFT; lfText.CharCount = strlen (lfText.pStr); BatchGraphics (); if (!(HiLiteState & DTSHS_EDIT)) { // normal or selected state TEXT rtText; UNICODE buf[30]; sprintf (buf, "%d", pMS->star_bucks[side]); rtText.pStr = buf; rtText.align = ALIGN_RIGHT; rtText.CharCount = (COUNT)~0; rtText.baseline.y = lfText.baseline.y; rtText.baseline.x = lfText.baseline.x + r.extent.width - 1; SetContextForeGroundColor (!(HiLiteState & DTSHS_SELECTED) ? TEAM_NAME_TEXT_COLOR : TEAM_NAME_EDIT_TEXT_COLOR); font_DrawText (&lfText); font_DrawText (&rtText); } else { // editing state COUNT i; RECT text_r; BYTE char_deltas[MAX_TEAM_CHARS]; PBYTE pchar_deltas; // not drawing team bucks r.extent.width -= 29; TextRect (&lfText, &text_r, char_deltas); if ((text_r.extent.width + 2) >= r.extent.width) { // the text does not fit the input box size and so // will not fit when displayed later UnbatchGraphics (); // disallow the change return (FALSE); } text_r = r; SetContextForeGroundColor (TEAM_NAME_EDIT_RECT_COLOR); DrawFilledRectangle (&text_r); // calculate the cursor position and draw it pchar_deltas = char_deltas; for (i = pMS->CurIndex; i > 0; --i) text_r.corner.x += (SIZE)*pchar_deltas++; if (pMS->CurIndex < lfText.CharCount) /* cursor mid-line */ --text_r.corner.x; if (HiLiteState & DTSHS_BLOCKCUR) { // Use block cursor for keyboardless systems if (pMS->CurIndex == lfText.CharCount) { // cursor at end-line -- use insertion point text_r.extent.width = 1; } else if (pMS->CurIndex + 1 == lfText.CharCount) { // extra pixel for last char margin text_r.extent.width = (SIZE)*pchar_deltas + 2; } else { // normal mid-line char text_r.extent.width = (SIZE)*pchar_deltas + 1; } } else { // Insertion point cursor text_r.extent.width = 1; } // position cursor within input field rect ++text_r.corner.x; ++text_r.corner.y; text_r.extent.height -= 2; SetContextForeGroundColor (TEAM_NAME_EDIT_CURS_COLOR); DrawFilledRectangle (&text_r); SetContextForeGroundColor (BLACK_COLOR); // TEAM_NAME_EDIT_TEXT_COLOR); font_DrawText (&lfText); } UnbatchGraphics (); return (TRUE); } // Draw a ship icon in the ship selection popup. static void DrawPickIcon (COUNT iship, BYTE DrawErase) { STAMP s; HSTARSHIP hStarShip; STARSHIPPTR StarShipPtr; RECT r; GetFrameRect (BuildPickFrame, &r); hStarShip = GetStarShipFromIndex (&master_q, iship); StarShipPtr = LockStarShip (&master_q, hStarShip); s.origin.x = r.corner.x + 20 + (iship % NUM_PICK_COLS) * 18; s.origin.y = r.corner.y + 5 + (iship / NUM_PICK_COLS) * 18; s.frame = StarShipPtr->RaceDescPtr->ship_info.icons; if (DrawErase) { // draw icon DrawStamp (&s); } else { // erase icon COLOR OldColor; OldColor = SetContextForeGroundColor (BLACK_COLOR); DrawFilledStamp (&s); SetContextForeGroundColor (OldColor); } UnlockStarShip (&master_q, hStarShip); } #ifdef NETPLAY // This function is generic. It should probably be moved to elsewhere. // The caller should hold the GraphicsLock. static void multiLineDrawText(TEXT *textIn, RECT *clipRect) { RECT oldRect; SIZE leading; TEXT text; SIZE lineWidth; GetContextClipRect (&oldRect); SetContextClipRect (clipRect); GetContextFontLeading (&leading); text = *textIn; text.baseline.x = 1; text.baseline.y = 0; if (clipRect->extent.width <= text.baseline.x) goto out; lineWidth = clipRect->extent.width - text.baseline.x; while (*text.pStr != '\0') { const unsigned char *nextLine; text.baseline.y += leading; text.CharCount = (COUNT) ~0; getLineWithinWidth(&text, &nextLine, lineWidth, text.CharCount); // This will also fill in text->CharCount. font_DrawText (&text); text.pStr = nextLine; } out: SetContextClipRect (&oldRect); } // Use an empty string to clear the status area. static void DrawMeleeStatusMessage (const char *message) { CONTEXT oldContext; RECT r; LockMutex (GraphicsLock); oldContext = SetContext (SpaceContext); r.corner.x = MELEE_STATUS_X_OFFS; r.corner.y = MELEE_STATUS_Y_OFFS; r.extent.width = MELEE_STATUS_WIDTH; r.extent.height = MELEE_STATUS_HEIGHT; RepairMeleeFrame (&r); if (message[0] != '\0') { TEXT lfText; lfText.pStr = message; lfText.align = ALIGN_LEFT; lfText.CharCount = (COUNT)~0; SetContextFont (MicroFont); SetContextForeGroundColor (MELEE_STATUS_COLOR); BatchGraphics (); multiLineDrawText (&lfText, &r); UnbatchGraphics (); } SetContext (oldContext); UnlockMutex (GraphicsLock); } static void UpdateMeleeStatusMessage (ssize_t player) { NetConnection *conn; assert (player == -1 || (player >= 0 && player < NUM_PLAYERS)); if (player == -1) { DrawMeleeStatusMessage (""); return; } conn = netConnections[player]; if (conn == NULL) { DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 0)); // "Unconnected. Press LEFT to connect." return; } switch (NetConnection_getState (conn)) { case NetState_unconnected: DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 0)); // "Unconnected. Press LEFT to connect." break; case NetState_connecting: if (NetConnection_getPeerOptions(conn)->isServer) DrawMeleeStatusMessage ( GAME_STRING (NETMELEE_STRING_BASE + 1)); // "Awaiting incoming connection...\n" // "Press RIGHT to cancel." else DrawMeleeStatusMessage ( GAME_STRING (NETMELEE_STRING_BASE + 2)); // "Attempting outgoing connection...\n" // "Press RIGHT to cancel." break; case NetState_init: case NetState_inSetup: DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 3)); // "Connected. Press RIGHT to disconnect." break; default: DrawMeleeStatusMessage (""); break; } } #endif /* NETPLAY */ // XXX: this function is called when the current selection is blinking off. // The caller should hold the GraphicsLock. static void Deselect (BYTE opt) { switch (opt) { case START_MELEE: DrawMeleeIcon (25); /* "Battle!" (not highlighted) */ break; case LOAD_TOP: case LOAD_BOT: if (pMeleeState->InputFunc != DoLoadTeam) DrawMeleeIcon (opt == LOAD_TOP ? 17 : 22); else DrawFileStrings (pMeleeState, 0); break; case SAVE_TOP: DrawMeleeIcon (18); /* "Save" (top; not highlighted) */ break; case SAVE_BOT: DrawMeleeIcon (21); /* "Save" (bottom; not highlighted) */ break; #ifdef NETPLAY case NET_TOP: DrawMeleeIcon (35); break; case NET_BOT: DrawMeleeIcon (37); break; #endif case QUIT_BOT: DrawMeleeIcon (29); break; case CONTROLS_TOP: case CONTROLS_BOT: { COUNT which_side; which_side = opt == CONTROLS_TOP ? 1 : 0; DrawControls (which_side, FALSE); break; } case EDIT_MELEE: if (pMeleeState->InputFunc == DoEdit) { if (pMeleeState->row < NUM_MELEE_ROWS) DrawShipBoxCurrent (pMeleeState, FALSE); else if (pMeleeState->CurIndex == (BYTE)~0) DrawTeamString (pMeleeState, pMeleeState->side, DTSHS_NORMAL); } else if (pMeleeState->InputFunc == DoPickShip) { DrawPickIcon (pMeleeState->CurIndex, 1); } break; } } // XXX: this function is called when the current selection is blinking off. // The caller should hold the GraphicsLock. static void Select (BYTE opt) { switch (opt) { case START_MELEE: DrawMeleeIcon (26); /* "Battle!" (highlighted) */ break; case LOAD_TOP: case LOAD_BOT: if (pMeleeState->InputFunc != DoLoadTeam) DrawMeleeIcon (opt == LOAD_TOP ? 19 : 24); else DrawFileStrings (pMeleeState, 1); break; case SAVE_TOP: DrawMeleeIcon (20); /* "Save" (top; highlighted) */ break; case SAVE_BOT: DrawMeleeIcon (23); /* "Save" (bottom; highlighted) */ break; #ifdef NETPLAY case NET_TOP: DrawMeleeIcon (36); /* "Save" (top; highlighted) */ break; case NET_BOT: DrawMeleeIcon (38); /* "Save" (bottom; highlighted) */ break; #endif case QUIT_BOT: DrawMeleeIcon (30); break; case CONTROLS_TOP: case CONTROLS_BOT: { COUNT which_side; which_side = opt == CONTROLS_TOP ? 1 : 0; DrawControls (which_side, TRUE); break; } case EDIT_MELEE: if (pMeleeState->InputFunc == DoEdit) { if (pMeleeState->row < NUM_MELEE_ROWS) DrawShipBoxCurrent (pMeleeState, TRUE); else if (pMeleeState->CurIndex == (BYTE)~0) DrawTeamString (pMeleeState, pMeleeState->side, DTSHS_SELECTED); } else if (pMeleeState->InputFunc == DoPickShip) { DrawPickIcon (pMeleeState->CurIndex, 0); } break; } } static int flash_selection_func (void *data) { DWORD TimeIn; Task task = (Task) data; TimeIn = GetTimeCounter (); while (!Task_ReadState (task, TASK_EXIT)) { #define FLASH_RATE (ONE_SECOND / 8) CONTEXT OldContext; LockMutex (GraphicsLock); OldContext = SetContext (SpaceContext); Deselect (pMeleeState->MeleeOption); SetContext (OldContext); UnlockMutex (GraphicsLock); SleepThreadUntil (TimeIn + FLASH_RATE); TimeIn = GetTimeCounter (); LockMutex (GraphicsLock); OldContext = SetContext (SpaceContext); Select (pMeleeState->MeleeOption); SetContext (OldContext); UnlockMutex (GraphicsLock); SleepThreadUntil (TimeIn + FLASH_RATE); TimeIn = GetTimeCounter (); } FinishTask (task); return 0; } static void InitMelee (PMELEE_STATE pMS) { RECT r; SetContext (SpaceContext); SetContextFGFrame (Screen); SetContextClipRect (NULL_PTR); SetContextBackGroundColor (BLACK_COLOR); ClearDrawable (); r.corner.x = SAFE_X; r.corner.y = SAFE_Y; r.extent.width = SCREEN_WIDTH - (SAFE_X * 2); r.extent.height = SCREEN_HEIGHT - (SAFE_Y * 2); SetContextClipRect (&r); r.corner.x = r.corner.y = 0; RedrawMeleeFrame (); pMS->flash_task = AssignTask (flash_selection_func, 2048, "flash melee selection"); } static void DrawMeleeShipStrings (PMELEE_STATE pMS, BYTE NewStarShip) { RECT r, OldRect; HSTARSHIP hStarShip; STARSHIPPTR StarShipPtr; CONTEXT OldContext; LockMutex (GraphicsLock); OldContext = SetContext (StatusContext); GetContextClipRect (&OldRect); r = OldRect; r.corner.x += ((SAFE_X << 1) - 32) + MENU_X_OFFS; r.corner.y += 76; r.extent.height = SHIP_INFO_HEIGHT; SetContextClipRect (&r); BatchGraphics (); if (NewStarShip == MELEE_NONE) { RECT r; TEXT t; ClearShipStatus (BAD_GUY_YOFFS); SetContextFont (StarConFont); r.corner.x = 3; r.corner.y = 4; r.extent.width = 57; r.extent.height = 60; SetContextForeGroundColor (BLACK_COLOR); DrawRectangle (&r); t.baseline.x = STATUS_WIDTH >> 1; t.baseline.y = 32; t.align = ALIGN_CENTER; if (pMS->row < NUM_MELEE_ROWS) { t.pStr = GAME_STRING (MELEE_STRING_BASE + 0); // "Empty" t.CharCount = (COUNT)~0; font_DrawText (&t); t.pStr = GAME_STRING (MELEE_STRING_BASE + 1); // "Slot" } else { t.pStr = GAME_STRING (MELEE_STRING_BASE + 2); // "Team" t.CharCount = (COUNT)~0; font_DrawText (&t); t.pStr = GAME_STRING (MELEE_STRING_BASE + 3); // "Name" } t.baseline.y += TINY_TEXT_HEIGHT; t.CharCount = (COUNT)~0; font_DrawText (&t); } else { hStarShip = GetStarShipFromIndex (&master_q, NewStarShip); StarShipPtr = LockStarShip (&master_q, hStarShip); InitShipStatus (StarShipPtr, NULL_PTR); UnlockStarShip (&master_q, hStarShip); } UnbatchGraphics (); SetContextClipRect (&OldRect); SetContext (OldContext); UnlockMutex (GraphicsLock); } static void UpdateCurrentShip (PMELEE_STATE pMS) { FleetShipIndex fleetShipIndex = GetShipIndex (pMS->row, pMS->col); if (pMS->row == NUM_MELEE_ROWS) pMS->CurIndex = MELEE_NONE; else pMS->CurIndex = pMS->TeamImage[pMS->side].ShipList[fleetShipIndex]; DrawMeleeShipStrings (pMS, (BYTE)(pMS->CurIndex)); } // returns (COUNT) ~0 for an invalid ship. static COUNT GetShipValue (BYTE StarShip) { HSTARSHIP hStarShip; if (StarShip == MELEE_NONE) return 0; hStarShip = GetStarShipFromIndex (&master_q, StarShip); if (hStarShip == 0) return (COUNT)~0; { STARSHIPPTR StarShipPtr; COUNT val; StarShipPtr = LockStarShip (&master_q, hStarShip); val = StarShipPtr->RaceDescPtr->ship_info.ship_cost; UnlockStarShip (&master_q, hStarShip); return val; } } static COUNT GetTeamValue (TEAM_IMAGE *pTI) { FleetShipIndex index; COUNT val; val = 0; for (index = 0; index < MELEE_FLEET_SIZE; index++) { BYTE StarShip = pTI->ShipList[index]; COUNT shipVal = GetShipValue (StarShip); if (shipVal == (COUNT)~0) pTI->ShipList[index] = MELEE_NONE; val += shipVal; } return val; } static int ReadTeamImage (TEAM_IMAGE *pTI, uio_Stream *load_fp) { int status; FleetShipIndex i; status = ReadResFile (pTI, sizeof (*pTI), 1, load_fp); if (status != 1) return -1; // Sanity check on the entries. for (i = 0; i < MELEE_FLEET_SIZE; i++) { BYTE StarShip = pTI->ShipList[i]; if (StarShip == MELEE_NONE) continue; if (StarShip >= NUM_MELEE_SHIPS) { log_add(log_Warning, "Invalid ship type in loaded team (index " "%d, ship type is %d, max valid is %d).", i, StarShip, NUM_MELEE_SHIPS - 1); pTI->ShipList[i] = MELEE_NONE; } } return 0; } static int LoadTeamImage (DIRENTRY DirEntry, TEAM_IMAGE* pTI, UNICODE* pFilePath) { UNICODE file[NAME_MAX]; // local buf if needed UNICODE *pfile; uio_Stream *load_fp; int status; pfile = pFilePath != NULL_PTR ? pFilePath : file; GetDirEntryContents (DirEntry, (STRINGPTR)pfile, FALSE); load_fp = res_OpenResFile (meleeDir, pfile, "rb"); if (load_fp == 0) status = -1; else { if (LengthResFile (load_fp) != sizeof (*pTI)) status = -1; else status = ReadTeamImage (pTI, load_fp); res_CloseResFile (load_fp); } return status; } static void DrawFileStrings (PMELEE_STATE pMS, int HiLiteState) { #define ENTRY_HEIGHT 32 COORD y; COUNT top, bot; TEXT Text, rtText; CONTEXT OldContext; UNICODE buf[60]; Text.baseline.x = 5; y = 34; Text.align = ALIGN_LEFT; rtText.pStr = buf; rtText.align = ALIGN_RIGHT; rtText.baseline.x = Text.baseline.x + NUM_MELEE_COLUMNS * (MELEE_BOX_WIDTH + MELEE_BOX_SPACE) - 1; top = pMS->TopTeamIndex; if (HiLiteState == 1) { COUNT new_; new_ = pMS->CurIndex; bot = pMS->BotTeamIndex; if (new_ < top || new_ > bot) { if (new_ < top) top = new_; else top += new_ - bot; pMS->TopTeamIndex = top; HiLiteState = -1; } } OldContext = SetContext (SpaceContext); SetContextFont (MicroFont); BatchGraphics (); if (HiLiteState != -1) { bot = pMS->CurIndex - top; Text.baseline.y = y + bot * ENTRY_HEIGHT; Text.pStr = pMS->FileList[bot].TeamName; Text.CharCount = (COUNT)~0; SetContextForeGroundColor (HiLiteState == 0 ? BUILD_COLOR (MAKE_RGB15 (15, 16, 27), 0x00) : BUILD_COLOR (MAKE_RGB15 (23, 24, 29), 0x00)); font_DrawText (&Text); rtText.baseline.y = Text.baseline.y; sprintf (buf, "%d", GetTeamValue (&pMS->FileList[bot])); rtText.CharCount = (COUNT)~0; font_DrawText (&rtText); } else { COUNT teams_left; DrawMeleeIcon (28); /* Load team frame */ Text.baseline.y = y; teams_left = (COUNT)( GetDirEntryTableCount (pMS->TeamDE) + NUM_PREBUILT - top); if (teams_left) { bot = top - 1; do { FleetShipIndex index; STAMP s; if (++bot < NUM_PREBUILT) pMS->FileList[bot - top] = pMS->PreBuiltList[bot]; else { pMS->TeamDE = SetAbsDirEntryTableIndex ( pMS->TeamDE, bot - NUM_PREBUILT); if (-1 == LoadTeamImage (pMS->TeamDE, &pMS->FileList[bot - top], NULL_PTR)) { pMS->FileList[bot - top] = pMS->PreBuiltList[0]; } } { Text.pStr = pMS->FileList[bot - top].TeamName; Text.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (15, 16, 27), 0x00)); font_DrawText (&Text); rtText.baseline.y = Text.baseline.y; sprintf (buf, "%d", GetTeamValue (&pMS->FileList[bot - top])); rtText.CharCount = (COUNT)~0; font_DrawText (&rtText); } s.origin.x = Text.baseline.x + 1; s.origin.y = Text.baseline.y + 4; for (index = 0; index < MELEE_FLEET_SIZE; index++) { BYTE StarShip; StarShip = pMS->FileList[bot - top].ShipList[index]; if (StarShip != MELEE_NONE) { HSTARSHIP hStarShip; STARSHIPPTR StarShipPtr; hStarShip = GetStarShipFromIndex (&master_q, StarShip); StarShipPtr = LockStarShip (&master_q, hStarShip); s.frame = StarShipPtr->RaceDescPtr->ship_info.icons; DrawStamp (&s); s.origin.x += 17; UnlockStarShip (&master_q, hStarShip); } } Text.baseline.y += ENTRY_HEIGHT; } while (--teams_left && bot - top < MAX_VIS_TEAMS - 1); pMS->BotTeamIndex = bot; } } UnbatchGraphics (); SetContext (OldContext); } static BOOLEAN DoLoadTeam (PMELEE_STATE pMS) { SIZE index; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN | MENU_SOUND_PAGEUP | MENU_SOUND_PAGEDOWN, MENU_SOUND_SELECT); if (!pMS->Initialized) { LockMutex (GraphicsLock); Select (pMS->MeleeOption); pMS->TopTeamIndex = pMS->CurIndex; if (pMS->TopTeamIndex == (COUNT)~0) { pMS->TopTeamIndex = 0; pMS->CurIndex = 0; } else if (pMS->TopTeamIndex <= MAX_VIS_TEAMS / 2) pMS->TopTeamIndex = 0; else pMS->TopTeamIndex -= MAX_VIS_TEAMS / 2; DrawFileStrings (pMS, -1); pMS->Initialized = TRUE; pMS->InputFunc = DoLoadTeam; UnlockMutex (GraphicsLock); } else if (PulsedInputState.menu[KEY_MENU_SELECT] | PulsedInputState.menu[KEY_MENU_CANCEL]) { if (!PulsedInputState.menu[KEY_MENU_CANCEL]) { pMS->TeamImage[pMS->side] = pMS->FileList[pMS->CurIndex - pMS->TopTeamIndex]; pMS->star_bucks[pMS->side] = GetTeamValue (&pMS->TeamImage[pMS->side]); entireFleetChanged (pMS, pMS->side); teamStringChanged (pMS, pMS->side); } pMS->InputFunc = DoMelee; { RECT r; GetFrameRect (SetAbsFrameIndex (MeleeFrame, 28), &r); LockMutex (GraphicsLock); RepairMeleeFrame (&r); UnlockMutex (GraphicsLock); } InTime = GetTimeCounter (); } else { SIZE old_index, NewTop; NewTop = pMS->TopTeamIndex; index = old_index = pMS->CurIndex; if (PulsedInputState.menu[KEY_MENU_UP]) { if (index-- == 0) index = 0; if (index < NewTop && (NewTop -= MAX_VIS_TEAMS) < 0) NewTop = 0; } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { if ((int)index < (int)GetDirEntryTableCount (pMS->TeamDE) + NUM_PREBUILT - 1) ++index; if ((int)index > (int)pMS->BotTeamIndex) NewTop = index; } else if (PulsedInputState.menu[KEY_MENU_PAGE_UP]) { index -= MAX_VIS_TEAMS; if (index < 0) { index = 0; NewTop = 0; } else { NewTop -= MAX_VIS_TEAMS; if (NewTop < 0) NewTop = 0; } } else if (PulsedInputState.menu[KEY_MENU_PAGE_DOWN]) { index += MAX_VIS_TEAMS; if ((int) index < (int)(GetDirEntryTableCount (pMS->TeamDE) + NUM_PREBUILT)) NewTop += MAX_VIS_TEAMS; else { index = GetDirEntryTableCount (pMS->TeamDE) + NUM_PREBUILT - 1; if (index - (MAX_VIS_TEAMS - 1) > NewTop) { NewTop = index - (MAX_VIS_TEAMS - 1); if (NewTop < 0) NewTop = 0; } } } if (index != old_index) { LockMutex (GraphicsLock); if ((int)NewTop == (int)pMS->TopTeamIndex) Deselect (pMS->MeleeOption); else { pMS->TopTeamIndex = NewTop; DrawFileStrings (pMS, -1); } pMS->CurIndex = index; UnlockMutex (GraphicsLock); } } return (TRUE); } static int WriteTeamImage (TEAM_IMAGE *pTI, uio_Stream *save_fp) { return (WriteResFile (pTI, sizeof (*pTI), 1, save_fp)); } static void LoadTeamList (PMELEE_STATE pMS, UNICODE *pbuf) { COUNT num_entries; char file[NAME_MAX]; GetNewList: DestroyDirEntryTable (ReleaseDirEntryTable (pMS->TeamDE)); pMS->TeamDE = CaptureDirEntryTable ( LoadDirEntryTable (meleeDir, "", ".mle", match_MATCH_SUFFIX, &num_entries)); pMS->CurIndex = 0; while (num_entries--) { int status; TEAM_IMAGE TI; status = LoadTeamImage (pMS->TeamDE, &TI, file); if (status == -1) { BOOLEAN deleteStatus; log_add (log_Error, "Could not load '%s', deleting", file); deleteStatus = DeleteResFile (meleeDir, file); if (deleteStatus == FALSE) { // XXX: see bug #823 log_add (log_Fatal, "FATAL: Could not delete '%s'", file); exit (EXIT_FAILURE); } goto GetNewList; } if (pbuf && stricmp (file, pbuf) == 0) { pMS->CurIndex = GetDirEntryTableIndex (pMS->TeamDE) + NUM_PREBUILT; pbuf = 0; } pMS->TeamDE = SetRelDirEntryTableIndex (pMS->TeamDE, 1); } pMS->TeamDE = SetAbsDirEntryTableIndex (pMS->TeamDE, 0); } static BOOLEAN DoSaveTeam (PMELEE_STATE pMS) { STAMP MsgStamp; char file[NAME_MAX]; uio_Stream *save_fp; CONTEXT OldContext; sprintf (file, "%s.mle", pMS->TeamImage[pMS->side].TeamName); LockMutex (GraphicsLock); OldContext = SetContext (ScreenContext); ConfirmSaveLoad (&MsgStamp); save_fp = res_OpenResFile (meleeDir, file, "wb"); if (save_fp) { BOOLEAN err; err = (BOOLEAN)(WriteTeamImage ( &pMS->TeamImage[pMS->side], save_fp) == 0); if (res_CloseResFile (save_fp) == 0) err = TRUE; if (err) save_fp = 0; } pMS->CurIndex = 0; if (save_fp == 0) { DrawStamp (&MsgStamp); DestroyDrawable (ReleaseDrawable (MsgStamp.frame)); SetContext (OldContext); UnlockMutex (GraphicsLock); DeleteResFile (meleeDir, file); SaveProblem (); } LoadTeamList (pMS, file); if (save_fp) { DrawStamp (&MsgStamp); DestroyDrawable (ReleaseDrawable (MsgStamp.frame)); SetContext (OldContext); UnlockMutex (GraphicsLock); } return (save_fp != 0); } static void DeleteCurrentShip (PMELEE_STATE pMS) { RECT r; HSTARSHIP hStarShip; STARSHIPPTR StarShipPtr; FleetShipIndex fleetShipIndex; int CurIndex; fleetShipIndex = GetShipIndex (pMS->row, pMS->col); CurIndex = pMS->TeamImage[pMS->side].ShipList[fleetShipIndex]; hStarShip = GetStarShipFromIndex (&master_q, CurIndex); StarShipPtr = LockStarShip (&master_q, hStarShip); if (StarShipPtr) { pMS->star_bucks[pMS->side] -= StarShipPtr->RaceDescPtr->ship_info.ship_cost; UnlockStarShip (&master_q, hStarShip); pMS->TeamImage[pMS->side].ShipList[fleetShipIndex] = MELEE_NONE; } LockMutex (GraphicsLock); GetShipBox (&r, pMS->side, pMS->row, pMS->col); RepairMeleeFrame (&r); DrawTeamString (pMS, pMS->side, DTSHS_REPAIR); UnlockMutex (GraphicsLock); } static void AdvanceCursor (PMELEE_STATE pMS) { if (++pMS->col == NUM_MELEE_COLUMNS) { if (++pMS->row < NUM_MELEE_ROWS) pMS->col = 0; else { pMS->col = NUM_MELEE_COLUMNS - 1; pMS->row = NUM_MELEE_ROWS - 1; } } } static BOOLEAN OnTeamNameChange (PTEXTENTRY_STATE pTES) { PMELEE_STATE pMS = (PMELEE_STATE) pTES->CbParam; BOOLEAN ret; COUNT hl = DTSHS_EDIT; pMS->CurIndex = pTES->CursorPos; if (pTES->JoystickMode) hl |= DTSHS_BLOCKCUR; LockMutex (GraphicsLock); ret = DrawTeamString (pMS, pMS->side, hl); UnlockMutex (GraphicsLock); return ret; } static BOOLEAN DoEdit (PMELEE_STATE pMS) { if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT | MENU_SOUND_DELETE); if (!pMS->Initialized) { FleetShipIndex fleetShipIndex = GetShipIndex (pMS->row, pMS->col); pMS->CurIndex = pMS->TeamImage[pMS->side].ShipList[fleetShipIndex]; DrawMeleeShipStrings (pMS, (BYTE)pMS->CurIndex); pMS->Initialized = TRUE; pMS->InputFunc = DoEdit; return TRUE; } #ifdef NETPLAY netInput (); #endif if ((pMS->row < NUM_MELEE_ROWS || pMS->CurIndex == (BYTE)~0) && (PulsedInputState.menu[KEY_MENU_CANCEL] || (PulsedInputState.menu[KEY_MENU_RIGHT] && (pMS->col == NUM_MELEE_COLUMNS - 1 || pMS->row == NUM_MELEE_ROWS)))) { // Done editing the teams. LockMutex (GraphicsLock); Deselect (EDIT_MELEE); pMS->CurIndex = (COUNT)~0; pMS->MeleeOption = START_MELEE; pMS->InputFunc = DoMelee; UnlockMutex (GraphicsLock); InTime = GetTimeCounter (); } else if (pMS->row < NUM_MELEE_ROWS && (PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_SPECIAL])) { // Show a popup to add a new ship to the current team. if (PulsedInputState.menu[KEY_MENU_SELECT]) pMS->Initialized = 0; else pMS->Initialized = -1; TFB_ResetControls (); DoPickShip (pMS); } else if (pMS->row < NUM_MELEE_ROWS && PulsedInputState.menu[KEY_MENU_DELETE]) { // Remove the currently selected ship from the current team. FleetShipIndex fleetShipIndex; DeleteCurrentShip (pMS); fleetShipIndex = GetShipIndex (pMS->row, pMS->col); fleetShipChanged (pMS, pMS->side, fleetShipIndex); AdvanceCursor (pMS); UpdateCurrentShip(pMS); } else { COUNT side, row, col; side = pMS->side; row = pMS->row; col = pMS->col; if (row == NUM_MELEE_ROWS) { // Edit the name of the current team. if (PulsedInputState.menu[KEY_MENU_SELECT]) { TEXTENTRY_STATE tes; // going to enter text // XXX: CurIndex is abused here; DrawTeamString expects // CurIndex to contain the current cursor position pMS->CurIndex = 0; LockMutex (GraphicsLock); DrawTeamString (pMS, pMS->side, DTSHS_EDIT); UnlockMutex (GraphicsLock); tes.Initialized = FALSE; tes.MenuRepeatDelay = 0; tes.BaseStr = pMS->TeamImage[pMS->side].TeamName; tes.CursorPos = 0; tes.MaxSize = MAX_TEAM_CHARS + 1; tes.CbParam = pMS; tes.ChangeCallback = OnTeamNameChange; tes.FrameCallback = 0; DoTextEntry (&tes); // done entering pMS->CurIndex = (BYTE)~0; LockMutex (GraphicsLock); DrawTeamString (pMS, pMS->side, DTSHS_REPAIR); UnlockMutex (GraphicsLock); teamStringChanged (pMS, pMS->side); return (TRUE); } } { if (PulsedInputState.menu[KEY_MENU_LEFT]) { if (col-- == 0) col = 0; } else if (PulsedInputState.menu[KEY_MENU_RIGHT]) { if (++col == NUM_MELEE_COLUMNS) col = NUM_MELEE_COLUMNS - 1; } if (PulsedInputState.menu[KEY_MENU_UP]) { if (row-- == 0) { if (side == 0) row = 0; else { row = NUM_MELEE_ROWS; side = !side; } } } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { if (row++ == NUM_MELEE_ROWS) { if (side == 1) row = NUM_MELEE_ROWS; else { row = 0; side = !side; } } } } if (col != pMS->col || row != pMS->row || side != pMS->side) { LockMutex (GraphicsLock); Deselect (EDIT_MELEE); pMS->side = side; pMS->row = row; pMS->col = col; UnlockMutex (GraphicsLock); UpdateCurrentShip(pMS); } } #ifdef NETPLAY flushPacketQueues (); #endif return (TRUE); } // Handle the popup from which a ship to add to the fleet can be chosen. static BOOLEAN DoPickShip (PMELEE_STATE pMS) { STARSHIPPTR StarShipPtr; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); if (pMS->Initialized <= 0) { if (pMS->CurIndex == (BYTE)~0 && pMS->Initialized == 0) pMS->CurIndex = 0; else if (pMS->CurIndex != (BYTE)~0) { DeleteCurrentShip (pMS); } if (pMS->Initialized == 0) { LockMutex (GraphicsLock); Deselect (EDIT_MELEE); pMS->InputFunc = DoPickShip; DrawPickFrame (pMS); pMS->Initialized = TRUE; UnlockMutex (GraphicsLock); } else { FleetShipIndex fleetShipIndex = GetShipIndex (pMS->row, pMS->col); LockMutex (GraphicsLock); Deselect (EDIT_MELEE); pMS->Initialized = TRUE; AdvanceCursor (pMS); pMS->CurIndex = pMS->TeamImage[pMS->side].ShipList[fleetShipIndex]; UnlockMutex (GraphicsLock); DrawMeleeShipStrings (pMS, (BYTE)(pMS->CurIndex)); } } else if (PulsedInputState.menu[KEY_MENU_SELECT] || PulsedInputState.menu[KEY_MENU_CANCEL]) { FleetShipIndex index = GetShipIndex (pMS->row, pMS->col); pMS->InputFunc = 0; /* disable ship flashing */ if (!PulsedInputState.menu[KEY_MENU_CANCEL]) { // Add the currently selected ship to the fleet. HSTARSHIP hStarShip; hStarShip = GetStarShipFromIndex (&master_q, pMS->CurIndex); StarShipPtr = LockStarShip (&master_q, hStarShip); pMS->star_bucks[pMS->side] += StarShipPtr->RaceDescPtr->ship_info.ship_cost; UnlockStarShip (&master_q, hStarShip); pMS->TeamImage[pMS->side].ShipList[index] = pMS->CurIndex; LockMutex (GraphicsLock); DrawTeamString (pMS, pMS->side, DTSHS_REPAIR); DrawShipBoxCurrent (pMS, FALSE); UnlockMutex (GraphicsLock); AdvanceCursor (pMS); } { RECT r; GetFrameRect (BuildPickFrame, &r); LockMutex (GraphicsLock); RepairMeleeFrame (&r); UnlockMutex (GraphicsLock); } fleetShipChanged (pMS, pMS->side, index); UpdateCurrentShip(pMS); pMS->InputFunc = DoEdit; return (TRUE); } else if (PulsedInputState.menu[KEY_MENU_SPECIAL]) { DoShipSpin (pMS->CurIndex, (MUSIC_REF)0); return (TRUE); } { BYTE NewStarShip; NewStarShip = pMS->CurIndex; if (PulsedInputState.menu[KEY_MENU_LEFT]) { if (NewStarShip-- % NUM_PICK_COLS == 0) NewStarShip += NUM_PICK_COLS; } else if (PulsedInputState.menu[KEY_MENU_RIGHT]) { if (++NewStarShip % NUM_PICK_COLS == 0) NewStarShip -= NUM_PICK_COLS; } if (PulsedInputState.menu[KEY_MENU_UP]) { if (NewStarShip >= NUM_PICK_COLS) NewStarShip -= NUM_PICK_COLS; else NewStarShip += NUM_PICK_COLS * (NUM_PICK_ROWS - 1); } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { if (NewStarShip < NUM_PICK_COLS * (NUM_PICK_ROWS - 1)) NewStarShip += NUM_PICK_COLS; else NewStarShip -= NUM_PICK_COLS * (NUM_PICK_ROWS - 1); } if (NewStarShip != pMS->CurIndex) { LockMutex (GraphicsLock); Deselect (EDIT_MELEE); pMS->CurIndex = NewStarShip; UnlockMutex (GraphicsLock); DrawMeleeShipStrings (pMS, NewStarShip); } } return (TRUE); } // Returns -1 if a connection has been aborted. static ssize_t numPlayersReady (void) { size_t player; size_t numDone; numDone = 0; for (player = 0; player < NUM_PLAYERS; player++) { if (!(PlayerControl[player] & NETWORK_CONTROL)) { numDone++; continue; } #ifdef NETPLAY { NetConnection *conn; conn = netConnections[player]; if (conn == NULL || !NetConnection_isConnected (conn)) return -1; if (NetConnection_getState(conn) > NetState_inSetup) numDone++; } #endif } return numDone; } // The player has pressed "Start Game", and all Network players are // connected. We're now just waiting for the confirmation of the other // party. // When the other party changes something in the settings, the confirmation // is cancelled. static BOOLEAN DoConfirmSettings (PMELEE_STATE pMS) { #ifdef NETPLAY ssize_t numDone; #endif if (PulsedInputState.menu[KEY_MENU_CANCEL]) { pMS->InputFunc = DoMelee; #ifdef NETPLAY cancelConfirmations (); DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 4)); // "Confirmation cancelled. Press FIRE to reconfirm." #endif return TRUE; } if (PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_UP] || PulsedInputState.menu[KEY_MENU_DOWN]) { pMS->InputFunc = DoMelee; #ifdef NETPLAY cancelConfirmations (); DrawMeleeStatusMessage (""); #endif return DoMelee (pMS); // Let the pressed keys take effect immediately. } #ifndef NETPLAY pMS->InputFunc = DoMelee; SeedRandomNumbers (); StartMelee (pMS); if (GLOBAL (CurrentActivity) & CHECK_ABORT) return FALSE; return TRUE; #else closeDisconnectedConnections (); netInput (); SleepThread (ONE_SECOND / 120); numDone = numPlayersReady (); if (numDone == -1) { // Connection aborted cancelConfirmations (); flushPacketQueues (); pMS->InputFunc = DoMelee; return TRUE; } else if (numDone != NUM_SIDES) { // Still waiting for some confirmation. return TRUE; } // All sides have confirmed. // Send our own prefered frame delay. sendInputDelayConnections (netplayOptions.inputDelay); // Synchronise the RNGs: { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn; if (!(PlayerControl[player] & NETWORK_CONTROL)) continue; conn = netConnections[player]; assert (conn != NULL); if (!NetConnection_isConnected (conn)) continue; if (NetConnection_getDiscriminant(conn)) Netplay_seedRandom (conn, SeedRandomNumbers ()); } flushPacketQueues (); } { // One side will send the seed followed by 'Done' and wait // for the other side to report 'Done'. // The other side will report 'Done' and will wait for the other // side to report 'Done', but before the reception of 'Done' // it will have received the seed. bool allOk = negotiateReadyConnections (true, NetState_interBattle); if (!allOk) return FALSE; } // The maximum value for all connections is used. { bool ok = setupInputDelay(netplayOptions.inputDelay); if (!ok) return FALSE; } pMS->InputFunc = DoMelee; StartMelee (pMS); if (GLOBAL (CurrentActivity) & CHECK_ABORT) return FALSE; return TRUE; #endif /* defined (NETPLAY) */ } static void LoadMeleeInfo (PMELEE_STATE pMS) { STAMP s; CONTEXT OldContext; RECT r; COUNT i; // reverting to original behavior OldContext = SetContext (OffScreenContext); if (PickMeleeFrame) DestroyDrawable (ReleaseDrawable (PickMeleeFrame)); PickMeleeFrame = CaptureDrawable (CreateDrawable ( WANT_PIXMAP, MELEE_WIDTH, MELEE_HEIGHT, 2)); s.origin.x = 0; s.origin.y = 0; s.frame = CaptureDrawable (LoadGraphic (MELEE_PICK_MASK_PMAP_ANIM)); SetContextFGFrame (PickMeleeFrame); DrawStamp (&s); s.frame = IncFrameIndex (s.frame); SetContextFGFrame (IncFrameIndex (PickMeleeFrame)); DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); MeleeFrame = CaptureDrawable (LoadGraphic (MELEE_SCREEN_PMAP_ANIM)); // create team building ship selection box s.frame = SetAbsFrameIndex (MeleeFrame, 27); GetFrameRect (s.frame, &r); BuildPickFrame = CaptureDrawable (CreateDrawable ( WANT_PIXMAP, r.extent.width, r.extent.height, 1)); SetContextFGFrame (BuildPickFrame); SetFrameHot (s.frame, MAKE_HOT_SPOT (0, 0)); DrawStamp (&s); for (i = 0; i < NUM_PICK_COLS * NUM_PICK_ROWS; ++i) DrawPickIcon (i, 1); SetContext (OldContext); InitSpace (); LoadTeamList (pMS, 0); } static void FreeMeleeInfo (PMELEE_STATE pMS) { if (pMS->flash_task) { ConcludeTask (pMS->flash_task); pMS->flash_task = 0; } DestroyDirEntryTable (ReleaseDirEntryTable (pMS->TeamDE)); pMS->TeamDE = 0; if (pMS->hMusic) { DestroyMusic (pMS->hMusic); pMS->hMusic = 0; } UninitSpace (); DestroyDrawable (ReleaseDrawable (MeleeFrame)); MeleeFrame = 0; DestroyDrawable (ReleaseDrawable (BuildPickFrame)); BuildPickFrame = 0; #ifdef NETPLAY closeAllConnections (); #endif } static void BuildAndDrawShipList (PMELEE_STATE pMS) { COUNT i; CONTEXT OldContext; OldContext = SetContext (OffScreenContext); for (i = 0; i < NUM_SIDES; ++i) { COUNT side; RECT r; TEXT t; STAMP s; UNICODE buf[30]; FleetShipIndex index; side = !i; s.frame = SetAbsFrameIndex (PickMeleeFrame, side); SetContextFGFrame (s.frame); GetFrameRect (s.frame, &r); t.baseline.x = r.extent.width >> 1; t.baseline.y = r.extent.height - NAME_AREA_HEIGHT + 4; r.corner.x += 2; r.corner.y += 2; r.extent.width -= (2 * 2) + (ICON_WIDTH + 2) + 1; r.extent.height -= (2 * 2) + NAME_AREA_HEIGHT; SetContextForeGroundColor (PICK_BG_COLOR); DrawFilledRectangle (&r); r.corner.x += 2; r.extent.width += (ICON_WIDTH + 2) - (2 * 2); r.corner.y += r.extent.height; r.extent.height = NAME_AREA_HEIGHT; DrawFilledRectangle (&r); // Team name at the bottom of the frame: t.align = ALIGN_CENTER; t.pStr = pMS->TeamImage[i].TeamName; t.CharCount = (COUNT)~0; SetContextFont (TinyFont); SetContextForeGroundColor (PICKSHIP_TEAM_NAME_TEXT_COLOR); font_DrawText (&t); // Total team value of the starting team: sprintf (buf, "%d", pMS->star_bucks[i]); t.baseline.x = 4; t.baseline.y = 7; t.align = ALIGN_LEFT; t.pStr = buf; t.CharCount = (COUNT)~0; SetContextForeGroundColor (PICKSHIP_TEAM_START_VALUE_COLOR); font_DrawText (&t); for (index = 0; index < MELEE_FLEET_SIZE; index++) { BYTE StarShip; StarShip = pMS->TeamImage[i].ShipList[index]; if (StarShip == MELEE_NONE) continue; { BYTE row, col; BYTE ship_cost; HSTARSHIP hStarShip, hBuiltShip; STARSHIPPTR StarShipPtr, BuiltShipPtr; hStarShip = GetStarShipFromIndex (&master_q, StarShip); StarShipPtr = LockStarShip (&master_q, hStarShip); hBuiltShip = Build (&race_q[side], StarShipPtr->RaceResIndex, 1 << side, NameCaptain (&race_q[side], StarShipPtr)); row = GetShipRow (index); col = GetShipColumn (index); s.origin.x = 4 + ((ICON_WIDTH + 2) * col); s.origin.y = 10 + ((ICON_HEIGHT + 2) * row); s.frame = StarShipPtr->RaceDescPtr->ship_info.icons; DrawStamp (&s); ship_cost = StarShipPtr->RaceDescPtr->ship_info.ship_cost; UnlockStarShip (&master_q, hStarShip); BuiltShipPtr = LockStarShip (&race_q[side], hBuiltShip); BuiltShipPtr->ShipFacing = index; BuiltShipPtr->special_counter = ship_cost; BuiltShipPtr->captains_name_index = StarShipCaptain (BuiltShipPtr); BuiltShipPtr->RaceDescPtr = StarShipPtr->RaceDescPtr; UnlockStarShip (&race_q[side], hBuiltShip); } } } SetContext (OldContext); } static void StartMelee (PMELEE_STATE pMS) { if (pMS->flash_task) { ConcludeTask (pMS->flash_task); pMS->flash_task = 0; } { BYTE black_buf[] = {FadeAllToBlack}; FadeMusic (0, ONE_SECOND / 2); SleepThreadUntil (XFormColorMap ( (COLORMAPPTR)black_buf, ONE_SECOND / 2) + ONE_SECOND / 60); FlushColorXForms (); StopMusic (); } FadeMusic (NORMAL_VOLUME, 0); if (pMS->hMusic) { DestroyMusic (pMS->hMusic); pMS->hMusic = 0; } do { LockMutex (GraphicsLock); BuildAndDrawShipList (pMS); UnlockMutex (GraphicsLock); WaitForSoundEnd (TFBSOUND_WAIT_ALL); load_gravity_well ((BYTE)((COUNT)TFB_Random () % NUMBER_OF_PLANET_TYPES)); Battle (); free_gravity_well (); if (GLOBAL (CurrentActivity) & CHECK_ABORT) return; { BYTE black_buf[] = { FadeAllToBlack }; SleepThreadUntil (XFormColorMap ( (COLORMAPPTR)black_buf, ONE_SECOND / 2) + ONE_SECOND / 60); FlushColorXForms (); } } while (0 /* !(GLOBAL (CurrentActivity) & CHECK_ABORT) */); GLOBAL (CurrentActivity) = SUPER_MELEE; pMS->Initialized = FALSE; } static void StartMeleeButtonPressed (PMELEE_STATE pMS) { if (pMS->star_bucks[0] == 0 || pMS->star_bucks[1] == 0) { PlayMenuSound (MENU_SOUND_FAILURE); return; } if ((PlayerControl[0] & NETWORK_CONTROL) && (PlayerControl[1] & NETWORK_CONTROL)) { DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 31)); // "Only one side at a time can be network controlled." return; } if (((PlayerControl[0] & NETWORK_CONTROL) && (PlayerControl[1] & COMPUTER_CONTROL)) || ((PlayerControl[0] & COMPUTER_CONTROL) && (PlayerControl[1] & NETWORK_CONTROL))) { DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 32)); // "Netplay with a computer-controlled side is currently // not possible." return; } #ifdef NETPLAY // Check whether all network parties are ready; { COUNT player; bool netReady = true; // We collect all error conditions, instead of only reporting // the first one. for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn; if (!(PlayerControl[player] & NETWORK_CONTROL)) continue; conn = netConnections[player]; if (conn == NULL || !NetConnection_isConnected (conn)) { // Connection for player not established. netReady = false; if (player == 0) DrawMeleeStatusMessage ( GAME_STRING (NETMELEE_STRING_BASE + 5)); // "Connection for bottom player not " // "established." else DrawMeleeStatusMessage ( GAME_STRING (NETMELEE_STRING_BASE + 6)); // "Connection for top player not " // "established." } else if (NetConnection_getState(conn) != NetState_inSetup) { // This side may be in the setup, but the network connection // is not in a state that setup information can be sent. netReady = false; if (player == 0) DrawMeleeStatusMessage ( GAME_STRING (NETMELEE_STRING_BASE + 14)); // "Connection for bottom player not ready." else DrawMeleeStatusMessage ( GAME_STRING (NETMELEE_STRING_BASE + 15)); // "Connection for top player not ready." } } if (!netReady) { PlayMenuSound (MENU_SOUND_FAILURE); return; } if (numPlayersReady () != NUM_PLAYERS) DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 7)); // "Waiting for remote confirmation." confirmConnections (); } #endif pMS->InputFunc = DoConfirmSettings; } #ifdef NETPLAY static BOOLEAN DoConnectingDialog (PMELEE_STATE pMS) { COUNT which_side = (pMS->MeleeOption == NET_TOP) ? 1 : 0; NetConnection *conn; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); if (!pMS->Initialized) { RECT r; FONT oldfont; COLOR oldcolor; TEXT t; // Build a network connection. if (netConnections[which_side] != NULL) closePlayerNetworkConnection(which_side); pMS->Initialized = TRUE; conn = openPlayerNetworkConnection (which_side, (void *) pMS); pMS->InputFunc = DoConnectingDialog; /* Draw the dialog box here */ LockMutex (GraphicsLock); oldfont = SetContextFont (StarConFont); oldcolor = SetContextForeGroundColor (BLACK_COLOR); BatchGraphics (); r.extent.width = 200; r.extent.height = 30; r.corner.x = (SCREEN_WIDTH - r.extent.width) >> 1; r.corner.y = (SCREEN_HEIGHT - r.extent.height) >> 1; DrawShadowedBox (&r, SHADOWBOX_BACKGROUND_COLOR, SHADOWBOX_DARK_COLOR, SHADOWBOX_MEDIUM_COLOR); if (NetConnection_getPeerOptions (conn)->isServer) { t.pStr = GAME_STRING (NETMELEE_STRING_BASE + 1); } else { t.pStr = GAME_STRING (NETMELEE_STRING_BASE + 2); } t.baseline.y = r.corner.y + 10; t.baseline.x = SCREEN_WIDTH >> 1; t.align = ALIGN_CENTER; t.CharCount = ~0; font_DrawText (&t); t.pStr = GAME_STRING (NETMELEE_STRING_BASE + 18); /* "Press SPACE to cancel" */ t.baseline.y += 16; font_DrawText (&t); // Restore original graphics SetContextFont (oldfont); SetContextForeGroundColor (oldcolor); UnbatchGraphics (); UnlockMutex (GraphicsLock); } netInput (); if (PulsedInputState.menu[KEY_MENU_CANCEL]) { // Terminate a network connection. if (netConnections[which_side] != NULL) { closePlayerNetworkConnection (which_side); UpdateMeleeStatusMessage (which_side); } RedrawMeleeFrame (); pMS->InputFunc = DoMelee; if (!pMS->flash_task) { pMS->flash_task = AssignTask (flash_selection_func, 2048, "flash melee selection"); } flushPacketQueues (); return TRUE; } conn = netConnections[which_side]; if (conn != NULL) { NetState status = NetConnection_getState (conn); if ((status == NetState_init) || (status == NetState_inSetup)) { /* Connection complete! */ PlayerControl[which_side] = NETWORK_CONTROL | STANDARD_RATING; SetPlayerInput (); DrawControls (which_side, TRUE); RedrawMeleeFrame (); UpdateMeleeStatusMessage (which_side); pMS->InputFunc = DoMelee; Deselect (pMS->MeleeOption); pMS->MeleeOption = START_MELEE; if (!pMS->flash_task) { pMS->flash_task = AssignTask (flash_selection_func, 2048, "flash melee selection"); } } } flushPacketQueues (); SleepThread (30); return TRUE; } /* Check for disconnections, and revert to human control if so */ static void check_for_disconnections (PMELEE_STATE pMS) { COUNT player; bool changed = FALSE; for (player = 0; player < NUM_PLAYERS; player++) { NetConnection *conn; if (!(PlayerControl[player] & NETWORK_CONTROL)) continue; conn = netConnections[player]; if (conn == NULL || !NetConnection_isConnected (conn)) { PlayerControl[player] = HUMAN_CONTROL | STANDARD_RATING; DrawControls (player, FALSE); log_add (log_User, "Player %d has disconnected; shifting " "controls\n", player); changed = TRUE; } } if (changed) { SetPlayerInput (); } (void) pMS; } #endif static BOOLEAN DoMelee (PMELEE_STATE pMS) { BOOLEAN force_select = FALSE; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); if (!pMS->Initialized) { if (pMS->hMusic) { StopMusic (); DestroyMusic (pMS->hMusic); pMS->hMusic = 0; } pMS->hMusic = LoadMusic (MELEE_MUSIC); pMS->Initialized = TRUE; pMS->MeleeOption = START_MELEE; PlayMusic (pMS->hMusic, TRUE, 1); LockMutex (GraphicsLock); InitMelee (pMS); UnlockMutex (GraphicsLock); { BYTE clut_buf[] = {FadeAllToColor}; XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 2); } InTime = GetTimeCounter (); return TRUE; } #ifdef NETPLAY netInput (); #endif if (PulsedInputState.menu[KEY_MENU_CANCEL] || PulsedInputState.menu[KEY_MENU_LEFT]) { // Start editing the teams. LockMutex (GraphicsLock); InTime = GetTimeCounter (); Deselect (pMS->MeleeOption); UnlockMutex (GraphicsLock); pMS->MeleeOption = EDIT_MELEE; pMS->Initialized = FALSE; if (PulsedInputState.menu[KEY_MENU_CANCEL]) { pMS->side = 0; pMS->row = 0; pMS->col = 0; } else { pMS->side = 0; pMS->row = NUM_MELEE_ROWS - 1; pMS->col = NUM_MELEE_COLUMNS - 1; } DoEdit (pMS); } else { MELEE_OPTIONS NewMeleeOption; NewMeleeOption = pMS->MeleeOption; if (PulsedInputState.menu[KEY_MENU_UP]) { InTime = GetTimeCounter (); if (NewMeleeOption-- == TOP_ENTRY) NewMeleeOption = TOP_ENTRY; } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { InTime = GetTimeCounter (); if (NewMeleeOption++ == QUIT_BOT) NewMeleeOption = QUIT_BOT; } if ((PlayerControl[0] & PlayerControl[1] & PSYTRON_CONTROL) && GetTimeCounter () - InTime > ONE_SECOND * 10) { force_select = TRUE; NewMeleeOption = START_MELEE; } if (NewMeleeOption != pMS->MeleeOption) { #ifdef NETPLAY if (pMS->MeleeOption == CONTROLS_TOP || pMS->MeleeOption == CONTROLS_BOT) UpdateMeleeStatusMessage (-1); #endif LockMutex (GraphicsLock); Deselect (pMS->MeleeOption); pMS->MeleeOption = NewMeleeOption; Select (pMS->MeleeOption); UnlockMutex (GraphicsLock); #ifdef NETPLAY if (NewMeleeOption == CONTROLS_TOP || NewMeleeOption == CONTROLS_BOT) { COUNT side = (NewMeleeOption == CONTROLS_TOP) ? 1 : 0; if (PlayerControl[side] & NETWORK_CONTROL) UpdateMeleeStatusMessage (side); else UpdateMeleeStatusMessage (-1); } #endif } if (PulsedInputState.menu[KEY_MENU_SELECT] || force_select) { switch (pMS->MeleeOption) { case START_MELEE: StartMeleeButtonPressed (pMS); if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); break; case LOAD_TOP: case LOAD_BOT: pMS->Initialized = FALSE; pMS->side = pMS->MeleeOption == LOAD_TOP ? 0 : 1; DoLoadTeam (pMS); break; case SAVE_TOP: case SAVE_BOT: pMS->side = pMS->MeleeOption == SAVE_TOP ? 0 : 1; if (pMS->star_bucks[pMS->side]) DoSaveTeam (pMS); else PlayMenuSound (MENU_SOUND_FAILURE); break; case QUIT_BOT: GLOBAL (CurrentActivity) |= CHECK_ABORT; break; #ifdef NETPLAY case NET_TOP: case NET_BOT: { COUNT which_side; BOOLEAN confirmed; if (pMS->flash_task) { ConcludeTask (pMS->flash_task); pMS->flash_task = 0; } which_side = pMS->MeleeOption == NET_TOP ? 1 : 0; confirmed = MeleeConnectDialog (which_side); RedrawMeleeFrame (); if (confirmed) { pMS->Initialized = FALSE; pMS->InputFunc = DoConnectingDialog; } else { if (!pMS->flash_task) { pMS->flash_task = AssignTask (flash_selection_func, 2048, "flash melee selection"); } } break; } #endif case CONTROLS_TOP: case CONTROLS_BOT: { COUNT which_side; which_side = pMS->MeleeOption == CONTROLS_TOP ? 1 : 0; if (PlayerControl[which_side] & HUMAN_CONTROL) PlayerControl[which_side] = COMPUTER_CONTROL | STANDARD_RATING; else if (PlayerControl[which_side] & AWESOME_RATING) { PlayerControl[which_side] = HUMAN_CONTROL | STANDARD_RATING; } #ifdef NETPLAY else if (PlayerControl[which_side] & NETWORK_CONTROL) { if (netConnections[which_side] != NULL) closePlayerNetworkConnection (which_side); UpdateMeleeStatusMessage (-1); PlayerControl[which_side] = HUMAN_CONTROL | STANDARD_RATING; } #endif /* NETPLAY */ else PlayerControl[which_side] = (( PlayerControl[which_side] & (STANDARD_RATING | GOOD_RATING | AWESOME_RATING)) << 1) | COMPUTER_CONTROL; SetPlayerInput (); DrawControls (which_side, TRUE); break; } } } } #ifdef NETPLAY flushPacketQueues (); check_for_disconnections (pMS); #endif return (TRUE); } static void InitPreBuilt (PMELEE_STATE pMS) { { FleetShipIndex shipI = 0; int fleetI; for (fleetI = 0; fleetI < NUM_PREBUILT; fleetI++) for (shipI = 0; shipI < MELEE_FLEET_SIZE; shipI++) pMS->PreBuiltList[fleetI].ShipList[shipI] = MELEE_NONE; } { /* "Balanced Team 1" */ FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[0].TeamName, sizeof (pMS->PreBuiltList[0].TeamName), GAME_STRING (MELEE_STRING_BASE + 4)); pMS->PreBuiltList[0].ShipList[i++] = MELEE_ANDROSYNTH; pMS->PreBuiltList[0].ShipList[i++] = MELEE_CHMMR; pMS->PreBuiltList[0].ShipList[i++] = MELEE_DRUUGE; pMS->PreBuiltList[0].ShipList[i++] = MELEE_URQUAN; pMS->PreBuiltList[0].ShipList[i++] = MELEE_MELNORME; pMS->PreBuiltList[0].ShipList[i++] = MELEE_ORZ; pMS->PreBuiltList[0].ShipList[i++] = MELEE_SPATHI; pMS->PreBuiltList[0].ShipList[i++] = MELEE_SYREEN; pMS->PreBuiltList[0].ShipList[i++] = MELEE_UTWIG; } { /* "Balanced Team 2" */ FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[1].TeamName, sizeof (pMS->PreBuiltList[1].TeamName), GAME_STRING (MELEE_STRING_BASE + 5)); pMS->PreBuiltList[1].ShipList[i++] = MELEE_ARILOU; pMS->PreBuiltList[1].ShipList[i++] = MELEE_CHENJESU; pMS->PreBuiltList[1].ShipList[i++] = MELEE_EARTHLING; pMS->PreBuiltList[1].ShipList[i++] = MELEE_KOHR_AH; pMS->PreBuiltList[1].ShipList[i++] = MELEE_MYCON; pMS->PreBuiltList[1].ShipList[i++] = MELEE_YEHAT; pMS->PreBuiltList[1].ShipList[i++] = MELEE_PKUNK; pMS->PreBuiltList[1].ShipList[i++] = MELEE_SUPOX; pMS->PreBuiltList[1].ShipList[i++] = MELEE_THRADDASH; pMS->PreBuiltList[1].ShipList[i++] = MELEE_ZOQFOTPIK; pMS->PreBuiltList[1].ShipList[i++] = MELEE_SHOFIXTI; } { /* "200 points" */ FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[2].TeamName, sizeof (pMS->PreBuiltList[2].TeamName), GAME_STRING (MELEE_STRING_BASE + 6)); pMS->PreBuiltList[2].ShipList[i++] = MELEE_ANDROSYNTH; pMS->PreBuiltList[2].ShipList[i++] = MELEE_CHMMR; pMS->PreBuiltList[2].ShipList[i++] = MELEE_DRUUGE; pMS->PreBuiltList[2].ShipList[i++] = MELEE_MELNORME; pMS->PreBuiltList[2].ShipList[i++] = MELEE_EARTHLING; pMS->PreBuiltList[2].ShipList[i++] = MELEE_KOHR_AH; pMS->PreBuiltList[2].ShipList[i++] = MELEE_SUPOX; pMS->PreBuiltList[2].ShipList[i++] = MELEE_ORZ; pMS->PreBuiltList[2].ShipList[i++] = MELEE_SPATHI; pMS->PreBuiltList[2].ShipList[i++] = MELEE_ILWRATH; pMS->PreBuiltList[2].ShipList[i++] = MELEE_VUX; } { /* "Behemoth Zenith" */ FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[3].TeamName, sizeof (pMS->PreBuiltList[3].TeamName), GAME_STRING (MELEE_STRING_BASE + 7)); pMS->PreBuiltList[3].ShipList[i++] = MELEE_CHENJESU; pMS->PreBuiltList[3].ShipList[i++] = MELEE_CHENJESU; pMS->PreBuiltList[3].ShipList[i++] = MELEE_CHMMR; pMS->PreBuiltList[3].ShipList[i++] = MELEE_CHMMR; pMS->PreBuiltList[3].ShipList[i++] = MELEE_KOHR_AH; pMS->PreBuiltList[3].ShipList[i++] = MELEE_KOHR_AH; pMS->PreBuiltList[3].ShipList[i++] = MELEE_URQUAN; pMS->PreBuiltList[3].ShipList[i++] = MELEE_URQUAN; pMS->PreBuiltList[3].ShipList[i++] = MELEE_UTWIG; pMS->PreBuiltList[3].ShipList[i++] = MELEE_UTWIG; } { /* "The Peeled Eyes" */ FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[4].TeamName, sizeof (pMS->PreBuiltList[4].TeamName), GAME_STRING (MELEE_STRING_BASE + 8)); pMS->PreBuiltList[4].ShipList[i++] = MELEE_URQUAN; pMS->PreBuiltList[4].ShipList[i++] = MELEE_CHENJESU; pMS->PreBuiltList[4].ShipList[i++] = MELEE_MYCON; pMS->PreBuiltList[4].ShipList[i++] = MELEE_SYREEN; pMS->PreBuiltList[4].ShipList[i++] = MELEE_ZOQFOTPIK; pMS->PreBuiltList[4].ShipList[i++] = MELEE_SHOFIXTI; pMS->PreBuiltList[4].ShipList[i++] = MELEE_EARTHLING; pMS->PreBuiltList[4].ShipList[i++] = MELEE_KOHR_AH; pMS->PreBuiltList[4].ShipList[i++] = MELEE_MELNORME; pMS->PreBuiltList[4].ShipList[i++] = MELEE_DRUUGE; pMS->PreBuiltList[4].ShipList[i++] = MELEE_PKUNK; pMS->PreBuiltList[4].ShipList[i++] = MELEE_ORZ; } { FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[5].TeamName, sizeof (pMS->PreBuiltList[5].TeamName), "Ford's Fighters"); pMS->PreBuiltList[5].ShipList[i++] = MELEE_CHMMR; pMS->PreBuiltList[5].ShipList[i++] = MELEE_ZOQFOTPIK; pMS->PreBuiltList[5].ShipList[i++] = MELEE_MELNORME; pMS->PreBuiltList[5].ShipList[i++] = MELEE_SUPOX; pMS->PreBuiltList[5].ShipList[i++] = MELEE_UTWIG; pMS->PreBuiltList[5].ShipList[i++] = MELEE_UMGAH; } { FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[6].TeamName, sizeof (pMS->PreBuiltList[6].TeamName), "Leyland's Lashers"); pMS->PreBuiltList[6].ShipList[i++] = MELEE_ANDROSYNTH; pMS->PreBuiltList[6].ShipList[i++] = MELEE_EARTHLING; pMS->PreBuiltList[6].ShipList[i++] = MELEE_MYCON; pMS->PreBuiltList[6].ShipList[i++] = MELEE_ORZ; pMS->PreBuiltList[6].ShipList[i++] = MELEE_URQUAN; } { FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[7].TeamName, sizeof (pMS->PreBuiltList[7].TeamName), "The Gregorizers 200"); pMS->PreBuiltList[7].ShipList[i++] = MELEE_ANDROSYNTH; pMS->PreBuiltList[7].ShipList[i++] = MELEE_CHMMR; pMS->PreBuiltList[7].ShipList[i++] = MELEE_DRUUGE; pMS->PreBuiltList[7].ShipList[i++] = MELEE_MELNORME; pMS->PreBuiltList[7].ShipList[i++] = MELEE_EARTHLING; pMS->PreBuiltList[7].ShipList[i++] = MELEE_KOHR_AH; pMS->PreBuiltList[7].ShipList[i++] = MELEE_SUPOX; pMS->PreBuiltList[7].ShipList[i++] = MELEE_ORZ; pMS->PreBuiltList[7].ShipList[i++] = MELEE_PKUNK; pMS->PreBuiltList[7].ShipList[i++] = MELEE_SPATHI; } { FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[8].TeamName, sizeof (pMS->PreBuiltList[8].TeamName), "300 point Armada!"); pMS->PreBuiltList[8].ShipList[i++] = MELEE_ANDROSYNTH; pMS->PreBuiltList[8].ShipList[i++] = MELEE_CHMMR; pMS->PreBuiltList[8].ShipList[i++] = MELEE_CHENJESU; pMS->PreBuiltList[8].ShipList[i++] = MELEE_DRUUGE; pMS->PreBuiltList[8].ShipList[i++] = MELEE_EARTHLING; pMS->PreBuiltList[8].ShipList[i++] = MELEE_KOHR_AH; pMS->PreBuiltList[8].ShipList[i++] = MELEE_MELNORME; pMS->PreBuiltList[8].ShipList[i++] = MELEE_MYCON; pMS->PreBuiltList[8].ShipList[i++] = MELEE_ORZ; pMS->PreBuiltList[8].ShipList[i++] = MELEE_PKUNK; pMS->PreBuiltList[8].ShipList[i++] = MELEE_SPATHI; pMS->PreBuiltList[8].ShipList[i++] = MELEE_SUPOX; pMS->PreBuiltList[8].ShipList[i++] = MELEE_URQUAN; pMS->PreBuiltList[8].ShipList[i++] = MELEE_YEHAT; } { FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[9].TeamName, sizeof (pMS->PreBuiltList[9].TeamName), "Little Dudes with Attitudes"); pMS->PreBuiltList[9].ShipList[i++] = MELEE_UMGAH; pMS->PreBuiltList[9].ShipList[i++] = MELEE_THRADDASH; pMS->PreBuiltList[9].ShipList[i++] = MELEE_SHOFIXTI; pMS->PreBuiltList[9].ShipList[i++] = MELEE_EARTHLING; pMS->PreBuiltList[9].ShipList[i++] = MELEE_VUX; pMS->PreBuiltList[9].ShipList[i++] = MELEE_ZOQFOTPIK; } { FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[10].TeamName, sizeof (pMS->PreBuiltList[10].TeamName), "New Alliance Ships"); pMS->PreBuiltList[10].ShipList[i++] = MELEE_ARILOU; pMS->PreBuiltList[10].ShipList[i++] = MELEE_CHMMR; pMS->PreBuiltList[10].ShipList[i++] = MELEE_EARTHLING; pMS->PreBuiltList[10].ShipList[i++] = MELEE_ORZ; pMS->PreBuiltList[10].ShipList[i++] = MELEE_PKUNK; pMS->PreBuiltList[10].ShipList[i++] = MELEE_SHOFIXTI; pMS->PreBuiltList[10].ShipList[i++] = MELEE_SUPOX; pMS->PreBuiltList[10].ShipList[i++] = MELEE_SYREEN; pMS->PreBuiltList[10].ShipList[i++] = MELEE_UTWIG; pMS->PreBuiltList[10].ShipList[i++] = MELEE_ZOQFOTPIK; pMS->PreBuiltList[10].ShipList[i++] = MELEE_YEHAT; pMS->PreBuiltList[10].ShipList[i++] = MELEE_DRUUGE; pMS->PreBuiltList[10].ShipList[i++] = MELEE_THRADDASH; pMS->PreBuiltList[10].ShipList[i++] = MELEE_SPATHI; } { FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[11].TeamName, sizeof (pMS->PreBuiltList[11].TeamName), "Old Alliance Ships"); pMS->PreBuiltList[11].ShipList[i++] = MELEE_ARILOU; pMS->PreBuiltList[11].ShipList[i++] = MELEE_CHENJESU; pMS->PreBuiltList[11].ShipList[i++] = MELEE_EARTHLING; pMS->PreBuiltList[11].ShipList[i++] = MELEE_MMRNMHRM; pMS->PreBuiltList[11].ShipList[i++] = MELEE_SHOFIXTI; pMS->PreBuiltList[11].ShipList[i++] = MELEE_SYREEN; pMS->PreBuiltList[11].ShipList[i++] = MELEE_YEHAT; } { FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[12].TeamName, sizeof (pMS->PreBuiltList[12].TeamName), "Old Hierarchy Ships"); pMS->PreBuiltList[12].ShipList[i++] = MELEE_ANDROSYNTH; pMS->PreBuiltList[12].ShipList[i++] = MELEE_ILWRATH; pMS->PreBuiltList[12].ShipList[i++] = MELEE_MYCON; pMS->PreBuiltList[12].ShipList[i++] = MELEE_SPATHI; pMS->PreBuiltList[12].ShipList[i++] = MELEE_UMGAH; pMS->PreBuiltList[12].ShipList[i++] = MELEE_URQUAN; pMS->PreBuiltList[12].ShipList[i++] = MELEE_VUX; } { FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[13].TeamName, sizeof (pMS->PreBuiltList[13].TeamName), "Star Control 1"); pMS->PreBuiltList[13].ShipList[i++] = MELEE_ANDROSYNTH; pMS->PreBuiltList[13].ShipList[i++] = MELEE_ARILOU; pMS->PreBuiltList[13].ShipList[i++] = MELEE_CHENJESU; pMS->PreBuiltList[13].ShipList[i++] = MELEE_EARTHLING; pMS->PreBuiltList[13].ShipList[i++] = MELEE_ILWRATH; pMS->PreBuiltList[13].ShipList[i++] = MELEE_MMRNMHRM; pMS->PreBuiltList[13].ShipList[i++] = MELEE_MYCON; pMS->PreBuiltList[13].ShipList[i++] = MELEE_SHOFIXTI; pMS->PreBuiltList[13].ShipList[i++] = MELEE_SPATHI; pMS->PreBuiltList[13].ShipList[i++] = MELEE_SYREEN; pMS->PreBuiltList[13].ShipList[i++] = MELEE_UMGAH; pMS->PreBuiltList[13].ShipList[i++] = MELEE_URQUAN; pMS->PreBuiltList[13].ShipList[i++] = MELEE_VUX; pMS->PreBuiltList[13].ShipList[i++] = MELEE_YEHAT; } { FleetShipIndex i = 0; utf8StringCopy (pMS->PreBuiltList[14].TeamName, sizeof (pMS->PreBuiltList[14].TeamName), "Star Control 2"); pMS->PreBuiltList[14].ShipList[i++] = MELEE_CHMMR; pMS->PreBuiltList[14].ShipList[i++] = MELEE_DRUUGE; pMS->PreBuiltList[14].ShipList[i++] = MELEE_KOHR_AH; pMS->PreBuiltList[14].ShipList[i++] = MELEE_MELNORME; pMS->PreBuiltList[14].ShipList[i++] = MELEE_ORZ; pMS->PreBuiltList[14].ShipList[i++] = MELEE_PKUNK; pMS->PreBuiltList[14].ShipList[i++] = MELEE_SLYLANDRO; pMS->PreBuiltList[14].ShipList[i++] = MELEE_SUPOX; pMS->PreBuiltList[14].ShipList[i++] = MELEE_THRADDASH; pMS->PreBuiltList[14].ShipList[i++] = MELEE_UTWIG; pMS->PreBuiltList[14].ShipList[i++] = MELEE_ZOQFOTPIK; pMS->PreBuiltList[14].ShipList[i++] = MELEE_ZOQFOTPIK; pMS->PreBuiltList[14].ShipList[i++] = MELEE_ZOQFOTPIK; pMS->PreBuiltList[14].ShipList[i++] = MELEE_ZOQFOTPIK; } } int LoadMeleeConfig (PMELEE_STATE pMS) { uio_Stream *load_fp; int status; load_fp = res_OpenResFile (configDir, "melee.cfg", "rb"); if (!load_fp) goto err; if (LengthResFile (load_fp) != (1 + sizeof (TEAM_IMAGE)) * 2) goto err; status = GetResFileChar (load_fp); if (status == -1) goto err; PlayerControl[0] = (BYTE)status; status = ReadTeamImage (&pMS->TeamImage[0], load_fp); if (status == -1) goto err; status = GetResFileChar (load_fp); if (status == -1) goto err; PlayerControl[1] = (BYTE)status; status = ReadTeamImage (&pMS->TeamImage[1], load_fp); if (status == -1) goto err; res_CloseResFile (load_fp); /* Do not allow netplay mode at the start. */ if (PlayerControl[0] & NETWORK_CONTROL) PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING; if (PlayerControl[1] & NETWORK_CONTROL) PlayerControl[1] = HUMAN_CONTROL | STANDARD_RATING; return 0; err: if (load_fp) res_CloseResFile (load_fp); return -1; } int WriteMeleeConfig (PMELEE_STATE pMS) { uio_Stream *save_fp; save_fp = res_OpenResFile (configDir, "melee.cfg", "wb"); if (!save_fp) goto err; if (PutResFileChar (PlayerControl[0], save_fp) == -1) goto err; if (WriteTeamImage (&pMS->TeamImage[0], save_fp) == 0) goto err; if (PutResFileChar (PlayerControl[1], save_fp) == -1) goto err; if (WriteTeamImage (&pMS->TeamImage[1], save_fp) == 0) goto err; if (!res_CloseResFile (save_fp)) goto err; return 0; err: if (save_fp) { res_CloseResFile (save_fp); DeleteResFile (configDir, "melee.cfg"); } return -1; } void Melee (void) { InitGlobData (); { MELEE_STATE MenuState; pMeleeState = &MenuState; memset (pMeleeState, 0, sizeof (*pMeleeState)); MenuState.InputFunc = DoMelee; MenuState.Initialized = FALSE; #ifdef NETPLAY { COUNT player; for (player = 0; player < NUM_PLAYERS; player++) netConnections[player] = NULL; } #endif MenuState.CurIndex = (COUNT)~0; InitPreBuilt (&MenuState); GLOBAL (CurrentActivity) = SUPER_MELEE; GameSounds = CaptureSound (LoadSound (GAME_SOUNDS)); LoadMeleeInfo (&MenuState); if (LoadMeleeConfig (&MenuState) == -1) { PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING; MenuState.TeamImage[0] = MenuState.PreBuiltList[0]; PlayerControl[1] = COMPUTER_CONTROL | STANDARD_RATING; MenuState.TeamImage[1] = MenuState.PreBuiltList[1]; } SetPlayerInput (); teamStringChanged (&MenuState, 0); teamStringChanged (&MenuState, 1); entireFleetChanged (&MenuState, 0); entireFleetChanged (&MenuState, 1); MenuState.side = 0; MenuState.star_bucks[0] = GetTeamValue (&MenuState.TeamImage[0]); MenuState.star_bucks[1] = GetTeamValue (&MenuState.TeamImage[1]); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); DoInput ((PVOID)&MenuState, TRUE); StopMusic (); WaitForSoundEnd (TFBSOUND_WAIT_ALL); WriteMeleeConfig (&MenuState); FreeMeleeInfo (&MenuState); DestroySound (ReleaseSound (GameSounds)); GameSounds = 0; DestroyDrawable (ReleaseDrawable (PickMeleeFrame)); PickMeleeFrame = 0; FlushInput (); } } // Notify the network connections of a team name change. void teamStringChanged (PMELEE_STATE pMS, int player) { #ifdef NETPLAY const char *name; size_t len; size_t playerI; name = pMS->TeamImage[player].TeamName; len = strlen (name); for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { NetConnection *conn = netConnections[playerI]; if (conn == NULL) continue; if (!NetConnection_isConnected (conn)) continue; if (NetConnection_getState (conn) != NetState_inSetup) continue; Netplay_teamStringChanged (conn, player, name, len); } #else (void) pMS; (void) player; #endif } // Notify the network connections of the configuration of a fleet. void entireFleetChanged (PMELEE_STATE pMS, int player) { #ifdef NETPLAY size_t playerI; for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { NetConnection *conn = netConnections[playerI]; if (conn == NULL) continue; if (!NetConnection_isConnected (conn)) continue; if (NetConnection_getState (conn) != NetState_inSetup) continue; Netplay_entireFleetChanged (conn, player, pMS->TeamImage[player].ShipList, MELEE_FLEET_SIZE); } #else (void) player; #endif (void) pMS; } // Notify the network of a change in the configuration of a fleet. void fleetShipChanged (PMELEE_STATE pMS, int player, size_t index) { #ifdef NETPLAY size_t playerI; for (playerI = 0; playerI < NUM_PLAYERS; playerI++) { NetConnection *conn = netConnections[playerI]; if (conn == NULL) continue; if (!NetConnection_isConnected (conn)) continue; if (NetConnection_getState (conn) != NetState_inSetup) continue; Netplay_fleetShipChanged (conn, player, index, pMS->TeamImage[player].ShipList[index]); } #else (void) player; (void) index; #endif (void) pMS; } #ifdef NETPLAY // NB: 'len' does not include the terminating 0. // 'len' counts in bytes, not in characters. void updateTeamName (PMELEE_STATE pMS, COUNT side, const char *name, size_t len) { // NB: MAX_TEAM_CHARS is the maximum number of characters, // without the terminating '\0'. if (len > MAX_TEAM_CHARS) len = MAX_TEAM_CHARS; // TeamName has space for at least MAX_TEAM_CHARS + 1 bytes. strncpy (pMS->TeamImage[side].TeamName, name, len); pMS->TeamImage[side].TeamName[len] = '\0'; LockMutex (GraphicsLock); #if 0 /* DTSHS_REPAIR does not combine with other options */ if (pMS->MeleeOption == EDIT_MELEE && pMS->side == side && pMS->row == NUM_MELEE_ROWS) DrawTeamString (pMS, side, DTSHS_REPAIR | DTSHS_SELECTED); else #endif DrawTeamString (pMS, side, DTSHS_REPAIR); UnlockMutex (GraphicsLock); } // Update a ship in a fleet as specified by a remote party. bool updateFleetShip (PMELEE_STATE pMS, COUNT side, COUNT index, BYTE ship) { BYTE row = GetShipRow (index); BYTE col = GetShipColumn (index); COUNT val; FleetShipIndex selectedShipIndex; BOOLEAN isSelected; if (ship >= NUM_MELEE_SHIPS && ship != MELEE_NONE) { fprintf (stderr, "Invalid ship type number %d (max = %d).\n", ship, NUM_MELEE_SHIPS - 1); return false; } if (index >= MELEE_FLEET_SIZE) { fprintf (stderr, "Invalid ship position number %d (max = %d).\n", index, MELEE_FLEET_SIZE - 1); return false; } val = GetShipValue (ship); if (val == (COUNT) ~0) return false; pMS->star_bucks[side] -= GetShipValue (pMS->TeamImage[side].ShipList[index]); pMS->star_bucks[side] += val; pMS->TeamImage[side].ShipList[index] = ship; selectedShipIndex = GetShipIndex (pMS->row, pMS->col); isSelected = (pMS->MeleeOption == EDIT_MELEE) && (pMS->side == side) && (index == selectedShipIndex); // Ship to be updated is the currently selected one. LockMutex (GraphicsLock); if (ship == MELEE_NONE) { RECT r; GetShipBox (&r, side, row, col); RepairMeleeFrame (&r); } else DrawShipBox (side, row, col, ship, isSelected); if (isSelected) { pMS->CurIndex = ship; DrawMeleeShipStrings (pMS, ship); } // Reprint the team value: //DrawTeamString (pMeleeState, side, DTSHS_NORMAL); DrawTeamString (pMS, side, DTSHS_REPAIR); UnlockMutex (GraphicsLock); return true; } void updateRandomSeed (PMELEE_STATE pMS, COUNT side, DWORD seed) { TFB_SeedRandom (seed); (void) pMS; (void) side; } // The remote player has done something which invalidates our confirmation. void confirmationCancelled(PMELEE_STATE pMS, COUNT side) { LockMutex (GraphicsLock); if (side == 0) DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 16)); // "Bottom player changed something -- need to reconfirm." else DrawMeleeStatusMessage (GAME_STRING (NETMELEE_STRING_BASE + 17)); // "Top player changed something -- need to reconfirm." UnlockMutex (GraphicsLock); if (pMS->InputFunc == DoConfirmSettings) pMS->InputFunc = DoMelee; } static void connectionFeedback (NetConnection *conn, const char *str, bool forcePopup) { struct battlestate_struct *bs = NetMelee_getBattleState (conn); if (bs == NULL && !forcePopup) { // bs == NULL means the game has not started yet. LockMutex (GraphicsLock); DrawMeleeStatusMessage (str); UnlockMutex (GraphicsLock); } else { DoPopupWindow (str); } } void connectedFeedback (NetConnection *conn) { if (NetConnection_getPlayerNr(conn) == 0) connectionFeedback (conn, GAME_STRING (NETMELEE_STRING_BASE + 8), false); // "Bottom player is connected." else connectionFeedback (conn, GAME_STRING (NETMELEE_STRING_BASE + 9), false); // "Top player is connected." PlayMenuSound (MENU_SOUND_INVOKED); } const char * abortReasonString (NetplayResetReason reason) { switch (reason) { case AbortReason_unspecified: return GAME_STRING (NETMELEE_STRING_BASE + 25); // "Disconnect for an unspecified reason.' case AbortReason_versionMismatch: return GAME_STRING (NETMELEE_STRING_BASE + 26); // "Connection aborted due to version mismatch." case AbortReason_protocolError: return GAME_STRING (NETMELEE_STRING_BASE + 27); // "Connection aborted due to an internal protocol " // "error." } return NULL; // Should not happen. } void abortFeedback (NetConnection *conn, NetplayAbortReason reason) { const char *msg; msg = abortReasonString (reason); if (msg != NULL) connectionFeedback (conn, msg, true); } const char * resetReasonString (NetplayResetReason reason) { switch (reason) { case ResetReason_unspecified: return GAME_STRING (NETMELEE_STRING_BASE + 28); // "Game aborted for an unspecified reason." case ResetReason_syncLoss: return GAME_STRING (NETMELEE_STRING_BASE + 29); // "Game aborted due to loss of synchronisation." case ResetReason_manualReset: return GAME_STRING (NETMELEE_STRING_BASE + 30); // "Game aborted by the remote player." } return NULL; // Should not happen. } void resetFeedback (NetConnection *conn, NetplayResetReason reason, bool byRemote) { const char *msg; GLOBAL (CurrentActivity) |= CHECK_ABORT; flushPacketQueues (); // If the local side queued a reset packet as a result of a // remote reset, that packet will not have been sent yet. // We flush the queue now, so that the remote side won't be // waiting for the reset packet while this side is waiting // for an acknowledgement of the feedback message. if (reason == ResetReason_manualReset && !byRemote) { // No message needed, the player initiated the reset. return; } msg = resetReasonString (reason); if (msg != NULL) connectionFeedback (conn, msg, false); } void errorFeedback (NetConnection *conn) { if (NetConnection_getPlayerNr(conn) == 0) connectionFeedback (conn, GAME_STRING (NETMELEE_STRING_BASE + 10), false); // "Bottom player: connection failed." else connectionFeedback (conn, GAME_STRING (NETMELEE_STRING_BASE + 11), false); // "Top player: connection failed." } void closeFeedback (NetConnection *conn) { if (NetConnection_getPlayerNr(conn) == 0) connectionFeedback (conn, GAME_STRING (NETMELEE_STRING_BASE + 12), false); // "Bottom player: connection closed." else connectionFeedback (conn, GAME_STRING (NETMELEE_STRING_BASE + 13), false); // "Top player: connection closed." } #endif /* NETPLAY */ uqm-0.6.2/sc2/src/sc2code/starbase.c0000600000175000017500000003351610543202102015554 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "colors.h" #include "controls.h" #include "encount.h" #include "gamestr.h" #include "load.h" #include "starbase.h" #include "resinst.h" #include "nameref.h" #include "settings.h" #include "setup.h" #include "sounds.h" #include "libs/graphics/gfx_common.h" #include "libs/tasklib.h" #include "libs/inplib.h" PMENU_STATE pMenuState; static void DrawBaseStateStrings (STARBASE_STATE OldState, STARBASE_STATE NewState) { TEXT t; //STRING locString; SetContext (ScreenContext); SetContextFont (StarConFont); SetContextForeGroundColor (BLACK_COLOR); t.baseline.x = 73 - 4 + SAFE_X; t.align = ALIGN_CENTER; if (OldState == (STARBASE_STATE)~0) { t.baseline.y = 106 + 28 + (SAFE_Y + 4); for (OldState = TALK_COMMANDER; OldState < DEPART_BASE; ++OldState) { if (OldState != NewState) { t.pStr = GAME_STRING (STARBASE_STRING_BASE + 1 + OldState); t.CharCount = (COUNT)~0; font_DrawText (&t); } t.baseline.y += (23 - 4); } } t.baseline.y = 106 + 28 + (SAFE_Y + 4) + ((23 - 4) * OldState); t.pStr = GAME_STRING (STARBASE_STRING_BASE + 1 + OldState); t.CharCount = (COUNT)~0; font_DrawText (&t); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E)); t.baseline.y = 106 + 28 + (SAFE_Y + 4) + ((23 - 4) * NewState); t.pStr = GAME_STRING (STARBASE_STRING_BASE + 1 + NewState); t.CharCount = (COUNT)~0; font_DrawText (&t); } void DrawShipPiece (PMENU_STATE pMS, COUNT which_piece, COUNT which_slot, BOOLEAN DrawBluePrint) { COLOR OldColor = 0; // Initialisation is to keep the compiler silent. RECT r; STAMP Side, Top; SBYTE RepairSlot; RepairSlot = 0; switch (which_piece) { case FUSION_THRUSTER: case EMPTY_SLOT + 0: Side.origin.x = DRIVE_SIDE_X; Side.origin.y = DRIVE_SIDE_Y; Top.origin.x = DRIVE_TOP_X; Top.origin.y = DRIVE_TOP_Y; break; case TURNING_JETS: case EMPTY_SLOT + 1: Side.origin.x = JET_SIDE_X; Side.origin.y = JET_SIDE_Y; Top.origin.x = JET_TOP_X; Top.origin.y = JET_TOP_Y; break; default: if (which_piece < EMPTY_SLOT + 2) { RepairSlot = 1; if (which_piece < EMPTY_SLOT && (which_slot == 0 || GLOBAL_SIS (ModuleSlots[ which_slot - 1 ]) < EMPTY_SLOT)) ++RepairSlot; } else if (!DrawBluePrint) { if (which_slot == 0 || which_slot >= NUM_MODULE_SLOTS - 3) ++which_piece; if (which_slot < NUM_MODULE_SLOTS - 1 && GLOBAL_SIS (ModuleSlots[ which_slot + 1 ]) < EMPTY_SLOT) { RepairSlot = -1; if (which_piece == EMPTY_SLOT + 3 || which_slot + 1 == NUM_MODULE_SLOTS - 3) --RepairSlot; } } Side.origin.x = MODULE_SIDE_X; Side.origin.y = MODULE_SIDE_Y; Top.origin.x = MODULE_TOP_X; Top.origin.y = MODULE_TOP_Y; break; } Side.origin.x += which_slot * SHIP_PIECE_OFFSET; if (RepairSlot < 0) { Side.frame = SetAbsFrameIndex (pMS->ModuleFrame, ((NUM_MODULES - 1) + (6 - 2)) + (NUM_MODULES + 6) - (RepairSlot + 1)); DrawStamp (&Side); } else if (RepairSlot) { r.corner = Side.origin; r.extent.width = SHIP_PIECE_OFFSET; r.extent.height = 1; OldColor = SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); r.corner.y += 23 - 1; DrawFilledRectangle (&r); r.extent.width = 1; r.extent.height = 8; if (RepairSlot == 2) { r.corner = Side.origin; DrawFilledRectangle (&r); r.corner.y += 15; DrawFilledRectangle (&r); } if (which_slot < (NUM_MODULE_SLOTS - 1)) { r.corner = Side.origin; r.corner.x += SHIP_PIECE_OFFSET; DrawFilledRectangle (&r); r.corner.y += 15; DrawFilledRectangle (&r); } } if (DrawBluePrint) { if (RepairSlot) SetContextForeGroundColor (OldColor); Side.frame = SetAbsFrameIndex (pMS->ModuleFrame, which_piece - 1); DrawFilledStamp (&Side); } else { Top.origin.x += which_slot * SHIP_PIECE_OFFSET; if (RepairSlot < 0) { Top.frame = SetRelFrameIndex (Side.frame, -((NUM_MODULES - 1) + 6)); DrawStamp (&Top); } else if (RepairSlot) { r.corner = Top.origin; r.extent.width = SHIP_PIECE_OFFSET; r.extent.height = 1; DrawFilledRectangle (&r); r.corner.y += 32 - 1; DrawFilledRectangle (&r); r.extent.width = 1; r.extent.height = 12; if (RepairSlot == 2) { r.corner = Top.origin; DrawFilledRectangle (&r); r.corner.y += 20; DrawFilledRectangle (&r); } RepairSlot = (which_slot < NUM_MODULE_SLOTS - 1); if (RepairSlot) { r.corner = Top.origin; r.corner.x += SHIP_PIECE_OFFSET; DrawFilledRectangle (&r); r.corner.y += 20; DrawFilledRectangle (&r); } } Top.frame = SetAbsFrameIndex (pMS->ModuleFrame, which_piece); DrawStamp (&Top); Side.frame = SetRelFrameIndex (Top.frame, (NUM_MODULES - 1) + 6); DrawStamp (&Side); if (which_slot == 1 && which_piece == EMPTY_SLOT + 2) { STAMP s; s.origin = Top.origin; s.origin.x -= SHIP_PIECE_OFFSET; s.frame = SetAbsFrameIndex (pMS->ModuleFrame, NUM_MODULES + 5); DrawStamp (&s); s.origin = Side.origin; s.origin.x -= SHIP_PIECE_OFFSET; s.frame = SetRelFrameIndex (s.frame, (NUM_MODULES - 1) + 6); DrawStamp (&s); } if (RepairSlot) { Top.origin.x += SHIP_PIECE_OFFSET; Side.origin.x += SHIP_PIECE_OFFSET; which_piece = GLOBAL_SIS (ModuleSlots[++which_slot]); if (which_piece == EMPTY_SLOT + 2 && which_slot >= NUM_MODULE_SLOTS - 3) ++which_piece; Top.frame = SetAbsFrameIndex (pMS->ModuleFrame, which_piece); DrawStamp (&Top); Side.frame = SetRelFrameIndex (Top.frame, (NUM_MODULES - 1) + 6); DrawStamp (&Side); } } } static int rotate_starbase(void *data) { DWORD TimeIn; STAMP s; Task task = (Task) data; //s.origin.x = s.origin.y = 0; s.origin.x = SAFE_X; s.origin.y = SAFE_Y + 4; s.frame = IncFrameIndex (pMenuState->CurFrame); TimeIn = GetTimeCounter (); while (!Task_ReadState (task, TASK_EXIT)) { //CONTEXT OldContext; LockMutex (GraphicsLock); DrawStamp (&s); s.frame = IncFrameIndex (s.frame); if (s.frame == pMenuState->CurFrame) s.frame = IncFrameIndex (s.frame); UnlockMutex (GraphicsLock); SleepThreadUntil (TimeIn + (ONE_SECOND / 20)); TimeIn = GetTimeCounter (); } FinishTask (task); return(0); } BOOLEAN DoStarBase (PMENU_STATE pMS) { if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) { pMS->CurState = DEPART_BASE; goto ExitStarBase; } SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); if (!pMS->Initialized) { STAMP s; LastActivity &= ~CHECK_LOAD; pMS->InputFunc = DoStarBase; LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); if (pMS->hMusic) { StopMusic (); DestroyMusic (pMS->hMusic); pMS->hMusic = 0; } if (pMS->flash_task) { Task_SetState (pMS->flash_task, TASK_EXIT); pMS->flash_task = 0; } pMS->Initialized = TRUE; SetContext (ScreenContext); UnlockMutex (GraphicsLock); //s.origin.x = s.origin.y = 0; s.origin.x = SAFE_X; s.origin.y = SAFE_Y + 4; s.frame = CaptureDrawable (LoadGraphic (STARBASE_ANIM)); pMS->CurFrame = s.frame; pMS->hMusic = LoadMusic (STARBASE_MUSIC); LockMutex (GraphicsLock); SetTransitionSource (NULL); BatchGraphics (); SetContextBackGroundColor (BLACK_COLOR); ClearDrawable (); DrawStamp (&s); DrawBaseStateStrings ((STARBASE_STATE)~0, pMS->CurState); { RECT r; r.corner.x = 0; r.corner.y = 0; r.extent.width = SCREEN_WIDTH; r.extent.height = SCREEN_HEIGHT; ScreenTransition (3, &r); } PlayMusic (pMS->hMusic, TRUE, 1); UnbatchGraphics (); pMS->flash_task = AssignTask (rotate_starbase, 4096, "rotate starbase"); UnlockMutex (GraphicsLock); } else if (PulsedInputState.menu[KEY_MENU_SELECT] || GET_GAME_STATE (MOONBASE_ON_SHIP) || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) { ExitStarBase: if (pMS->flash_task) { ConcludeTask (pMS->flash_task); pMS->flash_task = 0; } DestroyDrawable (ReleaseDrawable (pMS->CurFrame)); pMS->CurFrame = 0; StopMusic (); if (pMS->hMusic) { DestroyMusic (pMS->hMusic); pMS->hMusic = 0; } if (pMS->CurState == DEPART_BASE) { if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { SET_GAME_STATE (STARBASE_VISITED, 0); } return (FALSE); } pMS->Initialized = FALSE; if (pMS->CurState == TALK_COMMANDER) { FlushInput (); InitCommunication (COMMANDER_CONVERSATION); SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, (BYTE)~0); } else { BYTE OldState; switch (OldState = pMS->CurState) { case OUTFIT_STARSHIP: pMS->InputFunc = DoOutfit; break; case SHIPYARD: pMS->InputFunc = DoShipyard; break; } SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); DoInput ((PVOID)pMS, TRUE); pMS->Initialized = FALSE; pMS->CurState = OldState; pMS->InputFunc = DoStarBase; } } else { STARBASE_STATE NewState; NewState = pMS->CurState; if (PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_UP]) { if (NewState-- == TALK_COMMANDER) NewState = DEPART_BASE; } else if (PulsedInputState.menu[KEY_MENU_RIGHT] || PulsedInputState.menu[KEY_MENU_DOWN]) { if (NewState++ == DEPART_BASE) NewState = TALK_COMMANDER; } if (NewState != pMS->CurState) { LockMutex (GraphicsLock); DrawBaseStateStrings (pMS->CurState, NewState); UnlockMutex (GraphicsLock); pMS->CurState = NewState; } } return (TRUE); } static void DoTimePassage (void) { #define LOST_DAYS 14 COUNT i; BYTE clut_buf[1]; clut_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND * 2)); for (i = 0; i < LOST_DAYS; ++i) { while (ClockTick () > 0) ; ResumeGameClock (); SleepThread (ONE_SECOND / 60); SuspendGameClock (); } } void VisitStarBase (void) { MENU_STATE MenuState; CONTEXT OldContext; if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) { CurStarDescPtr = 0; goto TimePassage; } else if (!GET_GAME_STATE (STARBASE_AVAILABLE)) { HSTARSHIP hStarShip; SHIP_FRAGMENTPTR FragPtr; pMenuState = 0; InitCommunication (COMMANDER_CONVERSATION); if (!GET_GAME_STATE (PROBE_ILWRATH_ENCOUNTER) || (GLOBAL (CurrentActivity) & CHECK_ABORT)) goto ExitStarBase; hStarShip = CloneShipFragment ( ILWRATH_SHIP, &GLOBAL (npc_built_ship_q), 7 ); FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); SET_RACE_ID (FragPtr, (BYTE)~0); UnlockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); InitCommunication (ILWRATH_CONVERSATION); if (GLOBAL_SIS (CrewEnlisted) == (COUNT)~0 || (GLOBAL (CurrentActivity) & CHECK_ABORT)) return; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, (BYTE)~0); { pMenuState = &MenuState; InitCommunication (COMMANDER_CONVERSATION); TimePassage: SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, (BYTE)~0); DoTimePassage (); if (GLOBAL_SIS (CrewEnlisted) == (COUNT)~0) return; // You are now dead! Thank you! } } pMenuState = &MenuState; memset ((PMENU_STATE)&MenuState, 0, sizeof (MenuState)); MenuState.InputFunc = DoStarBase; if (GET_GAME_STATE (MOONBASE_ON_SHIP) || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) { MenuState.Initialized = TRUE; MenuState.CurState = TALK_COMMANDER; } OldContext = SetContext (ScreenContext); DoInput ((PVOID)pMenuState, TRUE); SetContext (OldContext); pMenuState = 0; ExitStarBase: if (!(GLOBAL (CurrentActivity) & (CHECK_LOAD | CHECK_ABORT))) { SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 0); GLOBAL (CurrentActivity) = CHECK_LOAD; NextActivity = MAKE_WORD (IN_INTERPLANETARY, 0) | START_INTERPLANETARY; } } void InstallBombAtEarth (void) { BYTE clut_buf[1]; DoTimePassage (); LockMutex (GraphicsLock); SetContext (ScreenContext); SetTransitionSource (NULL); SetContextBackGroundColor (BLACK_COLOR); ClearDrawable (); UnlockMutex (GraphicsLock); clut_buf[0] = FadeAllToColor; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)clut_buf, 0)); SET_GAME_STATE (CHMMR_BOMB_STATE, 3); /* bomb processed */ GLOBAL (CurrentActivity) = CHECK_LOAD; /* fake a load game */ NextActivity = MAKE_WORD (IN_INTERPLANETARY, 0) | START_INTERPLANETARY; CurStarDescPtr = 0; /* force SolarSys reload */ } // XXX: Doesn't really belong in this file. COUNT WrapText (const UNICODE *pStr, COUNT len, TEXT *tarray, SIZE field_width) { COUNT num_lines; num_lines = 0; do { RECT r; COUNT OldCount; tarray->align = ALIGN_LEFT; /* set alignment to something */ tarray->pStr = pStr; tarray->CharCount = 1; ++num_lines; do { OldCount = tarray->CharCount; while (*++pStr != ' ' && (COUNT)(pStr - tarray->pStr) < len) ; tarray->CharCount = pStr - tarray->pStr; TextRect (tarray, &r, NULL_PTR); } while (tarray->CharCount < len && r.extent.width < field_width); if (r.extent.width >= field_width) { if ((tarray->CharCount = OldCount) == 1) { do { ++tarray->CharCount; TextRect (tarray, &r, NULL_PTR); } while (r.extent.width < field_width); --tarray->CharCount; } } pStr = tarray->pStr + tarray->CharCount; len -= tarray->CharCount; ++tarray; if (len && (r.extent.width < field_width || OldCount > 1)) { ++pStr; /* skip white space */ --len; } } while (len); return (num_lines); } uqm-0.6.2/sc2/src/sc2code/uqmdebug.h0000600000175000017500000001372710543202101015567 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if !defined(_DEBUG_H) && (defined(DEBUG) || defined(USE_DEBUG_KEY)) #define _DEBUG_H #include "clock.h" #include "planets/planets.h" #include "races.h" #include "libs/compiler.h" #include // If set to true, interactive routines that are called (indirectly) in debug // functions are a no-op. extern BOOLEAN disableInteractivity; // If a function is assigned to this, it will be called from the main loop. extern void (* volatile debugHook) (void); // Called when the debug key (symbol 'Debug' in the keys.cfg) is pressed. void debugKeyPressed (void); // Forward time to the next event. If skipHEE is set, the event named // HYPERSPACE_ENCOUNTER_EVENT, which normally occurs every game day, // is skipped. void forwardToNextEvent (BOOLEAN skipHEE); // Generate a list of all events in the event queue. void dumpEvents (FILE *out); // Describe one event. void dumpEvent (FILE *out, EVENTPTR eventPtr); // Get the name of one event. const char *eventName (BYTE func_index); // Give the flagship a decent equipment for debugging. void equipShip (void); // Show all active spheres of influence. void showSpheres (void); // Make the ships of all races available for building at the shipyard. void activateAllShips (void); // Move the Flagship to the destination of the autopilot. // Should only be called from HS/QS. // It can be called from debugHook directly after entering HS/QS though. void doInstantMove (void); // Call a function for all stars. void forAllStars (void (*callback) (STAR_DESC *, void *), void *arg); // Call a function for all planets in a star system. void forAllPlanets (STAR_DESC *star, SOLARSYS_STATE *system, void (*callback) (STAR_DESC *, SOLARSYS_STATE *, PLANET_DESC *, void *), void *arg); // Call a function for all moons of a planet. void forAllMoons (STAR_DESC *star, SOLARSYS_STATE *system, PLANET_DESC *planet, void (*callback) (STAR_DESC *, SOLARSYS_STATE *, PLANET_DESC *, PLANET_DESC *, void *), void *arg); // Argument to UniverseRecurse() typedef struct { void (*systemFunc) (const STAR_DESC *star, const SOLARSYS_STATE *system, void *arg); void (*planetFunc) (const PLANET_DESC *planet, void *arg); void (*moonFunc) (const PLANET_DESC *moon, void *arg); void *arg; } UniverseRecurseArg; // Recurse through all systems, planets, and moons in the universe. void UniverseRecurse (UniverseRecurseArg *universeRecurseArg); // Describe the entire universe. void dumpUniverse (FILE *out); // Describe the entire universe, output to a file "./PlanetInfo". void dumpUniverseToFile (void); // Describe one star system. void dumpSystem (FILE *out, const STAR_DESC *star, const SOLARSYS_STATE *system); // Get a star color as a string. const char *bodyColorString (BYTE col); // Get a star type as a string. const char *starTypeString (BYTE type); // Get a string describing special presence in the star system. const char *starPresenceString (BYTE index); // Get a list describing all planets in a star. void dumpPlanets (FILE *out, const STAR_DESC *star); // Describe one planet. void dumpPlanet(FILE *out, const PLANET_DESC *planet); // Describe one moon. void dumpMoon (FILE *out, const PLANET_DESC *moon); // Calculate the total value of all minerals on a world. COUNT calculateMineralValue (const SOLARSYS_STATE *system, const PLANET_DESC *world); // Determine how much of each mineral type is present on a world void generateMineralIndex(const SOLARSYS_STATE *system, const PLANET_DESC *world, COUNT minerals[]); // Calculate the total value of all bio on a world. COUNT calculateBioValue (const SOLARSYS_STATE *system, const PLANET_DESC *world); // Determine how much of each mineral type is present on a world void generateBioIndex(const SOLARSYS_STATE *system, const PLANET_DESC *world, COUNT bio[]); // Call a function for all planet types. void forAllPlanetTypes (void (*callBack) (int, const PlanetFrame *, void *), void *arg); // Describe one planet type. void dumpPlanetType(FILE *out, int index, const PlanetFrame *planetFrame); // Generate a list of all planet types. void dumpPlanetTypes(FILE *out); // Get a string describing a planet type. const char *planetTypeString (int typeIndex); // Get a string describing the size of a type of planet. const char *worldSizeString (BYTE size); // Get a string describing a planet type map generation algoritm. const char *worldGenAlgoString (BYTE algo); // Get a string describing the severity of a tectonics on a type of planet. const char *tectonicsString (BYTE tectonics); // Get a string describing the atmospheric pressure on a type of planet. const char *atmosphereString (BYTE atmosphere); // Get a string describing the density of a type of planet. const char *densityString (BYTE density); // Get a string describing the quality of a deposit. const char *depositQualityString (BYTE quality); // Find a player ship. Setting which to BAD_GUY is only meaningful in battle. STARSHIPPTR findPlayerShip(ELEMENT_FLAGS which); // Resets the crew of the first player (the bottom one) to its maximum. void resetCrewBattle(void); // Resets the energy of the first player (the bottom one) to its maximum. void resetEnergyBattle(void); // Move instantly across hyperspace/quasispace. extern BOOLEAN instantMove; // To add some day: // - a function to fast forward the game clock to a specifiable time. #endif /* _DEBUG_H */ uqm-0.6.2/sc2/src/sc2code/getchar.c0000600000175000017500000002225610543202101015363 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "port.h" #include "controls.h" #include "libs/inplib.h" #include "libs/misc.h" #include "libs/log.h" #include "globdata.h" #include "sounds.h" #include "settings.h" #include "resinst.h" #include "nameref.h" struct joy_char { unsigned char len; unsigned char enc[7]; // 1+7 is a nice round number }; static int ReadOneChar (joy_char_t *ch, const UNICODE *str) { UNICODE *next = skipUTF8Chars (str, 1); int len = next - str; ch->len = len; memcpy (ch->enc, str, len); ch->enc[len] = '\0'; // string term return len; } static joy_char_t * LoadJoystickAlpha (STRING String, int *count) { UNICODE *str; int c; int i; joy_char_t *chars; UNICODE *cur; *count = 0; str = GetStringAddress (String); if (!str) return 0; c = utf8StringCount (str); chars = HMalloc (c * sizeof (*chars)); if (!chars) return 0; for (i = 0, cur = str; i < c; ++i) { int len = ReadOneChar (chars + i, cur); cur += len; } *count = c; return chars; } static int JoyCharFindIn (const joy_char_t *ch, const joy_char_t *set, int setsize) { int i; for (i = 0; i < setsize && strcmp (set[i].enc, ch->enc) != 0; ++i) ; return (i < setsize) ? i : -1; } static int JoyCharIsLower (const joy_char_t *ch, PTEXTENTRY_STATE pTES) { return 0 <= JoyCharFindIn (ch, pTES->JoyLower, pTES->JoyRegLength); } static void JoyCharSwitchReg (joy_char_t *ch, const joy_char_t *from, const joy_char_t *to, int regsize) { int i = JoyCharFindIn (ch, from, regsize); if (i >= 0) *ch = to[i]; } static void JoyCharToUpper (joy_char_t *outch, const joy_char_t *ch, PTEXTENTRY_STATE pTES) { *outch = *ch; JoyCharSwitchReg (outch, pTES->JoyLower, pTES->JoyUpper, pTES->JoyRegLength); } static void JoyCharToLower (joy_char_t *outch, const joy_char_t *ch, PTEXTENTRY_STATE pTES) { *outch = *ch; JoyCharSwitchReg (outch, pTES->JoyUpper, pTES->JoyLower, pTES->JoyRegLength); } BOOLEAN DoTextEntry (PTEXTENTRY_STATE pTES) { wchar_t ch; UNICODE *pStr; UNICODE *CacheInsPt; int CacheCursorPos; int len; BOOLEAN changed = FALSE; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); if (!pTES->Initialized) { // init basic vars int lwlen; pTES->InputFunc = DoTextEntry; pTES->Success = FALSE; pTES->Initialized = TRUE; pTES->JoystickMode = FALSE; pTES->UpperRegister = TRUE; // init insertion point if ((size_t)pTES->CursorPos > utf8StringCount (pTES->BaseStr)) pTES->CursorPos = utf8StringCount (pTES->BaseStr); pTES->InsPt = skipUTF8Chars (pTES->BaseStr, pTES->CursorPos); // load joystick alphabet pTES->JoyAlphaString = CaptureStringTable ( LoadStringTable (JOYSTICK_ALPHA_STRTAB)); pTES->JoyAlpha = LoadJoystickAlpha ( SetAbsStringTableIndex (pTES->JoyAlphaString, 0), &pTES->JoyAlphaLength); pTES->JoyUpper = LoadJoystickAlpha ( SetAbsStringTableIndex (pTES->JoyAlphaString, 1), &pTES->JoyRegLength); pTES->JoyLower = LoadJoystickAlpha ( SetAbsStringTableIndex (pTES->JoyAlphaString, 2), &lwlen); if (lwlen != pTES->JoyRegLength) { if (lwlen < pTES->JoyRegLength) pTES->JoyRegLength = lwlen; log_add (log_Warning, "Warning: Joystick upper-lower registers" " size mismatch; using the smallest subset (%d)", pTES->JoyRegLength); } pTES->CacheStr = HMalloc (pTES->MaxSize * sizeof (*pTES->CacheStr)); DoInput (pTES, TRUE); if (pTES->CacheStr) HFree (pTES->CacheStr); if (pTES->JoyLower) HFree (pTES->JoyLower); if (pTES->JoyUpper) HFree (pTES->JoyUpper); if (pTES->JoyAlpha) HFree (pTES->JoyAlpha); DestroyStringTable ( ReleaseStringTable (pTES->JoyAlphaString)); return pTES->Success; } pStr = pTES->InsPt; len = strlen (pStr); // save a copy of string CacheInsPt = pTES->InsPt; CacheCursorPos = pTES->CursorPos; memcpy (pTES->CacheStr, pTES->BaseStr, pTES->MaxSize); // process the pending character buffer ch = GetNextCharacter (); if (!ch && PulsedInputState.menu[KEY_MENU_ANY]) { // keyboard repeat, but only when buffer empty ch = GetLastCharacter (); } while (ch) { UNICODE chbuf[8]; int chsize; pTES->JoystickMode = FALSE; chsize = getStringFromChar (chbuf, sizeof (chbuf), ch); if (isWidePrintChar (ch) && chsize > 0) { if (pStr + len - pTES->BaseStr + chsize < pTES->MaxSize) { // insert character, when fits memmove (pStr + chsize, pStr, len + 1); memcpy (pStr, chbuf, chsize); pStr += chsize; ++pTES->CursorPos; changed = TRUE; } else { // does not fit PlayMenuSound (MENU_SOUND_FAILURE); } } ch = GetNextCharacter (); } if (PulsedInputState.menu[KEY_MENU_DELETE]) { if (len) { joy_char_t ch; ReadOneChar (&ch, pStr); memmove (pStr, pStr + ch.len, len - ch.len + 1); len -= ch.len; changed = TRUE; } } else if (PulsedInputState.menu[KEY_MENU_BACKSPACE]) { if (pStr > pTES->BaseStr) { UNICODE *prev = skipUTF8Chars (pTES->BaseStr, pTES->CursorPos - 1); memmove (prev, pStr, len + 1); pStr = prev; --pTES->CursorPos; changed = TRUE; } } else if (PulsedInputState.menu[KEY_MENU_LEFT]) { if (pStr > pTES->BaseStr) { UNICODE *prev = skipUTF8Chars (pTES->BaseStr, pTES->CursorPos - 1); pStr = prev; len += (prev - pStr); --pTES->CursorPos; changed = TRUE; } } else if (PulsedInputState.menu[KEY_MENU_RIGHT]) { if (len > 0) { joy_char_t ch; ReadOneChar (&ch, pStr); pStr += ch.len; len -= ch.len; ++pTES->CursorPos; changed = TRUE; } } else if (PulsedInputState.menu[KEY_MENU_HOME]) { if (pStr > pTES->BaseStr) { pStr = pTES->BaseStr; len = strlen (pStr); pTES->CursorPos = 0; changed = TRUE; } } else if (PulsedInputState.menu[KEY_MENU_END]) { if (len > 0) { pTES->CursorPos += utf8StringCount (pStr); pStr += len; len = 0; changed = TRUE; } } if (pTES->JoyAlpha && ( PulsedInputState.menu[KEY_MENU_UP] || PulsedInputState.menu[KEY_MENU_DOWN] || PulsedInputState.menu[KEY_MENU_PAGE_UP] || PulsedInputState.menu[KEY_MENU_PAGE_DOWN]) ) { // do joystick text joy_char_t ch; joy_char_t newch; joy_char_t cmpch; int i; pTES->JoystickMode = TRUE; if (len) ReadOneChar (&ch, pStr); else ch = pTES->JoyAlpha[0]; newch = ch; JoyCharToUpper (&cmpch, &ch, pTES); // find current char in the alphabet i = JoyCharFindIn (&cmpch, pTES->JoyAlpha, pTES->JoyAlphaLength); if (PulsedInputState.menu[KEY_MENU_UP]) { --i; if (i < 0) i = pTES->JoyAlphaLength - 1; newch = pTES->JoyAlpha[i]; } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { ++i; if (i >= pTES->JoyAlphaLength) i = 0; newch = pTES->JoyAlpha[i]; } if (PulsedInputState.menu[KEY_MENU_PAGE_UP] || PulsedInputState.menu[KEY_MENU_PAGE_DOWN]) { if (len) { // single char change if (JoyCharIsLower (&newch, pTES)) JoyCharToUpper (&newch, &newch, pTES); else JoyCharToLower (&newch, &newch, pTES); } else { // register change pTES->UpperRegister = !pTES->UpperRegister; } } else { // check register if (pTES->UpperRegister) JoyCharToUpper (&newch, &newch, pTES); else JoyCharToLower (&newch, &newch, pTES); } if (strcmp (newch.enc, ch.enc) != 0) { // new char is different, put it in if (len) { // change current -- this is messy with utf8 int l = len - ch.len; if (pStr + l - pTES->BaseStr + newch.len < pTES->MaxSize) { // adjust other chars if necessary if (newch.len != ch.len) memmove (pStr + newch.len, pStr + ch.len, l + 1); memcpy (pStr, newch.enc, newch.len); len = l + newch.len; changed = TRUE; } } else { // append if (pStr + len - pTES->BaseStr + newch.len < pTES->MaxSize) { memcpy (pStr, newch.enc, newch.len); pStr[newch.len] = '\0'; len += newch.len; changed = TRUE; } else { // does not fit PlayMenuSound (MENU_SOUND_FAILURE); } } } } if (PulsedInputState.menu[KEY_MENU_SELECT]) { // done entering pTES->Success = TRUE; return FALSE; } else if (PulsedInputState.menu[KEY_MENU_EDIT_CANCEL]) { // canceled entering pTES->Success = FALSE; return FALSE; } pTES->InsPt = pStr; if (changed && pTES->ChangeCallback) { if (!pTES->ChangeCallback (pTES)) { // changes not accepted - revert memcpy (pTES->BaseStr, pTES->CacheStr, pTES->MaxSize); pTES->InsPt = CacheInsPt; pTES->CursorPos = CacheCursorPos; PlayMenuSound (MENU_SOUND_FAILURE); } } if (pTES->FrameCallback) return pTES->FrameCallback (pTES); return TRUE; } uqm-0.6.2/sc2/src/sc2code/demo.h0000600000175000017500000000247010543202103014675 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _DEMO_H #define _DEMO_H #ifndef DEMO_MODE #define DEMO_MODE 0 #endif /* DEMO_MODE */ #ifndef CREATE_JOURNAL #define CREATE_JOURNAL 0 #endif /* CREATE_JOURNAL */ #if !(DEMO_MODE || CREATE_JOURNAL) #define OpenJournal SeedRandomNumbers #define CloseJournal() TRUE #define JournalInput(is) #else extern void OpenJournal (void); extern BOOLEAN CloseJournal (void); #if !CREATE_JOURNAL #define JournalInput(is) #else /* CREATE_JOURNAL */ extern void JournalInput (INPUT_STATE InputState); #endif /* CREATE_JOURNAL */ #endif #endif /* _DEMO_H */ uqm-0.6.2/sc2/src/sc2code/build.c0000600000175000017500000002640110543202100015040 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "races.h" #include "setup.h" #include "libs/compiler.h" #include "libs/mathlib.h" HSTARSHIP Build (PQUEUE pQueue, DWORD RaceResIndex, COUNT which_player, BYTE captains_name_index) { HSTARSHIP hNewShip; if ((hNewShip = AllocStarShip (pQueue)) != 0) { STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip (pQueue, hNewShip); memset (StarShipPtr, 0, GetLinkSize (pQueue)); StarShipPtr->RaceResIndex = RaceResIndex; OwnStarShip (StarShipPtr, which_player, captains_name_index); UnlockStarShip (pQueue, hNewShip); PutQueue (pQueue, hNewShip); } return (hNewShip); } HSTARSHIP GetStarShipFromIndex (PQUEUE pShipQ, COUNT Index) { HSTARSHIP hStarShip, hNextShip; for (hStarShip = GetHeadLink (pShipQ); Index > 0 && hStarShip; hStarShip = hNextShip, --Index) { STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip (pShipQ, hStarShip); hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (pShipQ, hStarShip); } return (hStarShip); } /* * What this function does depends on the value of the 'state' argument: * SPHERE_TRACKING: * The sphere of influence for the race for 'which_ship' will be shown * on the starmap in the future. * The value returned is 'which_ship', unless the type of ship is only * available in SuperMelee, in which case 0 is returned. * SPHERE_KNOWN: * The size of the fleet of the race of 'which_ship' when the starmap was * last checked is returned. * ESCORT_WORTH: * The total value of all the ships escorting the SIS is returned. * 'which_ship' is ignored. * ESCORTING_FLAGSHIP: * Test if a ship of type 'which_ship' is among the escorts of the SIS * 0 is returned if false, 1 if true. * FEASIBILITY_STUDY: * Test if the SIS can have an escort of type 'which_ship'. * 0 is returned if 'which_ship' is not available. * Otherwise, the number of ships that can be added is returned. * CHECK_ALLIANCE: * Test the alliance status of the race of 'which_ship'. * Either GOOD_GUY (allied) or BAD_GUY (not allied) is returned. * 0: * Ally with the race of 'which_ship'. This makes their ship available * for building in the shipyard. * -1: * End an alliance with the race of 'which_ship'. This ends the possibility * of building their ships in the shipyard. For the Orz also the ships the * player has with him will disappear. * any other positive number: * Give the player this much ships of type 'which_ship'. If it's */ COUNT ActivateStarShip (COUNT which_ship, SIZE state) { HSTARSHIP hStarShip, hNextShip; hStarShip = GetStarShipFromIndex ( &GLOBAL (avail_race_q), which_ship ); if (hStarShip) { switch (state) { case SPHERE_TRACKING: case SPHERE_KNOWN: { EXTENDED_SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip); if (state == SPHERE_KNOWN) which_ship = StarShipPtr->ShipInfo.known_strength; else if (StarShipPtr->ShipInfo.actual_strength == 0) { if (!(StarShipPtr->ShipInfo.ship_flags & (GOOD_GUY | BAD_GUY))) which_ship = 0; } else if (StarShipPtr->ShipInfo.known_strength == 0 && StarShipPtr->ShipInfo.actual_strength != (COUNT)~0) { StarShipPtr->ShipInfo.known_strength = 1; StarShipPtr->ShipInfo.known_loc = StarShipPtr->ShipInfo.loc; } UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); return (which_ship); } case ESCORT_WORTH: { COUNT ShipCost[] = { RACE_SHIP_COST }; COUNT total = 0; for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)); hStarShip; hStarShip = hNextShip) { SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR) LockStarShip ( &GLOBAL (built_ship_q), hStarShip); hNextShip = _GetSuccLink (StarShipPtr); total += ShipCost[GET_RACE_ID (StarShipPtr)]; UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); } return total; } case ESCORTING_FLAGSHIP: { for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)); hStarShip; hStarShip = hNextShip) { BYTE ship_type; SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR) LockStarShip ( &GLOBAL (built_ship_q), hStarShip); hNextShip = _GetSuccLink (StarShipPtr); ship_type = GET_RACE_ID (StarShipPtr); UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); if ((COUNT) ship_type == which_ship) return 1; } return 0; } case FEASIBILITY_STUDY: return (MAX_BUILT_SHIPS - CountLinks (&GLOBAL (built_ship_q))); default: { SHIP_FRAGMENTPTR StarShipPtr; if (state <= 0) { StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip ); if (state == CHECK_ALLIANCE) { state = StarShipPtr->ShipInfo.ship_flags & (GOOD_GUY | BAD_GUY); UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); return ((COUNT)state); } else if (StarShipPtr->ShipInfo.ship_flags & (GOOD_GUY | BAD_GUY)) { StarShipPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); if (state == 0) StarShipPtr->ShipInfo.ship_flags |= GOOD_GUY; else { StarShipPtr->ShipInfo.ship_flags |= BAD_GUY; if (which_ship == ORZ_SHIP) { BOOLEAN ShipRemoved; ShipRemoved = FALSE; for (hStarShip = GetHeadLink ( &GLOBAL (built_ship_q)); hStarShip; hStarShip = hNextShip) { BOOLEAN RemoveShip; SHIP_FRAGMENTPTR StarShipPtr2; StarShipPtr2 = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip); hNextShip = _GetSuccLink (StarShipPtr2); RemoveShip = (BOOLEAN) ( GET_RACE_ID (StarShipPtr2) == ORZ_SHIP); UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); if (RemoveShip) { ShipRemoved = TRUE; RemoveQueue (&GLOBAL (built_ship_q), hStarShip); FreeStarShip (&GLOBAL (built_ship_q), hStarShip); } } if (ShipRemoved) { LockMutex (GraphicsLock); DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, UNDEFINED_DELTA); UnlockMutex (GraphicsLock); } } } } UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } else { /* 'state > 0', add ships to the escorts */ BYTE which_window; COUNT i; which_window = 0; for (i = 0; i < (COUNT)state; i++) { HSTARSHIP hOldShip; BYTE crewLevel; if (which_ship == SPATHI_SHIP && GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) crewLevel = 1; // Only Fwiffo is on board. else crewLevel = 0; // Crewed to the max hStarShip = CloneShipFragment((COUNT) which_ship, &GLOBAL (built_ship_q), crewLevel); if (!hStarShip) break; RemoveQueue (&GLOBAL (built_ship_q), hStarShip); while ((hOldShip = GetStarShipFromIndex ( &GLOBAL (built_ship_q), which_window++))) { BYTE win_loc; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hOldShip); win_loc = GET_GROUP_LOC (StarShipPtr); UnlockStarShip (&GLOBAL (built_ship_q), hOldShip); if (which_window <= win_loc) break; } StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip); SET_GROUP_LOC (StarShipPtr, which_window - 1); if (which_ship == SPATHI_SHIP && GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) { OwnStarShip (StarShipPtr, GOOD_GUY, NAME_OFFSET + NUM_CAPTAINS_NAMES); } UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); InsertQueue (&GLOBAL (built_ship_q), hStarShip, hOldShip); } LockMutex (GraphicsLock); DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, UNDEFINED_DELTA); UnlockMutex (GraphicsLock); return (i); } break; } } return 1; } return 0; } COUNT GetIndexFromStarShip (PQUEUE pShipQ, HSTARSHIP hStarShip) { COUNT Index; Index = 0; while (hStarShip != GetHeadLink (pShipQ)) { HSTARSHIP hNextShip; STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip (pShipQ, hStarShip); hNextShip = _GetPredLink (StarShipPtr); UnlockStarShip (pShipQ, hStarShip); hStarShip = hNextShip; ++Index; } return Index; } BYTE NameCaptain (PQUEUE pQueue, STARSHIPPTR StarShipPtr) { BYTE name_index; HSTARSHIP hStarShip; do { HSTARSHIP hNextShip; name_index = PickCaptainName (); for (hStarShip = GetHeadLink (pQueue); hStarShip; hStarShip = hNextShip) { STARSHIPPTR TestShipPtr; TestShipPtr = LockStarShip (pQueue, hStarShip); hNextShip = _GetSuccLink (TestShipPtr); if (TestShipPtr->RaceResIndex == StarShipPtr->RaceResIndex) { BOOLEAN SameName; if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE) SameName = (BOOLEAN)( name_index == TestShipPtr->captains_name_index ); else SameName = (BOOLEAN)( name_index == StarShipCaptain (TestShipPtr) ); if (SameName) { UnlockStarShip (pQueue, hStarShip); break; } } UnlockStarShip (pQueue, hStarShip); } } while (hStarShip); return name_index; } // crew_level can be set to INFINITE_FLEET for a ship which is to // represent an infinite number of ships. HSTARSHIP CloneShipFragment (COUNT shipIndex, PQUEUE pDstQueue, COUNT crew_level) { HSTARSHIP hStarShip, hBuiltShip; SHIP_FRAGMENTPTR TemplatePtr; hStarShip = GetStarShipFromIndex (&GLOBAL (avail_race_q), shipIndex); if (hStarShip == 0) return 0; TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip); hBuiltShip = Build (pDstQueue, TemplatePtr->RaceResIndex, TemplatePtr->ShipInfo.ship_flags & (GOOD_GUY | BAD_GUY), (BYTE)(shipIndex == SAMATRA_SHIP ? 0 : NameCaptain (pDstQueue, (STARSHIPPTR)TemplatePtr))); if (hBuiltShip) { SHIP_FRAGMENTPTR ShipFragPtr; ShipFragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pDstQueue, hBuiltShip); ShipFragPtr->ShipInfo = TemplatePtr->ShipInfo; if (crew_level) ShipFragPtr->ShipInfo.crew_level = crew_level; ShipFragPtr->ShipInfo.energy_level = 0; ShipFragPtr->ShipInfo.ship_flags = 0; ShipFragPtr->ShipInfo.var1 = ShipFragPtr->ShipInfo.var2 = 0; ShipFragPtr->ShipInfo.loc.x = ShipFragPtr->ShipInfo.loc.y = 0; SET_RACE_ID (ShipFragPtr, (BYTE)shipIndex); UnlockStarShip (pDstQueue, hBuiltShip); } UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); return hBuiltShip; } uqm-0.6.2/sc2/src/sc2code/shipcont.h0000700000175000017500000000223210543202103015575 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SHIPCONT_H #define _SHIPCONT_H #include "menustat.h" #define FIELD_WIDTH (STATUS_WIDTH - 5) extern void Cargo (PMENU_STATE pMS); extern BOOLEAN Roster (void); extern BOOLEAN Devices (PMENU_STATE pMS); extern void DrawCargoStrings (BYTE OldElement, BYTE NewElement); extern void ShowRemainingCapacity (void); extern SIZE InventoryDevices (BYTE *pDeviceMap); #endif /* _SHIPCONT_H */ uqm-0.6.2/sc2/src/sc2code/loadship.c0000600000175000017500000001126310543202101015545 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "coderes.h" #include "globdata.h" #include "nameref.h" #include "races.h" MEM_HANDLE load_ship (STARSHIPPTR StarShipPtr, BOOLEAN LoadBattleData) { BOOLEAN retval; MEM_HANDLE h; h = OpenResourceIndexInstance (StarShipPtr->RaceResIndex); retval = FALSE; if (h) { #define INITIAL_CODE_RES MAKE_RESOURCE (1, CODE, 0) BYTE captains_name_index; PVOID CodeRef; MEM_HANDLE hOldIndex; COUNT which_player; captains_name_index = StarShipCaptain (StarShipPtr); which_player = StarShipPlayer (StarShipPtr); hOldIndex = SetResourceIndex (h); CodeRef = CaptureCodeRes (LoadCodeRes (INITIAL_CODE_RES), (PVOID)&GlobData, (PVOID)&StarShipPtr->RaceDescPtr); if (CodeRef == 0) goto BadLoad; StarShipPtr->RaceDescPtr->CodeRef = CodeRef; StarShipPtr->RaceDescPtr->ship_info.icons = CaptureDrawable (LoadGraphic ( (RESOURCE)StarShipPtr->RaceDescPtr->ship_info.icons)); if (StarShipPtr->RaceDescPtr->ship_info.icons == 0) { /* goto BadLoad */ } StarShipPtr->RaceDescPtr->ship_info.melee_icon = CaptureDrawable (LoadGraphic ( (RESOURCE)StarShipPtr->RaceDescPtr->ship_info.melee_icon)); if (StarShipPtr->RaceDescPtr->ship_info.melee_icon == 0) { /* goto BadLoad */ } StarShipPtr->RaceDescPtr->ship_info.race_strings = CaptureStringTable (LoadStringTable ( (RESOURCE)StarShipPtr->RaceDescPtr->ship_info.race_strings)); if (StarShipPtr->RaceDescPtr->ship_info.race_strings == 0) { /* goto BadLoad */ } if (LoadBattleData) { DATA_STUFFPTR RawPtr; StarShipPtr->captains_name_index = captains_name_index; StarShipPtr->RaceDescPtr->ship_info.ship_flags |= which_player; RawPtr = &StarShipPtr->RaceDescPtr->ship_data; if (!load_animation (RawPtr->ship, (RESOURCE)RawPtr->ship[0], (RESOURCE)RawPtr->ship[1], (RESOURCE)RawPtr->ship[2])) goto BadLoad; if (RawPtr->weapon[0] != 0) { if (!load_animation (RawPtr->weapon, (RESOURCE)RawPtr->weapon[0], (RESOURCE)RawPtr->weapon[1], (RESOURCE)RawPtr->weapon[2])) goto BadLoad; } if (RawPtr->special[0] != 0) { if (!load_animation (RawPtr->special, (RESOURCE)RawPtr->special[0], (RESOURCE)RawPtr->special[1], (RESOURCE)RawPtr->special[2])) goto BadLoad; } if (RawPtr->captain_control.background != 0) { RawPtr->captain_control.background = CaptureDrawable (LoadGraphic ( (RESOURCE)RawPtr->captain_control.background)); if (RawPtr->captain_control.background == 0) goto BadLoad; } if (RawPtr->victory_ditty != 0) { RawPtr->victory_ditty = LoadMusic ((RESOURCE)RawPtr->victory_ditty); if (RawPtr->victory_ditty == 0) goto BadLoad; } if (RawPtr->ship_sounds != 0) { RawPtr->ship_sounds = CaptureSound ( LoadSound ((RESOURCE)RawPtr->ship_sounds)); if (RawPtr->ship_sounds == 0) goto BadLoad; } if (StarShipPtr->RaceDescPtr->ship_info.icons) StarShipPtr->silhouette = IncFrameIndex ( StarShipPtr->RaceDescPtr->ship_info.icons); } retval = TRUE; BadLoad: SetResourceIndex (hOldIndex); CloseResourceIndex (h); } return (retval); } void free_ship (STARSHIPPTR StarShipPtr, BOOLEAN FreeBattleData) { RACE_DESCPTR raceDescPtr = StarShipPtr->RaceDescPtr; SHIP_INFO *shipInfo = &raceDescPtr->ship_info; if (FreeBattleData) { DATA_STUFF *shipData = &raceDescPtr->ship_data; free_image (shipData->special); free_image (shipData->weapon); free_image (shipData->ship); DestroyDrawable ( ReleaseDrawable (shipData->captain_control.background)); DestroyMusic ((MUSIC_REF)shipData->victory_ditty); DestroySound (ReleaseSound (shipData->ship_sounds)); } DestroyDrawable (ReleaseDrawable (shipInfo->melee_icon)); DestroyDrawable (ReleaseDrawable (shipInfo->icons)); DestroyStringTable (ReleaseStringTable (shipInfo->race_strings)); DestroyCodeRes (ReleaseCodeRes (raceDescPtr->CodeRef)); StarShipPtr->RaceDescPtr = 0; } uqm-0.6.2/sc2/src/sc2code/units.h0000600000175000017500000001377110543202103015121 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UNITS_H #define _UNITS_H #include "libs/gfxlib.h" extern int ScreenWidth; extern int ScreenHeight; #define SCREEN_WIDTH ScreenWidth #define SCREEN_HEIGHT ScreenHeight #define SAFE_X 0 /* Left and right screen margin to be left unused */ #define SAFE_Y 0 /* Top and bottom screen margin to be left unused */ #define SIS_ORG_X (7 + SAFE_X) #define SIS_ORG_Y (10 + SAFE_Y) #define STATUS_WIDTH 64 /* Width of the status "window" (the right part of the screen) */ #define STATUS_HEIGHT (SCREEN_HEIGHT - (SAFE_Y * 2)) /* Height of the status "window" (the right part of the screen) */ #define SPACE_WIDTH (SCREEN_WIDTH - STATUS_WIDTH - (SAFE_X * 2)) /* Width of the space "window" (the left part of the screen) */ #define SPACE_HEIGHT (SCREEN_HEIGHT - (SAFE_Y * 2)) /* Height of the space "window" (the left part of the screen) */ #define SIS_SCREEN_WIDTH (SPACE_WIDTH - 14) /* Width of the usable part of the space "window" */ #define SIS_SCREEN_HEIGHT (SPACE_HEIGHT - 13) /* Height of the usable part of the space "window" */ #define MAX_REDUCTION 3 #define MAX_VIS_REDUCTION 2 #define REDUCTION_SHIFT 1 #define NUM_VIEWS (MAX_VIS_REDUCTION + 1) #define ZOOM_SHIFT 8 #define MAX_ZOOM_OUT (1 << (ZOOM_SHIFT + MAX_REDUCTION - 1)) #define ONE_SHIFT 2 #define BACKGROUND_SHIFT 3 #define SCALED_ONE (1 << ONE_SHIFT) #define DISPLAY_TO_WORLD(x) ((x)<>ONE_SHIFT) #define DISPLAY_ALIGN(x) ((COORD)(x)&~(SCALED_ONE-1)) #define DISPLAY_ALIGN_X(x) ((COORD)((COUNT)(x)%LOG_SPACE_WIDTH)&~(SCALED_ONE-1)) #define DISPLAY_ALIGN_Y(y) ((COORD)((COUNT)(y)%LOG_SPACE_HEIGHT)&~(SCALED_ONE-1)) #define LOG_SPACE_WIDTH \ (DISPLAY_TO_WORLD (SPACE_WIDTH) << MAX_REDUCTION) #define LOG_SPACE_HEIGHT \ (DISPLAY_TO_WORLD (SPACE_HEIGHT) << MAX_REDUCTION) #define TRANSITION_WIDTH \ (DISPLAY_TO_WORLD (SPACE_WIDTH) << MAX_VIS_REDUCTION) #define TRANSITION_HEIGHT \ (DISPLAY_TO_WORLD (SPACE_HEIGHT) << MAX_VIS_REDUCTION) #define MAX_X_UNIVERSE 9999 #define MAX_Y_UNIVERSE 9999 #define MAX_X_LOGICAL \ ((UNIVERSE_TO_LOGX (MAX_X_UNIVERSE + 1) > UNIVERSE_TO_LOGX (-1) ? \ UNIVERSE_TO_LOGX (MAX_X_UNIVERSE) : UNIVERSE_TO_LOGX (-1)) \ - 1L) #define MAX_Y_LOGICAL \ ((UNIVERSE_TO_LOGY (MAX_Y_UNIVERSE + 1) > UNIVERSE_TO_LOGY (-1) ? \ UNIVERSE_TO_LOGY (MAX_Y_UNIVERSE) : UNIVERSE_TO_LOGY (-1)) \ - 1L) #define SECTOR_WIDTH 195 #define SECTOR_HEIGHT 25 #define SPHERE_RADIUS_INCREMENT 11 #define MAX_FLEET_STRENGTH (254 * SPHERE_RADIUS_INCREMENT) #define UNIT_SCREEN_WIDTH 63 #define UNIT_SCREEN_HEIGHT 50 static inline COORD logxToUniverse (SDWORD lx) { return (COORD) ((lx * ((MAX_X_UNIVERSE + 1) >> 4)) * 10 / ((SDWORD) ((LOG_SPACE_WIDTH) >> 4) * SECTOR_WIDTH)); } #define LOGX_TO_UNIVERSE(lx) \ logxToUniverse (lx) static inline COORD logyToUniverse (SDWORD ly) { return (COORD) (MAX_Y_UNIVERSE - (COORD)(((SDWORD) (ly) * ((MAX_Y_UNIVERSE + 1) >> 4)) / ((SDWORD) ((LOG_SPACE_HEIGHT) >> 4) * SECTOR_HEIGHT))); } #define LOGY_TO_UNIVERSE(ly) \ logyToUniverse (ly) static inline SDWORD universeToLogx (COORD ux) { return ((SDWORD) ux * ((SDWORD) ((LOG_SPACE_WIDTH) >> 4) * SECTOR_WIDTH) + ((((MAX_X_UNIVERSE + 1) >> 4) * 10) >> 1)) / (((MAX_X_UNIVERSE + 1) >> 4) * 10); } #define UNIVERSE_TO_LOGX(ux) \ universeToLogx (ux) static inline SDWORD universeToLogy (COORD uy) { return ((SDWORD) (MAX_Y_UNIVERSE - uy) * ((SDWORD) ((LOG_SPACE_HEIGHT) >> 4) * SECTOR_HEIGHT) + (((MAX_Y_UNIVERSE + 1) >> 4) >> 1)) / ((MAX_Y_UNIVERSE + 1) >> 4); } #define UNIVERSE_TO_LOGY(uy) \ universeToLogy (uy) #define CIRCLE_SHIFT 6 #define FULL_CIRCLE (1 << CIRCLE_SHIFT) #define OCTANT_SHIFT (CIRCLE_SHIFT - 3) /* (1 << 3) == 8 */ #define HALF_CIRCLE (FULL_CIRCLE >> 1) #define QUADRANT (FULL_CIRCLE >> 2) #define OCTANT (FULL_CIRCLE >> 3) #define FACING_SHIFT 4 #define ANGLE_TO_FACING(a) (((a)+(1<<(CIRCLE_SHIFT-FACING_SHIFT-1))) \ >>(CIRCLE_SHIFT-FACING_SHIFT)) #define FACING_TO_ANGLE(f) ((f)<<(CIRCLE_SHIFT-FACING_SHIFT)) #define NORMALIZE_ANGLE(a) ((COUNT)(a)&(COUNT)(FULL_CIRCLE-1)) #define NORMALIZE_FACING(f) ((COUNT)(f)&((1 << FACING_SHIFT)-1)) #define DEGREES_TO_ANGLE(d) NORMALIZE_ANGLE((((d) % 360) * FULL_CIRCLE \ + HALF_CIRCLE) / 360) #define ANGLE_TO_DEGREES(d) (NORMALIZE_ANGLE(d) * 360 / FULL_CIRCLE) #define SIN_SHIFT 14 #define SIN_SCALE (1 << SIN_SHIFT) #define INT_ADJUST(x) ((x)<>SIN_SHIFT) #define ROUND(x,y) ((x)+((x)>=0?((y)>>1):-((y)>>1))) extern SIZE sinetab[]; #define SINVAL(a) sinetab[NORMALIZE_ANGLE(a)] #define COSVAL(a) SINVAL((a)+QUADRANT) #define SINE(a,m) ((SIZE)((((long)SINVAL(a))*(long)(m))>>SIN_SHIFT)) #define COSINE(a,m) SINE((a)+QUADRANT,m) extern COUNT ARCTAN (SIZE delta_x, SIZE delta_y); #define WRAP_VAL(v,w) ((COUNT)((v)<0?((v)+(w)):((v)>=(w)?((v)-(w)):(v)))) #define WRAP_X(x) WRAP_VAL(x,LOG_SPACE_WIDTH) #define WRAP_Y(y) WRAP_VAL(y,LOG_SPACE_HEIGHT) #define WRAP_DELTA_X(dx) ((dx)<0 ? \ ((-(dx)<=LOG_SPACE_WIDTH>>1)?(dx):(LOG_SPACE_WIDTH+(dx))) : \ (((dx)<=LOG_SPACE_WIDTH>>1)?(dx):((dx)-LOG_SPACE_WIDTH))) #define WRAP_DELTA_Y(dy) ((dy)<0 ? \ ((-(dy)<=LOG_SPACE_HEIGHT>>1)?(dy):(LOG_SPACE_HEIGHT+(dy))) : \ (((dy)<=LOG_SPACE_HEIGHT>>1)?(dy):((dy)-LOG_SPACE_HEIGHT))) #endif /* _UNITS_H */ uqm-0.6.2/sc2/src/sc2code/races.h0000600000175000017500000004544210543202103015054 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _RACES_H #define _RACES_H #include "units.h" #include "element.h" #include "libs/compiler.h" #include "libs/sndlib.h" #define RACES_PER_PLAYER 7 #define MAX_SHIPS_PER_SIDE 14 /* heat of battle specific flags */ #define LEFT (1 << 0) #define RIGHT (1 << 1) #define THRUST (1 << 2) #define WEAPON (1 << 3) #define SPECIAL (1 << 4) #define LOW_ON_ENERGY (1 << 5) #define SHIP_BEYOND_MAX_SPEED (1 << 6) #define SHIP_AT_MAX_SPEED (1 << 7) #define SHIP_IN_GRAVITY_WELL (1 << 8) #define PLAY_VICTORY_DITTY (1 << 9) /* ship specific flags */ /* #define GOOD_GUY (1 << 0) #define BAD_GUY (1 << 1) */ #define SEEKING_WEAPON (1 << 2) #define SEEKING_SPECIAL (1 << 3) #define POINT_DEFENSE (1 << 4) /* Ship has some point-defense capabilities */ #define IMMEDIATE_WEAPON (1 << 5) #define CREW_IMMUNE (1 << 6) #define FIRES_FORE (1 << 7) #define FIRES_RIGHT (1 << 8) #define FIRES_AFT (1 << 9) #define FIRES_LEFT (1 << 10) #define SHIELD_DEFENSE (1 << 11) #define DONT_CHASE (1 << 12) #define PLAYER_CAPTAIN (1 << 13) /* The protagonist himself is on board. He gets a different color. */ typedef struct captain_stuff { FRAME background; FRAME turn; FRAME thrust; FRAME weapon; FRAME special; } CAPTAIN_STUFF; typedef CAPTAIN_STUFF *PCAPTAIN_STUFF; #define CAPTAIN_STUFFPTR PCAPTAIN_STUFF typedef void (IntelligenceFunc) (PVOID ShipPtr, PVOID ObjectsOfConcern, COUNT ConcernCounter); typedef struct { COUNT ManeuverabilityIndex; COUNT WeaponRange; IntelligenceFunc *intelligence_func; } INTEL_STUFF; typedef struct { COUNT max_thrust, thrust_increment; BYTE energy_regeneration, weapon_energy_cost, special_energy_cost, energy_wait, turn_wait, thrust_wait, weapon_wait, special_wait, ship_mass; } CHARACTERISTIC_STUFF; typedef CHARACTERISTIC_STUFF *PCHARACTERISTIC_STUFF; typedef struct { UWORD ship_flags; BYTE var1, var2; COUNT crew_level, max_crew; /* For ships in npc_built_ship_q, the value INFINITE_FLEET for * crew_level indicates an infinite number of ships. */ BYTE energy_level, max_energy; POINT loc; /* The fields above this line are included in queues in savegames, * All fields, including those below, are saved in ENCOUNTER structures * in savegames. The latter was probably not supposed to happen. */ STRING race_strings; FRAME icons, melee_icon; #define INFINITE_FLEET ((COUNT) ~0) } SHIP_INFO; typedef SHIP_INFO *PSHIP_INFO; #define SHIP_INFOPTR PSHIP_INFO #define ship_cost var1 #define group_counter ship_flags enum { IN_ORBIT = 0, EXPLORE, FLEE, ON_STATION, IGNORE_FLAGSHIP = 1 << 2, REFORM_GROUP = 1 << 3 }; #define MAX_REVOLUTIONS 5 #define GET_RACE_ID(s) ((s)->ShipInfo.var1) #define SET_RACE_ID(s,v) ((s)->ShipInfo.var1 = (v)) #define GET_GROUP_LOC(s) LONIBBLE ((s)->ShipInfo.var2) #define SET_GROUP_LOC(s,v) ((s)->ShipInfo.var2 = \ MAKE_BYTE ((v), HINIBBLE ((s)->ShipInfo.var2))) #define GET_GROUP_MISSION(s) HINIBBLE ((s)->ShipInfo.var2) #define SET_GROUP_MISSION(s,v) ((s)->ShipInfo.var2 = \ MAKE_BYTE (LONIBBLE ((s)->ShipInfo.var2), (v))) #define GET_GROUP_DEST(s) LONIBBLE ((s)->ShipInfo.energy_level) #define SET_GROUP_DEST(s,v) ((s)->ShipInfo.energy_level = \ MAKE_BYTE ((v), HINIBBLE ((s)->ShipInfo.energy_level))) #define GET_ORBIT_LOC(s) HINIBBLE ((s)->ShipInfo.energy_level) #define SET_ORBIT_LOC(s,v) ((s)->ShipInfo.energy_level = \ MAKE_BYTE (LONIBBLE ((s)->ShipInfo.energy_level), (v))) #define GET_GROUP_ID(s) ((s)->ShipInfo.max_energy) #define SET_GROUP_ID(s,v) ((s)->ShipInfo.max_energy = (v)) #define STATION_RADIUS 1600 #define ORBIT_RADIUS 2400 typedef struct { UWORD ship_flags; BYTE days_left; /* Days left before the fleet reachers 'dest_loc'. */ BYTE growth_fract; COUNT crew_level, max_crew; /* For ships in npc_built_ship_q, the value INFINITE_FLEET for * crew_level indicates an infinite number of ships. */ BYTE energy_level, max_energy; POINT loc; /* Location of the fleet (center) */ STRING race_strings; /* Race specific strings, see doc/devel/racestrings. */ FRAME icons, melee_icon; /* -== The fields below this line are included in savegames. ==- */ COUNT actual_strength; /* Measure for the size of the sphere of influence. * 0 if there is none and no ships will be generated. * '(COUNT) ~0' if there is none, and the ship generation * is handled separately. */ COUNT known_strength; /* Measure for the size of the sphere of influence when last * checked the starmap. * 0 if the race's SoI is not known. */ POINT known_loc; /* Location of the SoI (center) when last checked * the starmap. */ BYTE growth_err_term; BYTE func_index; /* Function index defined in clock.h (the same as in SetEvent()) * for the function to call when the fleet reaches 'dest_loc'. * '(BYTE) ~0' means no function to call. */ POINT dest_loc; /* Location to which the fleet (center) is moving. */ } EXTENDED_SHIP_INFO; typedef EXTENDED_SHIP_INFO *PEXTENDED_SHIP_INFO; typedef struct { FRAME ship[NUM_VIEWS]; FRAME weapon[NUM_VIEWS]; FRAME special[NUM_VIEWS]; CAPTAIN_STUFF captain_control; DWORD victory_ditty; SOUND ship_sounds; } DATA_STUFF; typedef DATA_STUFF *PDATA_STUFF; #define DATA_STUFFPTR PDATA_STUFF typedef struct race_desc RACE_DESC; typedef RACE_DESC *PRACE_DESC; #define RACE_DESCPTR PRACE_DESC typedef void (PREPROCESS_FUNC) (PELEMENT ElementPtr); typedef void (POSTPROCESS_FUNC) (PELEMENT ElementPtr); typedef COUNT (INIT_WEAPON_FUNC) (PELEMENT ElementPtr, HELEMENT Weapon[]); typedef void (UNINIT_FUNC) (RACE_DESCPTR pRaceDesc); struct race_desc { SHIP_INFO ship_info _ALIGNED_ANY; CHARACTERISTIC_STUFF characteristics _ALIGNED_ANY; DATA_STUFF ship_data _ALIGNED_ANY; INTEL_STUFF cyborg_control _ALIGNED_ANY; UNINIT_FUNC *uninit_func _ALIGNED_ON(sizeof (UNINIT_FUNC *)); PREPROCESS_FUNC *preprocess_func _ALIGNED_ON(sizeof (PREPROCESS_FUNC *)); POSTPROCESS_FUNC *postprocess_func _ALIGNED_ON(sizeof (POSTPROCESS_FUNC *)); INIT_WEAPON_FUNC *init_weapon_func _ALIGNED_ON(sizeof (INIT_WEAPON_FUNC *)); PVOID CodeRef _ALIGNED_ON(sizeof (PVOID)); }; typedef QUEUE_HANDLE HSTARSHIP; typedef struct { HSTARSHIP pred; HSTARSHIP succ; DWORD RaceResIndex; /* This field is abused to store other data when the ship * is in GLOBAL(built_ship_q), GLOBDATA(npc_built_ship_q), * or race_q[], namely the side this ship is on (accessed * through StarShipPlayer()), and the captains name for * the ship (accessed through StarShipCaptain()). * These values are set using OwnStarShip(). */ union { RACE_DESCPTR RaceDescPtr; struct { COUNT Player; BYTE Captain; } s; }; BYTE captains_name_index; BYTE weapon_counter; BYTE special_counter; BYTE energy_counter; BYTE ship_input_state; UWORD cur_status_flags _ALIGNED_ON(sizeof (UWORD)); UWORD old_status_flags _ALIGNED_ON(sizeof (UWORD)); FRAME silhouette _ALIGNED_ON(sizeof (FRAME)); HELEMENT hShip _ALIGNED_ON(sizeof (HELEMENT)); COUNT ShipFacing _ALIGNED_ON(sizeof (COUNT)); } STARSHIP; typedef STARSHIP *PSTARSHIP; #define STARSHIPPTR PSTARSHIP typedef struct { HSTARSHIP pred; HSTARSHIP succ; DWORD RaceResIndex; /* This field is abused to store other data when the ship * is in GLOBAL(built_ship_q), GLOBDATA(npc_built_ship_q), * or race_q[], namely the side this ship is on (accessed * through StarShipPlayer()), and the captains name for * the ship (accessed through StarShipCaptain()). * These values are set using OwnStarShip(). */ union { RACE_DESCPTR RaceDescPtr; struct { COUNT Player; BYTE Captain; } s; }; SHIP_INFO ShipInfo; } SHIP_FRAGMENT; typedef SHIP_FRAGMENT *PSHIP_FRAGMENT; #define SHIP_FRAGMENTPTR PSHIP_FRAGMENT typedef struct { HSTARSHIP pred; HSTARSHIP succ; DWORD RaceResIndex; RACE_DESCPTR RaceDescPtr; EXTENDED_SHIP_INFO ShipInfo; } EXTENDED_SHIP_FRAGMENT; typedef EXTENDED_SHIP_FRAGMENT *PEXTENDED_SHIP_FRAGMENT; #define EXTENDED_SHIP_FRAGMENTPTR PEXTENDED_SHIP_FRAGMENT #define AllocStarShip(pq) AllocLink (pq) #define LockStarShip(pq,h) (STARSHIPPTR)LockLink (pq, h) #define UnlockStarShip(pq,h) UnlockLink (pq, h) #define FreeStarShip(pq,h) FreeLink (pq, h) enum { ARILOU_SHIP, CHMMR_SHIP, HUMAN_SHIP, ORZ_SHIP, PKUNK_SHIP, SHOFIXTI_SHIP, SPATHI_SHIP, SUPOX_SHIP, THRADDASH_SHIP, UTWIG_SHIP, VUX_SHIP, YEHAT_SHIP, MELNORME_SHIP, DRUUGE_SHIP, ILWRATH_SHIP, MYCON_SHIP, SLYLANDRO_SHIP, UMGAH_SHIP, URQUAN_SHIP, ZOQFOTPIK_SHIP, SYREEN_SHIP, BLACK_URQUAN_SHIP, YEHAT_REBEL_SHIP, URQUAN_PROBE_SHIP, SAMATRA_SHIP = URQUAN_PROBE_SHIP, NUM_AVAILABLE_RACES }; #define YEHAT_REBEL_CONVERSATION (~0L) #define RACE_COMMUNICATION \ ARILOU_CONVERSATION, /* ARILOU_SHIP */ \ CHMMR_CONVERSATION, /* CHMMR_SHIP */ \ 0L, /* HUMAN_SHIP */ \ ORZ_CONVERSATION, /* ORZ_SHIP */ \ PKUNK_CONVERSATION, /* PKUNK_SHIP */ \ SHOFIXTI_CONVERSATION, /* SHOFIXTI_SHIP */ \ SPATHI_CONVERSATION, /* SPATHI_SHIP */ \ SUPOX_CONVERSATION, /* SUPOX_SHIP */ \ THRADD_CONVERSATION, /* THRADDASH_SHIP */ \ UTWIG_CONVERSATION, /* UTWIG_SHIP */ \ VUX_CONVERSATION, /* VUX_SHIP */ \ YEHAT_CONVERSATION, /* YEHAT_SHIP */ \ MELNORME_CONVERSATION, /* MELNORME_SHIP */ \ DRUUGE_CONVERSATION, /* DRUUGE_SHIP */ \ ILWRATH_CONVERSATION, /* ILWRATH_SHIP */ \ MYCON_CONVERSATION, /* MYCON_SHIP */ \ SLYLANDRO_CONVERSATION, /* SLYLANDRO_SHIP */ \ UMGAH_CONVERSATION, /* UMGAH_SHIP */ \ URQUAN_CONVERSATION, /* URQUAN_SHIP */ \ ZOQFOTPIK_CONVERSATION, /* ZOQFOTPIK_SHIP */ \ 0L, /* SYREEN_SHIP */ \ BLACKURQ_CONVERSATION, /* BLACK_URQUAN_SHIP */ \ YEHAT_REBEL_CONVERSATION, /* YEHAT_REBEL_SHIP */ \ 0L, /* URQUAN_PROBE_SHIP */ #define RACE_SHIP_COST \ 1600, /* ARILOU_SHIP */ \ 3000, /* CHMMR_SHIP */ \ 1100, /* HUMAN_SHIP */ \ 2300, /* ORZ_SHIP */ \ 2000, /* PKUNK_SHIP */ \ 500, /* SHOFIXTI_SHIP */ \ 1800, /* SPATHI_SHIP */ \ 1600, /* SUPOX_SHIP */ \ 1000, /* THRADDASH_SHIP */ \ 2200, /* UTWIG_SHIP */ \ 1200, /* VUX_SHIP */ \ 2300, /* YEHAT_SHIP */ \ 3600, /* MELNORME_SHIP */ \ 1700, /* DRUUGE_SHIP */ \ 1000, /* ILWRATH_SHIP */ \ 2100, /* MYCON_SHIP */ \ 4400, /* SLYLANDRO_SHIP */ \ 700, /* UMGAH_SHIP */ \ 3000, /* URQUAN_SHIP */ \ 600, /* ZOQFOTPIK_SHIP */ \ 1300, /* SYREEN_SHIP */ \ 3000, /* BLACK_URQUAN_SHIP */ \ 2300, /* YEHAT_REBEL_SHIP */ #define LOG_TO_IP(s) ((s) << 1) #define RACE_IP_SPEED \ LOG_TO_IP (40), /* ARILOU_SHIP */ \ LOG_TO_IP (27), /* CHMMR_SHIP */ \ LOG_TO_IP (24), /* HUMAN_SHIP */ \ LOG_TO_IP (40), /* ORZ_SHIP */ \ LOG_TO_IP (40), /* PKUNK_SHIP */ \ LOG_TO_IP (35), /* SHOFIXTI_SHIP */ \ LOG_TO_IP (48), /* SPATHI_SHIP */ \ LOG_TO_IP (40), /* SUPOX_SHIP */ \ LOG_TO_IP (28), /* THRADDASH_SHIP */ \ LOG_TO_IP (30), /* UTWIG_SHIP */ \ LOG_TO_IP (21), /* VUX_SHIP */ \ LOG_TO_IP (30), /* YEHAT_SHIP */ \ LOG_TO_IP (40), /* MELNORME_SHIP */ \ LOG_TO_IP (20), /* DRUUGE_SHIP */ \ LOG_TO_IP (25), /* ILWRATH_SHIP */ \ LOG_TO_IP (27), /* MYCON_SHIP */ \ LOG_TO_IP (60), /* SLYLANDRO_SHIP */ \ LOG_TO_IP (18), /* UMGAH_SHIP */ \ LOG_TO_IP (30), /* URQUAN_SHIP */ \ LOG_TO_IP (40), /* ZOQFOTPIK_SHIP */ \ LOG_TO_IP (36), /* SYREEN_SHIP */ \ LOG_TO_IP (30), /* BLACK_URQUAN_SHIP */ \ LOG_TO_IP (30), /* YEHAT_REBEL_SHIP */ \ LOG_TO_IP (90), /* URQUAN_PROBE_SHIP */ #define LOG_TO_HYPER(s) (WORLD_TO_VELOCITY (s) >> 1) #define RACE_HYPER_SPEED \ LOG_TO_HYPER (40), /* ARILOU_SHIP */ \ LOG_TO_HYPER (27), /* CHMMR_SHIP */ \ LOG_TO_HYPER (24), /* HUMAN_SHIP */ \ LOG_TO_HYPER (40), /* ORZ_SHIP */ \ LOG_TO_HYPER (40), /* PKUNK_SHIP */ \ LOG_TO_HYPER (35), /* SHOFIXTI_SHIP */ \ LOG_TO_HYPER (48), /* SPATHI_SHIP */ \ LOG_TO_HYPER (40), /* SUPOX_SHIP */ \ LOG_TO_HYPER (50), /* THRADDASH_SHIP */ \ LOG_TO_HYPER (30), /* UTWIG_SHIP */ \ LOG_TO_HYPER (21), /* VUX_SHIP */ \ LOG_TO_HYPER (30), /* YEHAT_SHIP */ \ LOG_TO_HYPER (40), /* MELNORME_SHIP */ \ LOG_TO_HYPER (20), /* DRUUGE_SHIP */ \ LOG_TO_HYPER (25), /* ILWRATH_SHIP */ \ LOG_TO_HYPER (27), /* MYCON_SHIP */ \ LOG_TO_HYPER (60), /* SLYLANDRO_SHIP */ \ LOG_TO_HYPER (18), /* UMGAH_SHIP */ \ LOG_TO_HYPER (30), /* URQUAN_SHIP */ \ LOG_TO_HYPER (40), /* ZOQFOTPIK_SHIP */ \ LOG_TO_HYPER (36), /* SYREEN_SHIP */ \ LOG_TO_HYPER (30), /* BLACK_URQUAN_SHIP */ \ LOG_TO_HYPER (30), /* YEHAT_REBEL_SHIP */ #define RACE_HYPERSPACE_PERCENT \ 20, /* ARILOU_SHIP */ \ 0, /* CHMMR_SHIP */ \ 0, /* HUMAN_SHIP */ \ 20, /* ORZ_SHIP */ \ 40, /* PKUNK_SHIP */ \ 0, /* SHOFIXTI_SHIP */ \ 20, /* SPATHI_SHIP */ \ 40, /* SUPOX_SHIP */ \ 60, /* THRADDASH_SHIP */ \ 40, /* UTWIG_SHIP */ \ 40, /* VUX_SHIP */ \ 60, /* YEHAT_SHIP */ \ 0, /* MELNORME_SHIP */ \ 30, /* DRUUGE_SHIP */ \ 60, /* ILWRATH_SHIP */ \ 40, /* MYCON_SHIP */ \ 2, /* SLYLANDRO_SHIP */ \ 30, /* UMGAH_SHIP */ \ 70, /* URQUAN_SHIP */ \ 0, /* ZOQFOTPIK_SHIP */ \ 0, /* SYREEN_SHIP */ \ 70, /* BLACK_URQUAN_SHIP */ \ 60, /* YEHAT_REBEL_SHIP */ \ 0, /* URQUAN_PROBE_SHIP */ #define RACE_INTERPLANETARY_PERCENT \ 0, /* ARILOU_SHIP */ \ 0, /* CHMMR_SHIP */ \ 0, /* HUMAN_SHIP */ \ 20, /* ORZ_SHIP */ \ 20, /* PKUNK_SHIP */ \ 0, /* SHOFIXTI_SHIP */ \ 10, /* SPATHI_SHIP */ \ 20, /* SUPOX_SHIP */ \ 20, /* THRADDASH_SHIP */ \ 20, /* UTWIG_SHIP */ \ 20, /* VUX_SHIP */ \ 40, /* YEHAT_SHIP */ \ 0, /* MELNORME_SHIP */ \ 20, /* DRUUGE_SHIP */ \ 60, /* ILWRATH_SHIP */ \ 20, /* MYCON_SHIP */ \ 5, /* SLYLANDRO_SHIP */ \ 20, /* UMGAH_SHIP */ \ 40, /* URQUAN_SHIP */ \ 0, /* ZOQFOTPIK_SHIP */ \ 0, /* SYREEN_SHIP */ \ 40, /* BLACK_URQUAN_SHIP */ \ 40, /* YEHAT_REBEL_SHIP */ \ 0, /* URQUAN_PROBE_SHIP */ // How many ships will an encounter consist of. // The first number specifies the minimum, the second the maximum. // The chance is 50% for each ship past the minimum to be present. #define RACE_ENCOUNTER_MAKEUP \ MAKE_BYTE (1, 5), /* ARILOU_SHIP */ \ 0, /* CHMMR_SHIP */ \ 0, /* HUMAN_SHIP */ \ MAKE_BYTE (1, 5), /* ORZ_SHIP */ \ MAKE_BYTE (1, 5), /* PKUNK_SHIP */ \ 0, /* SHOFIXTI_SHIP */ \ MAKE_BYTE (1, 5), /* SPATHI_SHIP */ \ MAKE_BYTE (1, 5), /* SUPOX_SHIP */ \ MAKE_BYTE (1, 5), /* THRADDASH_SHIP */ \ MAKE_BYTE (1, 5), /* UTWIG_SHIP */ \ MAKE_BYTE (1, 5), /* VUX_SHIP */ \ MAKE_BYTE (1, 5), /* YEHAT_SHIP */ \ MAKE_BYTE (1, 1), /* MELNORME_SHIP */ \ MAKE_BYTE (1, 5), /* DRUUGE_SHIP */ \ MAKE_BYTE (1, 5), /* ILWRATH_SHIP */ \ MAKE_BYTE (1, 5), /* MYCON_SHIP */ \ MAKE_BYTE (1, 1), /* SLYLANDRO_SHIP */ \ MAKE_BYTE (1, 5), /* UMGAH_SHIP */ \ MAKE_BYTE (1, 5), /* URQUAN_SHIP */ \ MAKE_BYTE (1, 5), /* ZOQFOTPIK_SHIP */ \ 0, /* SYREEN_SHIP */ \ MAKE_BYTE (1, 5), /* BLACK_URQUAN_SHIP */ \ MAKE_BYTE (1, 5), /* YEHAT_REBEL_SHIP */ #define RACE_COLORS \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x10), 0x53), /* ARILOU_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00), /* CHMMR_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x01, 0x1f), 0x4D), /* HUMAN_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x0E, 0x00, 0x0E), 0x36), /* ORZ_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x06, 0x08), 0x62), /* PKUNK_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00), /* SHOFIXTI_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x0C, 0x05, 0x00), 0x76), /* SPATHI_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x0C, 0x05, 0x00), 0x76), /* SUPOX_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x06, 0x08), 0x62), /* THRADDASH_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x06, 0x08), 0x62), /* UTWIG_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x10), 0x53), /* VUX_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x00, 0x11), 0x3D), /* YEHAT_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x06, 0x08), 0x62), /* MELNORME_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D), /* DRUUGE_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x0E, 0x00, 0x0E), 0x36), /* ILWRATH_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x0E, 0x00, 0x0E), 0x36), /* MYCON_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x0C, 0x05, 0x00), 0x76), /* SLYLANDRO_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x00, 0x11), 0x3D), /* UMGAH_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x08, 0x00), 0x6E), /* URQUAN_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D), /* ZOQFOTPIK_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00), /* SYREEN_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x06, 0x06, 0x06), 0x20), /* BLACK_URQUAN_SHIP */ \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x07, 0x1F), 0x39), /* YEHAT_REBEL_SHIP */ #define RADAR_SCAN_WIDTH (UNIT_SCREEN_WIDTH * NUM_RADAR_SCREENS) #define RADAR_SCAN_HEIGHT (UNIT_SCREEN_HEIGHT * NUM_RADAR_SCREENS) // Hyperspace coordinates of the naturally occuring portal into QuasiSpace #define ARILOU_SPACE_X 438 #define ARILOU_SPACE_Y 6372 // QuasiSpace coordinates of the same portal #define QUASI_SPACE_X 5000 #define QUASI_SPACE_Y 5000 // QuasiSpace coordinates of the Arilou home world #define ARILOU_HOME_X (QUASI_SPACE_X + ((RADAR_SCAN_WIDTH >> 1) * 3)) #define ARILOU_HOME_Y (QUASI_SPACE_Y + ((RADAR_SCAN_HEIGHT >> 1) * 3)) // Hyperspace coordinates of the Sol system // Should be the same as in plandata.c #define SOL_X 1752 #define SOL_Y 1450 extern BOOLEAN InitKernel (void); extern void DrawCaptainsWindow (STARSHIPPTR StarShipPtr); extern BOOLEAN GetNextStarShip (STARSHIPPTR LastStarShipPtr, COUNT which_side); extern HSTARSHIP GetEncounterStarShip (STARSHIPPTR LastStarShipPtr, COUNT which_player); extern void DrawArmadaPickShip (BOOLEAN draw_salvage_frame, PRECT pPickRect); extern BOOLEAN load_animation (PFRAME pixarray, DWORD big_res, DWORD med_res, DWORD sml_res); extern BOOLEAN free_image (PFRAME pixarray); extern void NotifyOthers (COUNT which_race, BYTE target_loc); #endif /* _RACES_H */ uqm-0.6.2/sc2/src/sc2code/gameinp.c0000600000175000017500000002535110543202103015367 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "controls.h" #include "init.h" #include "planets/planets.h" #include "settings.h" #include "sounds.h" #include "libs/inplib.h" #include "libs/timelib.h" #include "libs/threadlib.h" battle_summary_func ComputerInput, HumanInput[NUM_PLAYERS], NetworkInput; battle_summary_func PlayerInput[NUM_PLAYERS]; #define ACCELERATION_INCREMENT (ONE_SECOND / 12) #define MENU_REPEAT_DELAY (ONE_SECOND >> 1) typedef struct { BOOLEAN (*InputFunc) (PVOID pInputState); COUNT MenuRepeatDelay; } INPUT_STATE_DESC; typedef INPUT_STATE_DESC *PINPUT_STATE_DESC; /* These static variables are the values that are set by the controllers. */ typedef struct { DWORD key [NUM_TEMPLATES][NUM_KEYS]; DWORD menu [NUM_MENU_KEYS]; } MENU_ANNOTATIONS; CONTROL_TEMPLATE PlayerOne, PlayerTwo; CONTROLLER_INPUT_STATE CurrentInputState, PulsedInputState; static CONTROLLER_INPUT_STATE CachedInputState, OldInputState; static MENU_ANNOTATIONS RepeatDelays, Times; static DWORD GestaltRepeatDelay, GestaltTime; static BOOLEAN OldGestalt, CachedGestalt; static DWORD _max_accel, _min_accel, _step_accel; static BOOLEAN _gestalt_keys; int ExitState; static MENU_SOUND_FLAGS sound_0, sound_1; volatile CONTROLLER_INPUT_STATE ImmediateInputState; static void _clear_menu_state (void) { int i, j; for (i = 0; i < NUM_TEMPLATES; i++) { for (j = 0; j < NUM_KEYS; j++) { PulsedInputState.key[i][j] = 0; CachedInputState.key[i][j] = 0; } } for (i = 0; i < NUM_MENU_KEYS; i++) { PulsedInputState.menu[i] = 0; CachedInputState.menu[i] = 0; } CachedGestalt = FALSE; } void ResetKeyRepeat (void) { DWORD initTime = GetTimeCounter (); int i, j; for (i = 0; i < NUM_TEMPLATES; i++) { for (j = 0; j < NUM_KEYS; j++) { RepeatDelays.key[i][j] = _max_accel; Times.key[i][j] = initTime; } } for (i = 0; i < NUM_MENU_KEYS; i++) { RepeatDelays.menu[i] = _max_accel; Times.menu[i] = initTime; } GestaltRepeatDelay = _max_accel; GestaltTime = initTime; } static void _check_for_pulse (int *current, int *cached, int *old, DWORD *accel, DWORD *newtime, DWORD *oldtime) { if (*cached && *old) { if (*newtime - *oldtime < *accel) { *current = 0; } else { *current = *cached; if (*accel > _min_accel) *accel -= _step_accel; if (*accel < _min_accel) *accel = _min_accel; *oldtime = *newtime; } } else { *current = *cached; *oldtime = *newtime; *accel = _max_accel; } } /* BUG: If a key from a currently unused control template is held, * this will affect the gestalt repeat rate. This isn't a problem * *yet*, but it will be once the user gets to define control * templates on his own --McM */ static void _check_gestalt (DWORD NewTime) { BOOLEAN CurrentGestalt; int i,j; OldGestalt = CachedGestalt; CachedGestalt = 0; CurrentGestalt = 0; for (i = 0; i < NUM_TEMPLATES; i++) { for (j = 0; j < NUM_KEYS; j++) { CachedGestalt |= ImmediateInputState.key[i][j]; CurrentGestalt |= PulsedInputState.key[i][j]; } } for (i = 0; i < NUM_MENU_KEYS; i++) { CachedGestalt |= ImmediateInputState.menu[i]; CurrentGestalt |= PulsedInputState.menu[i]; } if (OldGestalt && CachedGestalt) { if (NewTime - GestaltTime < GestaltRepeatDelay) { for (i = 0; i < NUM_TEMPLATES; i++) { for (j = 0; j < NUM_KEYS; j++) { PulsedInputState.key[i][j] = 0; } } for (i = 0; i < NUM_MENU_KEYS; i++) { PulsedInputState.menu[i] = 0; } } else { for (i = 0; i < NUM_TEMPLATES; i++) { for (j = 0; j < NUM_KEYS; j++) { PulsedInputState.key[i][j] = CachedInputState.key[i][j]; } } for (i = 0; i < NUM_MENU_KEYS; i++) { PulsedInputState.menu[i] = CachedInputState.menu[i]; } if (GestaltRepeatDelay > _min_accel) GestaltRepeatDelay -= _step_accel; if (GestaltRepeatDelay < _min_accel) GestaltRepeatDelay = _min_accel; GestaltTime = NewTime; } } else { for (i = 0; i < NUM_TEMPLATES; i++) { for (j = 0; j < NUM_KEYS; j++) { PulsedInputState.key[i][j] = CachedInputState.key[i][j]; } } for (i = 0; i < NUM_MENU_KEYS; i++) { PulsedInputState.menu[i] = CachedInputState.menu[i]; } GestaltTime = NewTime; GestaltRepeatDelay = _max_accel; } } void UpdateInputState (void) { DWORD NewTime; /* First, if the game is, in fact, paused, we stall until * unpaused. Every thread with control over game logic calls * UpdateInputState routinely, so we handle pause and exit * state updates here. */ if (GamePaused) PauseGame (); if (ExitRequested) { ConfirmExit (); } CurrentInputState = ImmediateInputState; OldInputState = CachedInputState; CachedInputState = ImmediateInputState; NewTime = GetTimeCounter (); if (_gestalt_keys) { _check_gestalt (NewTime); } else { int i, j; for (i = 0; i < NUM_TEMPLATES; i++) { for (j = 0; j < NUM_KEYS; j++) { _check_for_pulse (&PulsedInputState.key[i][j], &CachedInputState.key[i][j], &OldInputState.key[i][j], &RepeatDelays.key[i][j], &NewTime, &Times.key[i][j]); } } for (i = 0; i < NUM_MENU_KEYS; i++) { _check_for_pulse (&PulsedInputState.menu[i], &CachedInputState.menu[i], &OldInputState.menu[i], &RepeatDelays.menu[i], &NewTime, &Times.menu[i]); } } if (CurrentInputState.menu[KEY_PAUSE]) GamePaused = TRUE; if (CurrentInputState.menu[KEY_EXIT]) ExitRequested = TRUE; } void SetMenuRepeatDelay (DWORD min, DWORD max, DWORD step, BOOLEAN gestalt) { _min_accel = min; _max_accel = max; _step_accel = step; _gestalt_keys = gestalt; _clear_menu_state (); ResetKeyRepeat (); } void SetDefaultMenuRepeatDelay () { _min_accel = ACCELERATION_INCREMENT; _max_accel = MENU_REPEAT_DELAY; _step_accel = ACCELERATION_INCREMENT; _gestalt_keys = FALSE; _clear_menu_state (); ResetKeyRepeat (); } void FlushInputState (void) { _clear_menu_state (); } void DoInput (PVOID pInputState, BOOLEAN resetInput) { SetMenuRepeatDelay (ACCELERATION_INCREMENT, MENU_REPEAT_DELAY, ACCELERATION_INCREMENT, FALSE); if (resetInput) { TFB_ResetControls (); } do { MENU_SOUND_FLAGS input; TaskSwitch (); UpdateInputState (); #if DEMO_MODE || CREATE_JOURNAL if (ArrowInput != DemoInput) #endif { #if CREATE_JOURNAL JournalInput (InputState); #endif /* CREATE_JOURNAL */ } if (CurrentInputState.menu[KEY_EXIT]) ExitState = ConfirmExit (); input = MENU_SOUND_NONE; if (PulsedInputState.menu[KEY_MENU_UP]) input |= MENU_SOUND_UP; if (PulsedInputState.menu[KEY_MENU_DOWN]) input |= MENU_SOUND_DOWN; if (PulsedInputState.menu[KEY_MENU_LEFT]) input |= MENU_SOUND_LEFT; if (PulsedInputState.menu[KEY_MENU_RIGHT]) input |= MENU_SOUND_RIGHT; if (PulsedInputState.menu[KEY_MENU_SELECT]) input |= MENU_SOUND_SELECT; if (PulsedInputState.menu[KEY_MENU_CANCEL]) input |= MENU_SOUND_CANCEL; if (PulsedInputState.menu[KEY_MENU_SPECIAL]) input |= MENU_SOUND_SPECIAL; if (PulsedInputState.menu[KEY_MENU_PAGE_UP]) input |= MENU_SOUND_PAGEUP; if (PulsedInputState.menu[KEY_MENU_PAGE_DOWN]) input |= MENU_SOUND_PAGEDOWN; if (PulsedInputState.menu[KEY_MENU_DELETE]) input |= MENU_SOUND_DELETE; if (PulsedInputState.menu[KEY_MENU_BACKSPACE]) input |= MENU_SOUND_DELETE; if (MenuSounds && (pSolarSysState == 0 /* see if in menu */ || pSolarSysState->MenuState.CurState || pSolarSysState->MenuState.Initialized > 2) && (input & (sound_0 | sound_1)) #ifdef NEVER && !PLRPlaying ((MUSIC_REF)~0) #endif /* NEVER */ ) { SOUND S; S = MenuSounds; if (input & sound_1) S = SetAbsSoundIndex (S, MENU_SOUND_SUCCESS); PlaySoundEffect (S, 0, NotPositional (), NULL, 0); } } while ((*((PINPUT_STATE_DESC)pInputState)->InputFunc) (pInputState)); if (resetInput) { TFB_ResetControls (); } } void SetMenuSounds (MENU_SOUND_FLAGS s0, MENU_SOUND_FLAGS s1) { sound_0 = s0; sound_1 = s1; } void GetMenuSounds (MENU_SOUND_FLAGS *s0, MENU_SOUND_FLAGS *s1) { *s0 = sound_0; *s1 = sound_1; } /* These can really be refactored */ BATTLE_INPUT_STATE p1_combat_summary (COUNT player, STARSHIPPTR StarShipPtr) { BATTLE_INPUT_STATE InputState = 0; if (CurrentInputState.key[PlayerOne][KEY_UP]) InputState |= BATTLE_THRUST; if (CurrentInputState.key[PlayerOne][KEY_LEFT]) InputState |= BATTLE_LEFT; if (CurrentInputState.key[PlayerOne][KEY_RIGHT]) InputState |= BATTLE_RIGHT; if (CurrentInputState.key[PlayerOne][KEY_WEAPON]) InputState |= BATTLE_WEAPON; if (CurrentInputState.key[PlayerOne][KEY_SPECIAL]) InputState |= BATTLE_SPECIAL; if (CurrentInputState.key[PlayerOne][KEY_ESCAPE]) InputState |= BATTLE_ESCAPE; if (CurrentInputState.key[PlayerOne][KEY_DOWN]) InputState |= BATTLE_DOWN; (void) player; (void) StarShipPtr; return InputState; } BATTLE_INPUT_STATE p2_combat_summary (COUNT player, STARSHIPPTR StarShipPtr) { BATTLE_INPUT_STATE InputState = 0; if (CurrentInputState.key[PlayerTwo][KEY_UP]) InputState |= BATTLE_THRUST; if (CurrentInputState.key[PlayerTwo][KEY_LEFT]) InputState |= BATTLE_LEFT; if (CurrentInputState.key[PlayerTwo][KEY_RIGHT]) InputState |= BATTLE_RIGHT; if (CurrentInputState.key[PlayerTwo][KEY_WEAPON]) InputState |= BATTLE_WEAPON; if (CurrentInputState.key[PlayerTwo][KEY_SPECIAL]) InputState |= BATTLE_SPECIAL; if (CurrentInputState.key[PlayerTwo][KEY_DOWN]) InputState |= BATTLE_DOWN; (void) player; (void) StarShipPtr; return InputState; } BOOLEAN AnyButtonPress (BOOLEAN CheckSpecial) { int i, j; (void) CheckSpecial; // Ignored UpdateInputState (); for (i = 0; i < NUM_TEMPLATES; i++) { for (j = 0; j < NUM_KEYS; j++) { if (CurrentInputState.key[i][j]) return TRUE; } } for (i = 0; i < NUM_MENU_KEYS; i++) { if (CurrentInputState.menu[i]) return TRUE; } return FALSE; } BOOLEAN ConfirmExit (void) { DWORD old_max_accel, old_min_accel, old_step_accel; BOOLEAN old_gestalt_keys, result; old_max_accel = _max_accel; old_min_accel = _min_accel; old_step_accel = _step_accel; old_gestalt_keys = _gestalt_keys; SetDefaultMenuRepeatDelay (); result = DoConfirmExit (); SetMenuRepeatDelay (old_min_accel, old_max_accel, old_step_accel, old_gestalt_keys); return result; } uqm-0.6.2/sc2/src/sc2code/gameev.c0000600000175000017500000005142510543202103015214 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "gameev.h" #include "build.h" #include "clock.h" #include "encount.h" #include "globdata.h" #include "hyper.h" #include "libs/compiler.h" #include "libs/mathlib.h" static void arilou_entrance_event (void); static void arilou_exit_event (void); static void check_race_growth (void); static void black_urquan_genocide (void); static void pkunk_mission (void); static void thradd_mission (void); static void ilwrath_mission (void); static void utwig_supox_mission (void); static void mycon_mission (void); void AddInitialGameEvents (void) { AddEvent (RELATIVE_EVENT, 0, 1, 0, HYPERSPACE_ENCOUNTER_EVENT); AddEvent (ABSOLUTE_EVENT, 3, 17, START_YEAR, ARILOU_ENTRANCE_EVENT); AddEvent (RELATIVE_EVENT, 0, 0, YEARS_TO_KOHRAH_VICTORY, KOHR_AH_VICTORIOUS_EVENT); AddEvent (RELATIVE_EVENT, 0, 0, 0, SLYLANDRO_RAMP_UP); } void EventHandler (BYTE selector) { switch (selector) { case ARILOU_ENTRANCE_EVENT: arilou_entrance_event (); break; case ARILOU_EXIT_EVENT: arilou_exit_event (); break; case HYPERSPACE_ENCOUNTER_EVENT: check_race_growth (); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) check_hyperspace_encounter (); AddEvent (RELATIVE_EVENT, 0, 1, 0, HYPERSPACE_ENCOUNTER_EVENT); break; case KOHR_AH_VICTORIOUS_EVENT: if (GET_GAME_STATE (UTWIG_SUPOX_MISSION)) { AddEvent (RELATIVE_EVENT, 0, 0, 1, KOHR_AH_GENOCIDE_EVENT); break; } /* FALLTHROUGH */ case KOHR_AH_GENOCIDE_EVENT: if (!GET_GAME_STATE (KOHR_AH_FRENZY) && LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && CurStarDescPtr && CurStarDescPtr->Index == SAMATRA_DEFINED) AddEvent (RELATIVE_EVENT, 0, 7, 0, KOHR_AH_GENOCIDE_EVENT); else black_urquan_genocide (); break; case ADVANCE_PKUNK_MISSION: pkunk_mission (); break; case ADVANCE_THRADD_MISSION: thradd_mission (); break; case ZOQFOT_DISTRESS_EVENT: if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && CurStarDescPtr && CurStarDescPtr->Index == ZOQFOT_DEFINED) AddEvent (RELATIVE_EVENT, 0, 7, 0, ZOQFOT_DISTRESS_EVENT); else { SET_GAME_STATE (ZOQFOT_DISTRESS, 1); AddEvent (RELATIVE_EVENT, 6, 0, 0, ZOQFOT_DEATH_EVENT); } break; case ZOQFOT_DEATH_EVENT: if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && CurStarDescPtr && CurStarDescPtr->Index == ZOQFOT_DEFINED) AddEvent (RELATIVE_EVENT, 0, 7, 0, ZOQFOT_DEATH_EVENT); else if (GET_GAME_STATE (ZOQFOT_DISTRESS)) { HSTARSHIP hZoqFot; EXTENDED_SHIP_FRAGMENTPTR ZoqFotPtr; hZoqFot = GetStarShipFromIndex (&GLOBAL (avail_race_q), ZOQFOTPIK_SHIP); ZoqFotPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hZoqFot); ZoqFotPtr->ShipInfo.actual_strength = 0; ZoqFotPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); UnlockStarShip ( &GLOBAL (avail_race_q), hZoqFot); SET_GAME_STATE (ZOQFOT_DISTRESS, 2); } break; case SHOFIXTI_RETURN_EVENT: ActivateStarShip (SHOFIXTI_SHIP, 0); GLOBAL (CrewCost) -= 2; /* crew is not an issue anymore */ SET_GAME_STATE (CREW_PURCHASED0, 0); SET_GAME_STATE (CREW_PURCHASED1, 0); break; case ADVANCE_UTWIG_SUPOX_MISSION: utwig_supox_mission (); break; case SPATHI_SHIELD_EVENT: if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && CurStarDescPtr && CurStarDescPtr->Index == SPATHI_DEFINED) AddEvent (RELATIVE_EVENT, 0, 7, 0, SPATHI_SHIELD_EVENT); else { HSTARSHIP hSpathi; EXTENDED_SHIP_FRAGMENTPTR SpathiPtr; hSpathi = GetStarShipFromIndex ( &GLOBAL (avail_race_q), SPATHI_SHIP); SpathiPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hSpathi); if (SpathiPtr->ShipInfo.actual_strength) { ActivateStarShip (SPATHI_SHIP, -1); SET_GAME_STATE (SPATHI_SHIELDED_SELVES, 1); SpathiPtr->ShipInfo.actual_strength = 0; } UnlockStarShip (&GLOBAL (avail_race_q), hSpathi); } break; case ADVANCE_ILWRATH_MISSION: ilwrath_mission (); break; case ADVANCE_MYCON_MISSION: mycon_mission (); break; case ARILOU_UMGAH_CHECK: SET_GAME_STATE (ARILOU_CHECKED_UMGAH, 2); break; case YEHAT_REBEL_EVENT: { HSTARSHIP hRebel, hRoyalist; EXTENDED_SHIP_FRAGMENTPTR RebelPtr, RoyalistPtr; hRebel = GetStarShipFromIndex (&GLOBAL (avail_race_q), YEHAT_REBEL_SHIP); RebelPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hRebel); hRoyalist = GetStarShipFromIndex (&GLOBAL (avail_race_q), YEHAT_SHIP); RoyalistPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hRoyalist); RebelPtr->ShipInfo.actual_strength = RoyalistPtr->ShipInfo.actual_strength = RoyalistPtr->ShipInfo.actual_strength * 2 / 3; RebelPtr->ShipInfo.loc.x = 5150; RebelPtr->ShipInfo.loc.y = 0; UnlockStarShip (&GLOBAL (avail_race_q), hRoyalist); UnlockStarShip (&GLOBAL (avail_race_q), hRebel); ActivateStarShip (YEHAT_REBEL_SHIP, SPHERE_TRACKING); break; } case SLYLANDRO_RAMP_UP: if (!GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP)) { BYTE ramp_factor; ramp_factor = GET_GAME_STATE (SLYLANDRO_MULTIPLIER); if (++ramp_factor <= 4) { SET_GAME_STATE (SLYLANDRO_MULTIPLIER, ramp_factor); AddEvent (RELATIVE_EVENT, 0, 182, 0, SLYLANDRO_RAMP_UP); } } break; case SLYLANDRO_RAMP_DOWN: { BYTE ramp_factor; ramp_factor = GET_GAME_STATE (SLYLANDRO_MULTIPLIER); if (--ramp_factor) AddEvent (RELATIVE_EVENT, 0, 23, 0, SLYLANDRO_RAMP_DOWN); SET_GAME_STATE (SLYLANDRO_MULTIPLIER, ramp_factor); break; } } } void SetRaceDest (BYTE which_race, COORD x, COORD y, BYTE days_left, BYTE func_index) { HSTARSHIP hStarShip; EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; hStarShip = GetStarShipFromIndex (&GLOBAL (avail_race_q), which_race); TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip); TemplatePtr->ShipInfo.dest_loc.x = x; TemplatePtr->ShipInfo.dest_loc.y = y; TemplatePtr->ShipInfo.days_left = days_left; TemplatePtr->ShipInfo.func_index = func_index; UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } static void arilou_entrance_event (void) { SET_GAME_STATE (ARILOU_SPACE, OPENING); AddEvent (RELATIVE_EVENT, 0, 3, 0, ARILOU_EXIT_EVENT); } static void arilou_exit_event (void) { COUNT month_index, year_index; year_index = GLOBAL (GameClock.year_index); if ((month_index = GLOBAL (GameClock.month_index) % 12) == 0) ++year_index; ++month_index; SET_GAME_STATE (ARILOU_SPACE, CLOSING); AddEvent (ABSOLUTE_EVENT, month_index, 17, year_index, ARILOU_ENTRANCE_EVENT); } static void check_race_growth (void) { HSTARSHIP hStarShip, hNextShip; for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); hStarShip; hStarShip = hNextShip) { EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip); hNextShip = _GetSuccLink (TemplatePtr); if (TemplatePtr->ShipInfo.actual_strength && TemplatePtr->ShipInfo.actual_strength != (COUNT)~0) { SIZE delta_strength; delta_strength = (SBYTE)TemplatePtr->ShipInfo.energy_level; if (TemplatePtr->ShipInfo.growth_err_term <= TemplatePtr->ShipInfo.growth_fract) { if (delta_strength <= 0) --delta_strength; else ++delta_strength; } TemplatePtr->ShipInfo.growth_err_term -= TemplatePtr->ShipInfo.growth_fract; delta_strength += TemplatePtr->ShipInfo.actual_strength; if (delta_strength <= 0) { delta_strength = 0; TemplatePtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); } else if (delta_strength > MAX_FLEET_STRENGTH) delta_strength = MAX_FLEET_STRENGTH; TemplatePtr->ShipInfo.actual_strength = (COUNT)delta_strength; if (TemplatePtr->ShipInfo.actual_strength && TemplatePtr->ShipInfo.days_left) { TemplatePtr->ShipInfo.loc.x += (TemplatePtr->ShipInfo.dest_loc.x - TemplatePtr->ShipInfo.loc.x) / TemplatePtr->ShipInfo.days_left; TemplatePtr->ShipInfo.loc.y += (TemplatePtr->ShipInfo.dest_loc.y - TemplatePtr->ShipInfo.loc.y) / TemplatePtr->ShipInfo.days_left; if (--TemplatePtr->ShipInfo.days_left == 0 && TemplatePtr->ShipInfo.func_index != (BYTE) ~0) EventHandler (TemplatePtr->ShipInfo.func_index); } } UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } } static void black_urquan_genocide (void) { BYTE Index; long best_dist; SIZE best_dx, best_dy; HSTARSHIP hStarShip, hNextShip; HSTARSHIP hBlackUrquan; EXTENDED_SHIP_FRAGMENTPTR BlackUrquanPtr; hBlackUrquan = GetStarShipFromIndex ( &GLOBAL (avail_race_q), BLACK_URQUAN_SHIP); BlackUrquanPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hBlackUrquan); best_dist = -1; best_dx = SOL_X - BlackUrquanPtr->ShipInfo.loc.x; best_dy = SOL_Y - BlackUrquanPtr->ShipInfo.loc.y; for (Index = 0, hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); hStarShip; ++Index, hStarShip = hNextShip) { EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip); hNextShip = _GetSuccLink (TemplatePtr); if (Index != BLACK_URQUAN_SHIP && Index != URQUAN_SHIP && TemplatePtr->ShipInfo.actual_strength != (COUNT)~0) { SIZE dx, dy; dx = TemplatePtr->ShipInfo.loc.x - BlackUrquanPtr->ShipInfo.loc.x; dy = TemplatePtr->ShipInfo.loc.y - BlackUrquanPtr->ShipInfo.loc.y; if (dx == 0 && dy == 0) { // Arrived at the victim's home world. Cleanse it. TemplatePtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); TemplatePtr->ShipInfo.actual_strength = 0; } else if (TemplatePtr->ShipInfo.actual_strength) { long dist; dist = (long)dx * dx + (long)dy * dy; if (best_dist < 0 || dist < best_dist || Index == DRUUGE_SHIP) { best_dist = dist; best_dx = dx; best_dy = dy; if (Index == DRUUGE_SHIP) hNextShip = 0; } } } UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } if (best_dist < 0 && best_dx == 0 && best_dy == 0) { // All spheres of influence are gone - game over. GLOBAL (CurrentActivity) &= ~IN_BATTLE; GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; SET_GAME_STATE (KOHR_AH_KILLED_ALL, 1); } else { // Moving towards new race to cleanse. COUNT speed; if (best_dist < 0) best_dist = (long)best_dx * best_dx + (long)best_dy * best_dy; speed = square_root (best_dist) / 158; if (speed == 0) speed = 1; else if (speed > 255) speed = 255; SET_GAME_STATE (KOHR_AH_FRENZY, 1); SET_GAME_STATE (KOHR_AH_VISITS, 0); SET_GAME_STATE (KOHR_AH_REASONS, 0); SET_GAME_STATE (KOHR_AH_PLEAD, 0); SET_GAME_STATE (KOHR_AH_INFO, 0); SET_GAME_STATE (URQUAN_VISITS, 0); SetRaceDest (BLACK_URQUAN_SHIP, BlackUrquanPtr->ShipInfo.loc.x + best_dx, BlackUrquanPtr->ShipInfo.loc.y + best_dy, (BYTE)speed, KOHR_AH_GENOCIDE_EVENT); } UnlockStarShip (&GLOBAL (avail_race_q), hBlackUrquan); } static void pkunk_mission (void) { HSTARSHIP hPkunk; EXTENDED_SHIP_FRAGMENTPTR PkunkPtr; hPkunk = GetStarShipFromIndex (&GLOBAL (avail_race_q), PKUNK_SHIP); PkunkPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hPkunk); if (PkunkPtr->ShipInfo.actual_strength) { BYTE MissionState; MissionState = GET_GAME_STATE (PKUNK_MISSION); if (PkunkPtr->ShipInfo.days_left == 0 && MissionState) { if ((MissionState & 1) /* made it to Yehat space */ || (PkunkPtr->ShipInfo.loc.x == 4970 && PkunkPtr->ShipInfo.loc.y == 400)) PkunkPtr->ShipInfo.actual_strength = 0; else if (PkunkPtr->ShipInfo.loc.x == 502 && PkunkPtr->ShipInfo.loc.y == 401 && GET_GAME_STATE (PKUNK_ON_THE_MOVE)) { SET_GAME_STATE (PKUNK_ON_THE_MOVE, 0); AddEvent (RELATIVE_EVENT, 3, 0, 0, ADVANCE_PKUNK_MISSION); UnlockStarShip (&GLOBAL (avail_race_q), hPkunk); return; } } if (PkunkPtr->ShipInfo.actual_strength == 0) { SET_GAME_STATE (YEHAT_ABSORBED_PKUNK, 1); PkunkPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); ActivateStarShip (YEHAT_SHIP, SPHERE_TRACKING); } else { COORD x, y; if (!(MissionState & 1)) { x = 4970; y = 400; } else { x = 502; y = 401; } SET_GAME_STATE (PKUNK_ON_THE_MOVE, 1); SET_GAME_STATE (PKUNK_SWITCH, 0); SetRaceDest (PKUNK_SHIP, x, y, (BYTE)((365 >> 1) - PkunkPtr->ShipInfo.days_left), ADVANCE_PKUNK_MISSION); } SET_GAME_STATE (PKUNK_MISSION, MissionState + 1); } UnlockStarShip (&GLOBAL (avail_race_q), hPkunk); } static void thradd_mission (void) { BYTE MissionState; HSTARSHIP hThradd; EXTENDED_SHIP_FRAGMENTPTR ThraddPtr; hThradd = GetStarShipFromIndex (&GLOBAL (avail_race_q), THRADDASH_SHIP); ThraddPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hThradd); MissionState = GET_GAME_STATE (THRADD_MISSION); if (ThraddPtr->ShipInfo.actual_strength && MissionState < 3) { COORD x, y; if (MissionState < 2) { /* attacking */ x = 4879; y = 7201; } else { /* returning */ x = 2535; y = 8358; } if (MissionState == 1) { /* arrived at Kohr-Ah, engaging */ SIZE strength_loss; strength_loss = (SIZE)(ThraddPtr->ShipInfo.actual_strength >> 1); ThraddPtr->ShipInfo.energy_level = (BYTE)(-strength_loss / 14); ThraddPtr->ShipInfo.growth_fract = (BYTE)(((strength_loss % 14) << 8) / 14); ThraddPtr->ShipInfo.growth_err_term = 255 >> 1; } else { if (MissionState != 0) { /* stop losses */ ThraddPtr->ShipInfo.energy_level = 0; ThraddPtr->ShipInfo.growth_fract = 0; } } SetRaceDest (THRADDASH_SHIP, x, y, 14, ADVANCE_THRADD_MISSION); } ++MissionState; SET_GAME_STATE (THRADD_MISSION, MissionState); if (MissionState == 4 && GET_GAME_STATE (ILWRATH_FIGHT_THRADDASH)) { /* returned home - notify the Ilwrath */ AddEvent (RELATIVE_EVENT, 0, 0, 0, ADVANCE_ILWRATH_MISSION); } UnlockStarShip (&GLOBAL (avail_race_q), hThradd); } static void ilwrath_mission (void) { BYTE ThraddState; HSTARSHIP hIlwrath, hThradd; EXTENDED_SHIP_FRAGMENTPTR IlwrathPtr, ThraddPtr; hIlwrath = GetStarShipFromIndex (&GLOBAL (avail_race_q), ILWRATH_SHIP); IlwrathPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hIlwrath); hThradd = GetStarShipFromIndex (&GLOBAL (avail_race_q), THRADDASH_SHIP); ThraddPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hThradd); if (IlwrathPtr->ShipInfo.loc.x == ((2500 + 2535) >> 1) && IlwrathPtr->ShipInfo.loc.y == ((8070 + 8358) >> 1)) { IlwrathPtr->ShipInfo.actual_strength = ThraddPtr->ShipInfo.actual_strength = 0; IlwrathPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); ThraddPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); } else if (IlwrathPtr->ShipInfo.actual_strength) { if (!GET_GAME_STATE (ILWRATH_FIGHT_THRADDASH) && (IlwrathPtr->ShipInfo.dest_loc.x != 2500 || IlwrathPtr->ShipInfo.dest_loc.y != 8070)) { SetRaceDest (ILWRATH_SHIP, 2500, 8070, 90, ADVANCE_ILWRATH_MISSION); } else { #define MADD_LENGTH 128 SIZE strength_loss; if (IlwrathPtr->ShipInfo.days_left == 0) { /* arrived for battle */ SET_GAME_STATE (ILWRATH_FIGHT_THRADDASH, 1); SET_GAME_STATE (HELIX_UNPROTECTED, 1); strength_loss = (SIZE)IlwrathPtr->ShipInfo.actual_strength; IlwrathPtr->ShipInfo.energy_level = (BYTE)(-strength_loss / MADD_LENGTH); IlwrathPtr->ShipInfo.growth_fract = (BYTE)(((strength_loss % MADD_LENGTH) << 8) / MADD_LENGTH); SetRaceDest (ILWRATH_SHIP, (2500 + 2535) >> 1, (8070 + 8358) >> 1, MADD_LENGTH - 1, ADVANCE_ILWRATH_MISSION); strength_loss = (SIZE)ThraddPtr->ShipInfo.actual_strength; ThraddPtr->ShipInfo.energy_level = (BYTE)(-strength_loss / MADD_LENGTH); ThraddPtr->ShipInfo.growth_fract = (BYTE)(((strength_loss % MADD_LENGTH) << 8) / MADD_LENGTH); SET_GAME_STATE (THRADD_VISITS, 0); if (ThraddPtr->ShipInfo.ship_flags & GOOD_GUY) ActivateStarShip (THRADDASH_SHIP, -1); } ThraddState = GET_GAME_STATE (THRADD_MISSION); if (ThraddState == 0 || ThraddState > 3) { /* never went to Kohr-Ah or returned */ SetRaceDest (THRADDASH_SHIP, (2500 + 2535) >> 1, (8070 + 8358) >> 1, IlwrathPtr->ShipInfo.days_left + 1, (BYTE)~0); } else if (ThraddState < 3) { /* recall on the double */ SetRaceDest (THRADDASH_SHIP, 2535, 8358, 10, ADVANCE_THRADD_MISSION); SET_GAME_STATE (THRADD_MISSION, 3); } } } UnlockStarShip (&GLOBAL (avail_race_q), hThradd); UnlockStarShip (&GLOBAL (avail_race_q), hIlwrath); } static void utwig_supox_mission (void) { BYTE MissionState; HSTARSHIP hUtwig, hSupox; EXTENDED_SHIP_FRAGMENTPTR UtwigPtr, SupoxPtr; hUtwig = GetStarShipFromIndex (&GLOBAL (avail_race_q), UTWIG_SHIP); UtwigPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hUtwig); hSupox = GetStarShipFromIndex (&GLOBAL (avail_race_q), SUPOX_SHIP); SupoxPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hSupox); MissionState = GET_GAME_STATE (UTWIG_SUPOX_MISSION); if (UtwigPtr->ShipInfo.actual_strength && MissionState < 5) { if (MissionState == 1) { SIZE strength_loss; AddEvent (RELATIVE_EVENT, 0, (160 >> 1), 0, ADVANCE_UTWIG_SUPOX_MISSION); strength_loss = (SIZE)(UtwigPtr->ShipInfo.actual_strength >> 1); UtwigPtr->ShipInfo.energy_level = (BYTE)(-strength_loss / 160); UtwigPtr->ShipInfo.growth_fract = (BYTE)(((strength_loss % 160) << 8) / 160); UtwigPtr->ShipInfo.growth_err_term = 255 >> 1; strength_loss = (SIZE)(SupoxPtr->ShipInfo.actual_strength >> 1); if (strength_loss) { SupoxPtr->ShipInfo.energy_level = (BYTE)(-strength_loss / 160); SupoxPtr->ShipInfo.growth_fract = (BYTE)(((strength_loss % 160) << 8) / 160); SupoxPtr->ShipInfo.growth_err_term = 255 >> 1; } SET_GAME_STATE (UTWIG_WAR_NEWS, 0); SET_GAME_STATE (SUPOX_WAR_NEWS, 0); } else if (MissionState == 2) { AddEvent (RELATIVE_EVENT, 0, (160 >> 1), 0, ADVANCE_UTWIG_SUPOX_MISSION); ++MissionState; } else { COORD ux, uy, sx, sy; if (MissionState == 0) { ux = 7208; uy = 7000; sx = 6479; sy = 7541; } else { ux = 8534; uy = 8797; sx = 7468; sy = 9246; UtwigPtr->ShipInfo.energy_level = 0; UtwigPtr->ShipInfo.growth_fract = 0; SupoxPtr->ShipInfo.energy_level = 0; SupoxPtr->ShipInfo.growth_fract = 0; SET_GAME_STATE (UTWIG_WAR_NEWS, 0); SET_GAME_STATE (SUPOX_WAR_NEWS, 0); } SET_GAME_STATE (UTWIG_VISITS, 0); SET_GAME_STATE (UTWIG_INFO, 0); SET_GAME_STATE (SUPOX_VISITS, 0); SET_GAME_STATE (SUPOX_INFO, 0); SetRaceDest (UTWIG_SHIP, ux, uy, 21, ADVANCE_UTWIG_SUPOX_MISSION); SetRaceDest (SUPOX_SHIP, sx, sy, 21, (BYTE)~0); } } SET_GAME_STATE (UTWIG_SUPOX_MISSION, MissionState + 1); UnlockStarShip (&GLOBAL (avail_race_q), hSupox); UnlockStarShip (&GLOBAL (avail_race_q), hUtwig); } static void mycon_mission (void) { HSTARSHIP hMycon; EXTENDED_SHIP_FRAGMENTPTR MyconPtr; hMycon = GetStarShipFromIndex (&GLOBAL (avail_race_q), MYCON_SHIP); MyconPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hMycon); if (MyconPtr->ShipInfo.actual_strength) { if (MyconPtr->ShipInfo.energy_level) { // Head back. SET_GAME_STATE (MYCON_KNOW_AMBUSH, 1); SetRaceDest (MYCON_SHIP, 6392, 2200, 30, (BYTE)~0); MyconPtr->ShipInfo.energy_level = 0; MyconPtr->ShipInfo.growth_fract = 0; } else if (MyconPtr->ShipInfo.loc.x != 6858 || MyconPtr->ShipInfo.loc.y != 577) SetRaceDest (MYCON_SHIP, 6858, 577, 30, ADVANCE_MYCON_MISSION); // To Organon. else { // Endure losses at Organon. SIZE strength_loss; AddEvent (RELATIVE_EVENT, 0, 14, 0, ADVANCE_MYCON_MISSION); strength_loss = (SIZE)(MyconPtr->ShipInfo.actual_strength >> 1); MyconPtr->ShipInfo.energy_level = (BYTE)(-strength_loss / 14); MyconPtr->ShipInfo.growth_fract = (BYTE)(((strength_loss % 14) << 8) / 14); MyconPtr->ShipInfo.growth_err_term = 255 >> 1; } } UnlockStarShip (&GLOBAL (avail_race_q), hMycon); } uqm-0.6.2/sc2/src/sc2code/clock.c0000600000175000017500000002363710543202101015045 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "gameev.h" #include "globdata.h" #include "setup.h" #include "libs/compiler.h" #include "libs/gfxlib.h" #include "libs/tasklib.h" #include "libs/threadlib.h" #include "libs/log.h" #include "libs/misc.h" // the running of the game-clock is based on game framerates // *not* on the system (or translated) timer // and is hard-coded to the original 24 fps #define CLOCK_BASE_FRAMERATE 24 static int clock_task_func(void* data); static Mutex clock_mutex; static BOOLEAN IsLeapYear (COUNT year) { // every 4th year but not 100s yet still 400s return (year & 3) == 0 && ((year % 100) != 0 || (year % 400) == 0); } /* month is 1-based: 1=Jan, 2=Feb, etc. */ static BYTE DaysInMonth (COUNT month, COUNT year) { static const BYTE days_in_month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, }; if (month == 2 && IsLeapYear (year)) return 29; /* February, leap year */ return days_in_month[month - 1]; } static int clock_task_func(void* data) { BOOLEAN LastPilot; DWORD LastTime; DWORD cycle_index, delay_count; static const COLOR cycle_tab[] = { BUILD_COLOR (MAKE_RGB15 (0x0A, 0x14, 0x18), 0x5B), BUILD_COLOR (MAKE_RGB15 (0x06, 0x10, 0x16), 0x5C), BUILD_COLOR (MAKE_RGB15 (0x03, 0x0E, 0x14), 0x5D), BUILD_COLOR (MAKE_RGB15 (0x02, 0x0C, 0x11), 0x5E), BUILD_COLOR (MAKE_RGB15 (0x01, 0x0B, 0x0F), 0x5F), BUILD_COLOR (MAKE_RGB15 (0x01, 0x09, 0x0D), 0x60), BUILD_COLOR (MAKE_RGB15 (0x00, 0x07, 0x0B), 0x61), }; #define NUM_CYCLES (sizeof (cycle_tab) / sizeof (cycle_tab[0])) #define NUM_DELAYS (ONE_SECOND * 3 / 40) // 9 @ 120 ticks/second Task task = (Task) data; LastPilot = FALSE; LastTime = 0; cycle_index = delay_count = 0; while (GLOBAL (GameClock).day_in_ticks == 0 && !Task_ReadState (task, TASK_EXIT)) TaskSwitch (); while (!Task_ReadState (task, TASK_EXIT)) { BOOLEAN OnAutoPilot; DWORD TimeIn; /* use semaphore so that time passage * can be halted. (e.g. during battle * or communications) */ SetSemaphore (GLOBAL (GameClock.clock_sem)); TimeIn = GetTimeCounter (); if (GLOBAL (GameClock).tick_count <= 0 && (GLOBAL (GameClock).tick_count = GLOBAL (GameClock).day_in_ticks) > 0) { /* next day -- move the calendar */ if (++GLOBAL (GameClock).day_index > DaysInMonth ( GLOBAL (GameClock).month_index, GLOBAL (GameClock).year_index)) { GLOBAL (GameClock).day_index = 1; if (++GLOBAL (GameClock).month_index > 12) { GLOBAL (GameClock).month_index = 1; ++GLOBAL (GameClock).year_index; } } LockMutex (GraphicsLock); DrawStatusMessage (NULL_PTR); { HEVENT hEvent; while ((hEvent = GetHeadEvent ())) { EVENTPTR EventPtr; LockEvent (hEvent, &EventPtr); if (GLOBAL (GameClock).day_index != EventPtr->day_index || GLOBAL (GameClock).month_index != EventPtr->month_index || GLOBAL (GameClock).year_index != EventPtr->year_index) { UnlockEvent (hEvent); break; } RemoveEvent (hEvent); EventHandler (EventPtr->func_index); UnlockEvent (hEvent); FreeEvent (hEvent); } } UnlockMutex (GraphicsLock); } OnAutoPilot = (BOOLEAN)( (GLOBAL (autopilot.x) != ~0 && GLOBAL (autopilot.y) != ~0) || GLOBAL_SIS (FuelOnBoard) == 0 ); if (OnAutoPilot || OnAutoPilot != LastPilot) { DWORD num_ticks; LockMutex (GraphicsLock); num_ticks = GetTimeCounter () - LastTime; if (!OnAutoPilot) { DrawSISMessage (NULL_PTR); cycle_index = delay_count = 0; } else if (delay_count > num_ticks) { delay_count -= num_ticks; } else { if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT)) && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) { // 2002/11/30 this additional 'if' fixes autopilot indicator blinking on combat/starmap // TODO: is there a better (more exact) way of determining if player is in starmap menu or not? if (LOBYTE (GLOBAL (CurrentActivity)) != IN_ENCOUNTER && (!pMenuState || (pMenuState && pMenuState->InputFunc == DoFlagshipCommands))) { CONTEXT OldContext; OldContext = SetContext (OffScreenContext); SetContextForeGroundColor (cycle_tab[cycle_index]); DrawSISMessage ((UNICODE *)~0L); SetContext (OldContext); } } cycle_index = (cycle_index + 1) % NUM_CYCLES; delay_count = NUM_DELAYS; } UnlockMutex (GraphicsLock); LastPilot = OnAutoPilot; LastTime += num_ticks; } ClearSemaphore (GLOBAL (GameClock.clock_sem)); SleepThreadUntil (TimeIn + ONE_SECOND / 120); } FinishTask (task); return(0); } BOOLEAN InitGameClock (void) { if (!InitQueue (&GLOBAL (GameClock.event_q), NUM_EVENTS, sizeof (EVENT))) return (FALSE); clock_mutex = CreateMutex ("Clock Mutex", SYNC_CLASS_TOPLEVEL); GLOBAL (GameClock.month_index) = 2; GLOBAL (GameClock.day_index) = 17; GLOBAL (GameClock.year_index) = START_YEAR; /* Feb 17, START_YEAR */ GLOBAL (GameClock).tick_count = GLOBAL (GameClock).day_in_ticks = 0; SuspendGameClock (); if ((GLOBAL (GameClock.clock_task) = AssignTask (clock_task_func, 2048, "game clock")) == 0) return (FALSE); return (TRUE); } BOOLEAN UninitGameClock (void) { if (GLOBAL (GameClock.clock_task)) { ResumeGameClock (); ConcludeTask (GLOBAL (GameClock.clock_task)); GLOBAL (GameClock.clock_task) = 0; } DestroyMutex (clock_mutex); clock_mutex = NULL; UninitQueue (&GLOBAL (GameClock.event_q)); return (TRUE); } void SuspendGameClock (void) { if (!clock_mutex) { log_add (log_Fatal, "BUG: " "Attempted to suspend non-existent game clock"); #ifdef DEBUG explode (); #endif return; } LockMutex (clock_mutex); if (GameClockRunning ()) { SetSemaphore (GLOBAL (GameClock.clock_sem)); GLOBAL (GameClock.TimeCounter) = 0; } UnlockMutex (clock_mutex); } void ResumeGameClock (void) { if (!clock_mutex) { log_add (log_Fatal, "BUG: " "Attempted to resume non-existent game clock\n"); #ifdef DEBUG explode (); #endif return; } LockMutex (clock_mutex); if (!GameClockRunning ()) { GLOBAL (GameClock.TimeCounter) = GetTimeCounter (); ClearSemaphore (GLOBAL (GameClock.clock_sem)); } UnlockMutex (clock_mutex); } BOOLEAN GameClockRunning (void) { return ((BOOLEAN)(GLOBAL (GameClock.TimeCounter) != 0)); } void SetGameClockRate (COUNT seconds_per_day) { SIZE new_day_in_ticks, new_tick_count; SetSemaphore (GLOBAL (GameClock.clock_sem)); new_day_in_ticks = (SIZE)(seconds_per_day * CLOCK_BASE_FRAMERATE); if (GLOBAL (GameClock.day_in_ticks) == 0) new_tick_count = new_day_in_ticks; else if (GLOBAL (GameClock.tick_count) <= 0) new_tick_count = 0; else if ((new_tick_count = (SIZE)((DWORD)GLOBAL (GameClock.tick_count) * new_day_in_ticks / GLOBAL (GameClock.day_in_ticks))) == 0) new_tick_count = 1; GLOBAL (GameClock.day_in_ticks) = new_day_in_ticks; GLOBAL (GameClock.tick_count) = new_tick_count; ClearSemaphore (GLOBAL (GameClock.clock_sem)); } BOOLEAN ValidateEvent (EVENT_TYPE type, PCOUNT pmonth_index, PCOUNT pday_index, PCOUNT pyear_index) { COUNT month_index, day_index, year_index; month_index = *pmonth_index; day_index = *pday_index; year_index = *pyear_index; if (type == RELATIVE_EVENT) { month_index += GLOBAL (GameClock.month_index) - 1; year_index += GLOBAL (GameClock.year_index) + (month_index / 12); month_index = (month_index % 12) + 1; day_index += GLOBAL (GameClock.day_index); while (day_index > DaysInMonth (month_index, year_index)) { day_index -= DaysInMonth (month_index, year_index); if (++month_index > 12) { month_index = 1; ++year_index; } } *pmonth_index = month_index; *pday_index = day_index; *pyear_index = year_index; } // translation: return (BOOLEAN) !(date < GLOBAL (Gameclock.date)); return (BOOLEAN) (!(year_index < GLOBAL (GameClock.year_index) || (year_index == GLOBAL (GameClock.year_index) && (month_index < GLOBAL (GameClock.month_index) || (month_index == GLOBAL (GameClock.month_index) && day_index < GLOBAL (GameClock.day_index)))))); } HEVENT AddEvent (EVENT_TYPE type, COUNT month_index, COUNT day_index, COUNT year_index, BYTE func_index) { HEVENT hNewEvent; if (type == RELATIVE_EVENT && month_index == 0 && day_index == 0 && year_index == 0) EventHandler (func_index); else if (ValidateEvent (type, &month_index, &day_index, &year_index) && (hNewEvent = AllocEvent ())) { EVENTPTR EventPtr; LockEvent (hNewEvent, &EventPtr); EventPtr->day_index = (BYTE)day_index; EventPtr->month_index = (BYTE)month_index; EventPtr->year_index = year_index; EventPtr->func_index = func_index; UnlockEvent (hNewEvent); { HEVENT hEvent, hSuccEvent; for (hEvent = GetHeadEvent (); hEvent != 0; hEvent = hSuccEvent) { LockEvent (hEvent, &EventPtr); if (year_index < EventPtr->year_index || (year_index == EventPtr->year_index && (month_index < EventPtr->month_index || (month_index == EventPtr->month_index && day_index < EventPtr->day_index)))) { UnlockEvent (hEvent); break; } hSuccEvent = GetSuccEvent (EventPtr); UnlockEvent (hEvent); } InsertEvent (hNewEvent, hEvent); } return (hNewEvent); } return (0); } SIZE ClockTick (void) { return (--GLOBAL (GameClock.tick_count)); } uqm-0.6.2/sc2/src/sc2code/star3do.typ0000600000175000017500000000015110543202103015707 0ustar joeyjoeyTYPE KEY_CONFIG TYPE GFXRES TYPE FONTRES TYPE STRTAB TYPE SNDRES TYPE MUSICRES TYPE RES_INDEX TYPE CODE uqm-0.6.2/sc2/src/sc2code/menu.c0000600000175000017500000003471410543202101014714 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "commglue.h" #include "controls.h" #include "options.h" #include "setup.h" #include "gamestr.h" #include "libs/graphics/gfx_common.h" #include "libs/tasklib.h" #include "libs/log.h" extern Task flash_task; extern RECT flash_rect; static BYTE GetEndMenuState (BYTE BaseState); static BYTE GetBeginMenuState (BYTE BaseState); static BYTE FixMenuState (BYTE BadState); static BYTE NextMenuState (BYTE BaseState, BYTE CurState); static BYTE PreviousMenuState (BYTE BaseState, BYTE CurState); static BOOLEAN GetAlternateMenu (BYTE *BaseState, BYTE *CurState); static BYTE ConvertAlternateMenu (BYTE BaseState, BYTE NewState); /* Draw the blue background for PC Menu Text */ static void DrawPCMenuFrame (RECT *r) { SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0F, 0x0F, 0x0F), 0x00)); DrawRectangle (r); r->corner.x++; r->corner.y++; r->extent.height--; r->extent.width--; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x06, 0x06, 0x06), 0x00)); DrawRectangle (r); r->extent.height--; r->extent.width--; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x15), 0x00)); DrawFilledRectangle (r); } #define ALT_MANIFEST 0x80 #define ALT_EXIT_MENU0 0x81 static UNICODE pm_crew_str[128]; static UNICODE pm_fuel_str[128]; /* Actually display the menu text */ static void DrawPCMenu (BYTE beg_index, BYTE end_index, BYTE NewState, BYTE hilite, RECT *r) { #define PC_MENU_HEIGHT 8 BYTE pos; COUNT i; int num_items; FONT OldFont; TEXT t; UNICODE buf[256]; pos = beg_index + NewState; num_items = 1 + end_index - beg_index; r->corner.x -= 1; r->extent.width += 1; DrawFilledRectangle (r); if (num_items * PC_MENU_HEIGHT > r->extent.height) log_add (log_Error, "Warning, no room for all menu items!"); else r->corner.y += (r->extent.height - num_items * PC_MENU_HEIGHT) / 2; r->extent.height = num_items * PC_MENU_HEIGHT + 4; DrawPCMenuFrame (r); OldFont = SetContextFont (StarConFont); t.align = ALIGN_LEFT; t.baseline.x = r->corner.x + 2; t.baseline.y = r->corner.y + PC_MENU_HEIGHT -1; t.pStr = buf; t.CharCount = (COUNT)~0; r->corner.x++; r->extent.width -= 2; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x15, 0x15), 0x00)); for (i = beg_index; i <= end_index; i++) { utf8StringCopy (buf, sizeof (buf), (i == PM_FUEL) ? pm_fuel_str : (i == PM_CREW) ? pm_crew_str : GAME_STRING (MAINMENU_STRING_BASE + i)); if (hilite && pos == i) { SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x00)); r->corner.y = t.baseline.y - PC_MENU_HEIGHT + 2; r->extent.height = PC_MENU_HEIGHT - 1; DrawFilledRectangle (r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x00)); font_DrawText (&t); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x15, 0x15), 0x00)); } else font_DrawText (&t); t.baseline.y += PC_MENU_HEIGHT; } } /* Determine the last text item to display */ static BYTE GetEndMenuState (BYTE BaseState) { switch (BaseState) { case PM_SCAN: case PM_STARMAP: return PM_NAVIGATE; break; case PM_MIN_SCAN: return PM_LAUNCH_LANDER; break; case PM_SAVE_GAME: return PM_EXIT_MENU1; break; case PM_CONVERSE: return PM_SAVE_LOAD1; break; case PM_FUEL: return PM_EXIT_MENU2; break; case PM_CREW: return PM_EXIT_MENU3; break; case PM_SOUND_ON: return PM_EXIT_MENU4; break; case PM_NO_QUIT: return PM_YES_QUIT; break; case PM_ALT_SCAN: case PM_ALT_STARMAP: return PM_ALT_NAVIGATE; break; case PM_ALT_CARGO: return PM_ALT_EXITMENU0; break; case PM_ALT_MSCAN: return PM_ALT_EXITMENU1; break; } return BaseState; } static BYTE GetBeginMenuState (BYTE BaseState) { return BaseState; } /* Correct Menu State for cases where the Menu shouldn't move */ static BYTE FixMenuState (BYTE BadState) { switch (BadState) { case PM_SOUND_ON: if (GLOBAL (glob_flags) & SOUND_DISABLED) return (PM_SOUND_OFF); else return (PM_SOUND_ON); case PM_MUSIC_ON: if (GLOBAL (glob_flags) & MUSIC_DISABLED) return (PM_MUSIC_OFF); else return (PM_MUSIC_ON); case PM_CYBORG_OFF: return (PM_CYBORG_OFF + ((BYTE)(GLOBAL (glob_flags) & COMBAT_SPEED_MASK) >> COMBAT_SPEED_SHIFT)); } return (BadState); } /* Choose the next menu to hilight in the 'forward' direction */ static BYTE NextMenuState (BYTE BaseState, BYTE CurState) { BYTE NextState; BYTE AdjBase = BaseState; if (BaseState == PM_STARMAP) AdjBase--; switch (AdjBase + CurState) { case PM_SOUND_ON: case PM_SOUND_OFF: NextState = PM_MUSIC_ON; break; case PM_MUSIC_ON: case PM_MUSIC_OFF: NextState = PM_CYBORG_OFF; break; case PM_CYBORG_OFF: case PM_CYBORG_NORMAL: case PM_CYBORG_DOUBLE: case PM_CYBORG_SUPER: NextState = PM_CHANGE_CAPTAIN; break; default: NextState = AdjBase + CurState + 1; } if (NextState > GetEndMenuState (BaseState)) NextState = GetBeginMenuState (BaseState); return (FixMenuState (NextState) - AdjBase); } /* Choose the next menu to hilight in the 'back' direction */ BYTE PreviousMenuState (BYTE BaseState, BYTE CurState) { SWORD NextState; BYTE AdjBase = BaseState; if (BaseState == PM_STARMAP) AdjBase--; switch (AdjBase + CurState) { case PM_SOUND_OFF: NextState = PM_EXIT_MENU4; break; case PM_MUSIC_ON: case PM_MUSIC_OFF: NextState = PM_SOUND_ON; break; case PM_CYBORG_OFF: case PM_CYBORG_NORMAL: case PM_CYBORG_DOUBLE: case PM_CYBORG_SUPER: NextState = PM_MUSIC_ON; break; case PM_CHANGE_CAPTAIN: NextState = PM_CYBORG_OFF; break; default: NextState = AdjBase + CurState - 1; } if (NextState < GetBeginMenuState (BaseState)) NextState = GetEndMenuState (BaseState); return (FixMenuState ((BYTE)NextState) - AdjBase); } /* When using PC hierarchy, convert 3do->PC */ static BOOLEAN GetAlternateMenu (BYTE *BaseState, BYTE *CurState) { BYTE AdjBase = *BaseState; BYTE adj = 0; if (*BaseState == PM_STARMAP) { AdjBase--; adj = 1; } if (*CurState & 0x80) { switch (*CurState) { case ALT_MANIFEST: *BaseState = PM_ALT_SCAN + adj; *CurState = PM_ALT_MANIFEST - PM_ALT_SCAN - adj; return (TRUE); case ALT_EXIT_MENU0: *BaseState = PM_ALT_CARGO; *CurState = PM_ALT_EXITMENU0 - PM_ALT_CARGO; return (TRUE); } log_add (log_Error, "Unknown state combination: %d, %d", *BaseState, *CurState); return (FALSE); } else { switch (AdjBase + *CurState) { case PM_SCAN: *BaseState = PM_ALT_SCAN; *CurState = PM_ALT_SCAN - PM_ALT_SCAN; return (TRUE); case PM_STARMAP: *BaseState = PM_ALT_SCAN + adj; *CurState = PM_ALT_STARMAP - PM_ALT_SCAN - adj; return (TRUE); case PM_DEVICES: *BaseState = PM_ALT_CARGO; *CurState = PM_ALT_DEVICES - PM_ALT_CARGO; return (TRUE); case PM_CARGO: *BaseState = PM_ALT_CARGO; *CurState = PM_ALT_CARGO - PM_ALT_CARGO; return (TRUE); case PM_ROSTER: *BaseState = PM_ALT_CARGO; *CurState = PM_ALT_ROSTER - PM_ALT_CARGO; return (TRUE); case PM_SAVE_LOAD0: *BaseState = PM_ALT_SCAN + adj; *CurState = PM_ALT_SAVE0 - PM_ALT_SCAN - adj; return (TRUE); case PM_NAVIGATE: *BaseState = PM_ALT_SCAN + adj; *CurState = PM_ALT_NAVIGATE - PM_ALT_SCAN - adj; return (TRUE); case PM_MIN_SCAN: *BaseState = PM_ALT_MSCAN; *CurState = PM_ALT_MSCAN - PM_ALT_MSCAN; return (TRUE); case PM_ENE_SCAN: *BaseState = PM_ALT_MSCAN; *CurState = PM_ALT_ESCAN - PM_ALT_MSCAN; return (TRUE); case PM_BIO_SCAN: *BaseState = PM_ALT_MSCAN; *CurState = PM_ALT_BSCAN - PM_ALT_MSCAN; return (TRUE); case PM_EXIT_MENU0: *BaseState = PM_ALT_MSCAN; *CurState = PM_ALT_EXITMENU1 - PM_ALT_MSCAN; return (TRUE); case PM_AUTO_SCAN: *BaseState = PM_ALT_MSCAN; *CurState = PM_ALT_ASCAN - PM_ALT_MSCAN; return (TRUE); case PM_LAUNCH_LANDER: *BaseState = PM_ALT_MSCAN; *CurState = PM_ALT_DISPATCH - PM_ALT_MSCAN; return (TRUE); } return (FALSE); } } /* When using PC hierarchy, convert PC->3DO */ static BYTE ConvertAlternateMenu (BYTE BaseState, BYTE NewState) { switch (BaseState + NewState) { case PM_ALT_SCAN: return (PM_SCAN - PM_SCAN); case PM_ALT_STARMAP: return (PM_STARMAP - PM_SCAN); case PM_ALT_MANIFEST: return (ALT_MANIFEST); case PM_ALT_SAVE0: return (PM_SAVE_LOAD0 - PM_SCAN); case PM_ALT_NAVIGATE: return (PM_NAVIGATE - PM_SCAN); case PM_ALT_CARGO: return (PM_CARGO - PM_SCAN); case PM_ALT_DEVICES: return (PM_DEVICES - PM_SCAN); case PM_ALT_ROSTER: return (PM_ROSTER - PM_SCAN); case PM_ALT_EXITMENU0: return (ALT_EXIT_MENU0); case PM_ALT_MSCAN: return (PM_MIN_SCAN - PM_MIN_SCAN); case PM_ALT_ESCAN: return (PM_ENE_SCAN - PM_MIN_SCAN); case PM_ALT_BSCAN: return (PM_BIO_SCAN - PM_MIN_SCAN); case PM_ALT_ASCAN: return (PM_AUTO_SCAN - PM_MIN_SCAN); case PM_ALT_DISPATCH: return (PM_LAUNCH_LANDER - PM_MIN_SCAN); case PM_ALT_EXITMENU1: return (PM_EXIT_MENU0 - PM_MIN_SCAN); } return (NewState); } BOOLEAN DoMenuChooser (PMENU_STATE pMS, BYTE BaseState) { { BYTE NewState = pMS->CurState; BYTE OrigBase = BaseState; BOOLEAN useAltMenu = FALSE; if (optWhichMenu == OPT_PC) useAltMenu = GetAlternateMenu (&BaseState, &NewState); if (PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_UP]) NewState = PreviousMenuState (BaseState, NewState); else if (PulsedInputState.menu[KEY_MENU_RIGHT] || PulsedInputState.menu[KEY_MENU_DOWN]) NewState = NextMenuState (BaseState, NewState); else if (useAltMenu && PulsedInputState.menu[KEY_MENU_SELECT]) { NewState = ConvertAlternateMenu (BaseState, NewState); if (NewState == ALT_MANIFEST) { DrawMenuStateStrings (PM_ALT_CARGO, 0); pMS->CurState = PM_CARGO - PM_SCAN; return (TRUE); } if (NewState == ALT_EXIT_MENU0) { if (OrigBase == PM_SCAN) DrawMenuStateStrings (PM_ALT_SCAN, PM_ALT_MANIFEST - PM_ALT_SCAN); else DrawMenuStateStrings (PM_ALT_STARMAP, PM_ALT_MANIFEST - PM_ALT_STARMAP); pMS->CurState = ALT_MANIFEST; return (TRUE); } return (FALSE); } else return (FALSE); DrawMenuStateStrings (BaseState, NewState); if (useAltMenu) NewState = ConvertAlternateMenu (BaseState, NewState); pMS->CurState = NewState; return (TRUE); } } void DrawMenuStateStrings (BYTE beg_index, SWORD NewState) { BYTE end_index; RECT r; STAMP s; CONTEXT OldContext; BYTE hilite = 1; extern FRAME PlayFrame; if (NewState < 0) { NewState = - NewState; hilite = 0; } if (optWhichMenu == OPT_PC) { BYTE tmpState = (BYTE)NewState; GetAlternateMenu (&beg_index, &tmpState); NewState = tmpState; } if (beg_index == PM_STARMAP) NewState--; end_index = GetEndMenuState (beg_index); s.frame = 0; if (NewState <= end_index - beg_index) s.frame = SetAbsFrameIndex (PlayFrame, beg_index + NewState); LockMutex (GraphicsLock); OldContext = SetContext (StatusContext); GetContextClipRect (&r); s.origin.x = RADAR_X - r.corner.x; s.origin.y = RADAR_Y - r.corner.y; r.corner.x = s.origin.x - 1; r.corner.y = s.origin.y - 11; r.extent.width = RADAR_WIDTH + 2; BatchGraphics (); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x1D)); if (s.frame && optWhichMenu == OPT_PC) { if (beg_index == PM_CREW) sprintf (pm_crew_str, "%s(%d)", GAME_STRING (MAINMENU_STRING_BASE + PM_CREW), GLOBAL (CrewCost)); if (beg_index == PM_FUEL) sprintf (pm_fuel_str, "%s(%d)", GAME_STRING (MAINMENU_STRING_BASE + PM_FUEL), GLOBAL (FuelCost)); if (beg_index == PM_SOUND_ON) { end_index = beg_index + 5; switch (beg_index + NewState) { case PM_SOUND_ON: case PM_SOUND_OFF: NewState = 0; break; case PM_MUSIC_ON: case PM_MUSIC_OFF: NewState = 1; break; case PM_CYBORG_OFF: case PM_CYBORG_NORMAL: case PM_CYBORG_DOUBLE: case PM_CYBORG_SUPER: NewState = 2; break; case PM_CHANGE_CAPTAIN: NewState = 3; break; case PM_CHANGE_SHIP: NewState = 4; break; case PM_EXIT_MENU4: NewState = 5; break; } } if (beg_index == PM_NO_QUIT) { end_index = beg_index + 1; switch (beg_index + NewState) { case PM_NO_QUIT: NewState = 0; break; case PM_YES_QUIT: NewState = 1; break; } } r.extent.height = RADAR_HEIGHT + 11; DrawPCMenu (beg_index, end_index, (BYTE)NewState, hilite, &r); s.frame = 0; } else { if(optWhichMenu == OPT_PC) { r.corner.x -= 1; r.extent.width += 1; r.extent.height = RADAR_HEIGHT + 11; } else r.extent.height = 11; DrawFilledRectangle (&r); } if (s.frame) { DrawStamp (&s); switch (beg_index + NewState) { TEXT t; UNICODE buf[20]; case PM_CREW: t.baseline.x = s.origin.x + RADAR_WIDTH - 2; t.baseline.y = s.origin.y + RADAR_HEIGHT - 2; t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; t.pStr = buf; sprintf (buf, "%u", GLOBAL (CrewCost)); SetContextFont (TinyFont); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x1F, 0x00), 0x00)); font_DrawText (&t); break; case PM_FUEL: t.baseline.x = s.origin.x + RADAR_WIDTH - 2; t.baseline.y = s.origin.y + RADAR_HEIGHT - 2; t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; t.pStr = buf; sprintf (buf, "%u", GLOBAL (FuelCost)); SetContextFont (TinyFont); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x1F, 0x00), 0x00)); font_DrawText (&t); break; } } UnbatchGraphics (); if (flash_task && flash_rect.corner.x == RADAR_X && flash_rect.corner.y == RADAR_Y && flash_rect.extent.width == RADAR_WIDTH && flash_rect.extent.height == RADAR_HEIGHT) SetFlashRect (SFR_MENU_3DO, (FRAME)0); SetContext (OldContext); UnlockMutex (GraphicsLock); } uqm-0.6.2/sc2/src/sc2code/Makeinfo0000600000175000017500000000137510543202101015255 0ustar joeyjoeyuqm_SUBDIRS="comm libs planets ships" uqm_CFILES="battle.c border.c build.c cleanup.c clock.c cnctdlg.c collide.c comm.c commanim.c commglue.c confirm.c credits.c cyborg.c demo.c displist.c dummy.c encount.c fmv.c galaxy.c gameev.c gameinp.c gameopt.c gendef.c getchar.c globdata.c gravity.c gravwell.c grpinfo.c hyper.c init.c intel.c intro.c ipdisp.c load.c loadship.c master.c melee.c menu.c misc.c mouse_err.c oscill.c outfit.c pickmele.c pickship.c plandata.c process.c restart.c save.c settings.c setup.c setupmenu.c ship.c shipstat.c shipyard.c sis.c sounds.c starbase.c starcon.c starmap.c state.c status.c tactrans.c trans.c uqmdebug.c util.c velocity.c weapon.c" if [ -n "$uqm_NETPLAY" ]; then uqm_SUBDIRS="$uqm_SUBDIRS netplay" fi uqm-0.6.2/sc2/src/sc2code/colors.h0000600000175000017500000001235610543202101015254 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _COLORS_H #define _COLORS_H #if 0 #define DEFAULT_COLOR_00 \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00) #define DEFAULT_COLOR_01 \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) #define DEFAULT_COLOR_02 \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x00), 0x02) #define DEFAULT_COLOR_03 \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03) #define DEFAULT_COLOR_04 \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) #define DEFAULT_COLOR_05 \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x14), 0x05) #define DEFAULT_COLOR_06 \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x00), 0x06) #define DEFAULT_COLOR_07 \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x07) #define DEFAULT_COLOR_08 \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08) #define DEFAULT_COLOR_09 \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09) #define DEFAULT_COLOR_0A \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x0A), 0x0A) #define DEFAULT_COLOR_0B \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B) #define DEFAULT_COLOR_0C \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C) #define DEFAULT_COLOR_0D \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x1F), 0x0D) #define DEFAULT_COLOR_0E \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x0E) #define DEFAULT_COLOR_0F \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) #endif #define BLACK_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00) #define LTGRAY_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x14, 0x14), 0x07) #define DKGRAY_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08) #define VDKGRAY_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x06, 0x06, 0x06), 0x00) #define WHITE_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F) #define NORMAL_ILLUMINATED_COLOR \ WHITE_COLOR #define NORMAL_SHADOWED_COLOR \ DKGRAY_COLOR #define HIGHLIGHT_ILLUMINATED_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x0C) #define HIGHLIGHT_SHADOWED_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) #define MENU_BACKGROUND_COLOR \ LTGRAY_COLOR #define MENU_FOREGROUND_COLOR \ DKGRAY_COLOR #define MENU_TEXT_COLOR \ VDKGRAY_COLOR #define MENU_HIGHLIGHT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x0E) #define MENU_CURSOR_COLOR \ WHITE_COLOR #define STATUS_ILLUMINATED_COLOR \ WHITE_COLOR #define STATUS_SHADOWED_COLOR \ DKGRAY_COLOR #define STATUS_SHAPE_COLOR \ BLACK_COLOR #define STATUS_SHAPE_OUTLINE_COLOR \ WHITE_COLOR #define CONTROL_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) #define ALLIANCE_BACKGROUND_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) #define HIERARCHY_BACKGROUND_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x14, 0x00, 0x00), 0x04) #define ALLIANCE_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B) #define HIERARCHY_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E) #define ALLIANCE_BOX_HIGHLIGHT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) #define HIERARCHY_BOX_HIGHLIGHT_COLOR \ HIERARCHY_BACKGROUND_COLOR #define MESSAGE_BACKGROUND_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) #define MESSAGE_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E) // Not highlighted dialog options in comm. #define COMM_PLAYER_TEXT_NORMAL_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03) // Currently highlighted dialog option in comm. #define COMM_PLAYER_TEXT_HIGHLIGHT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x1A, 0x1A, 0x1A), 0x12) // Background color of the area containing the player's dialog options. #define COMM_PLAYER_BACKGROUND_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01) // "(In response to your statement)" #define COMM_RESPONSE_INTRO_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0C, 0x1F), 0x48) // Your dialog option after choosing it. #define COMM_FEEDBACK_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x12, 0x14, 0x4F), 0x44) // The background when reviewing the conversation history. #define COMM_HISTORY_BACKGROUND_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x05, 0x00), 0x00) // The text when reviewing the conversation history. #define COMM_HISTORY_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x10, 0x00), 0x6B) // The text "MORE" when reviewing the conversation history. #define COMM_MORE_TEXT_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x00, 0x17, 0x00), 0x00) // Default colors for System Dialog Boxes (DrawShadowedBox) #define SHADOWBOX_BACKGROUND_COLOR \ MENU_BACKGROUND_COLOR #define SHADOWBOX_MEDIUM_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19) #define SHADOWBOX_DARK_COLOR \ BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F) #endif /* _COLORS_H */ uqm-0.6.2/sc2/src/sc2code/fmv.h0000600000175000017500000000232510543202103014540 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _FMV_H #define _FMV_H #include "libs/compiler.h" extern void Logo (void); extern void SplashScreen (void (* DoProcessing)(DWORD TimeOut)); extern void Introduction (void); extern void Victory (void); #include "libs/sndlib.h" extern void DoShipSpin (COUNT index, MUSIC_REF hMusic); extern BOOLEAN DoFMV (const char *name, const char *loopname, BOOLEAN uninit); extern BOOLEAN ShowPresentation (STRING PresStr); extern BOOLEAN ShowPresentationFile (const char *name); #endif /* _FMV_H */ uqm-0.6.2/sc2/src/sc2code/util.h0000600000175000017500000000205110543202103014721 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _UTIL_H #define _UTIL_H #include "libs/compiler.h" #include "libs/gfxlib.h" extern void DrawStarConBox (PRECT pRect, SIZE BorderWidth, COLOR TopLeftColor, COLOR BottomRightColor, BOOLEAN FillInterior, COLOR InteriorColor); extern DWORD SeedRandomNumbers (void); extern void MouseError (void); #endif /* _UTIL_H */ uqm-0.6.2/sc2/src/sc2code/init.h0000600000175000017500000000177010543202100014713 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _INIT_H #define _INIT_H #include "libs/gfxlib.h" #define NUM_PLAYERS 2 #define NUM_SIDES 2 extern FRAME stars_in_space; extern BOOLEAN InitSpace (void); extern void UninitSpace (void); extern SIZE InitShips (void); extern void UninitShips (void); #endif /* _INIT_H */ uqm-0.6.2/sc2/src/sc2code/sis.c0000600000175000017500000011654610543202101014552 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "colors.h" #include "commglue.h" #include "encount.h" #include "gamestr.h" #include "options.h" #include "starbase.h" #include "setup.h" #include "state.h" #include "libs/graphics/gfx_common.h" #include "libs/tasklib.h" #include "libs/log.h" #include static const UNICODE *describeWeapon (BYTE moduleType); void RepairSISBorder (void) { RECT r; CONTEXT OldContext; OldContext = SetContext (ScreenContext); BatchGraphics (); r.corner.x = SIS_ORG_X - 1; r.corner.y = SIS_ORG_Y - 1; r.extent.width = 1; r.extent.height = SIS_SCREEN_HEIGHT + 2; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); r.corner.x += (SIS_SCREEN_WIDTH + 2) - 1; DrawFilledRectangle (&r); r.corner.x = SIS_ORG_X - 1; r.corner.y += (SIS_SCREEN_HEIGHT + 2) - 1; r.extent.width = SIS_SCREEN_WIDTH + 2; r.extent.height = 1; DrawFilledRectangle (&r); UnbatchGraphics (); SetContext (OldContext); } void ClearSISRect (BYTE ClearFlags) { RECT r; COLOR OldColor; CONTEXT OldContext; OldContext = SetContext (StatusContext); OldColor = SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); r.corner.x = 2; r.extent.width = STATUS_WIDTH - 4; BatchGraphics (); if (ClearFlags & DRAW_SIS_DISPLAY) { DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, UNDEFINED_DELTA); } if (ClearFlags & CLEAR_SIS_RADAR) { UnlockMutex (GraphicsLock); DrawMenuStateStrings ((BYTE)~0, 1); LockMutex (GraphicsLock); #ifdef NEVER r.corner.x = RADAR_X - 1; r.corner.y = RADAR_Y - 1; r.extent.width = RADAR_WIDTH + 2; r.extent.height = RADAR_HEIGHT + 2; DrawStarConBox (&r, 1, BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F), TRUE, BUILD_COLOR (MAKE_RGB15 (0x00, 0x0E, 0x00), 0x6C)); #endif /* NEVER */ } UnbatchGraphics (); SetContextForeGroundColor (OldColor); SetContext (OldContext); } void DrawSISTitle (UNICODE *pStr) { TEXT t; CONTEXT OldContext; t.baseline.x = SIS_TITLE_WIDTH >> 1; t.baseline.y = SIS_TITLE_HEIGHT - 2; t.align = ALIGN_CENTER; t.pStr = pStr; t.CharCount = (COUNT)~0; OldContext = SetContext (OffScreenContext); { RECT r; r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH - 57 + 1; r.corner.y = SIS_ORG_Y - SIS_TITLE_HEIGHT; r.extent.width = SIS_TITLE_WIDTH; r.extent.height = SIS_TITLE_HEIGHT - 1; SetContextFGFrame (Screen); SetContextClipRect (&r); } SetContextFont (TinyFont); BatchGraphics (); SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); ClearDrawable (); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33)); font_DrawText (&t); UnbatchGraphics (); SetContextClipRect (NULL_PTR); SetContext (OldContext); } void DrawHyperCoords (POINT universe) { UNICODE buf[100]; sprintf (buf, "%03u.%01u : %03u.%01u", universe.x / 10, universe.x % 10, universe.y / 10, universe.y % 10); DrawSISTitle (buf); } void DrawSISMessage (const UNICODE *pStr) { DrawSISMessageEx (pStr, -1, -1, DSME_NONE); } BOOLEAN DrawSISMessageEx (const UNICODE *pStr, SIZE CurPos, SIZE ExPos, COUNT flags) { UNICODE buf[256]; CONTEXT OldContext; TEXT t; RECT r; OldContext = SetContext (OffScreenContext); // prepare the context r.corner.x = SIS_ORG_X + 1; r.corner.y = SIS_ORG_Y - SIS_MESSAGE_HEIGHT; r.extent.width = SIS_MESSAGE_WIDTH; r.extent.height = SIS_MESSAGE_HEIGHT - 1; SetContextFGFrame (Screen); SetContextClipRect (&r); BatchGraphics (); SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); if (pStr == (UNICODE *)~0L) { if (GLOBAL_SIS (FuelOnBoard) == 0) pStr = GAME_STRING (NAVIGATION_STRING_BASE + 2); else pStr = GAME_STRING (NAVIGATION_STRING_BASE + 3); } else { if (pStr == 0) { switch (LOBYTE (GLOBAL (CurrentActivity))) { default: case IN_ENCOUNTER: buf[0] = '\0'; break; case IN_LAST_BATTLE: case IN_INTERPLANETARY: GetClusterName (CurStarDescPtr, buf); break; case IN_HYPERSPACE: utf8StringCopy (buf, sizeof (buf), GAME_STRING (NAVIGATION_STRING_BASE + (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1 ? 0 : 1))); break; } pStr = buf; } SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33)); } t.baseline.y = SIS_MESSAGE_HEIGHT - 2; t.pStr = pStr; t.CharCount = utf8StringCount(pStr); SetContextFont (TinyFont); if (flags & DSME_CLEARFR) { SetFlashRect (NULL_PTR, (FRAME)0); } if (CurPos < 0 && ExPos < 0) { // normal state ClearDrawable (); t.baseline.x = SIS_MESSAGE_WIDTH >> 1; t.align = ALIGN_CENTER; font_DrawText (&t); } else { // editing state int i; RECT text_r; BYTE char_deltas[MAX_DESC_CHARS]; PBYTE pchar_deltas; t.baseline.x = 3; t.align = ALIGN_LEFT; TextRect (&t, &text_r, char_deltas); if (text_r.extent.width + t.baseline.x + 2 >= r.extent.width) { // the text does not fit the input box size and so // will not fit when displayed later // disallow the change UnbatchGraphics (); SetContextClipRect (NULL_PTR); SetContext (OldContext); return (FALSE); } ClearDrawable (); if (CurPos >= 0 && CurPos <= t.CharCount) { // calc and draw the cursor RECT cur_r = text_r; for (i = CurPos, pchar_deltas = char_deltas; i > 0; --i) cur_r.corner.x += (SIZE)*pchar_deltas++; if (CurPos < t.CharCount) /* end of line */ --cur_r.corner.x; if (flags & DSME_BLOCKCUR) { // Use block cursor for keyboardless systems if (CurPos == t.CharCount) { // cursor at end-line -- use insertion point cur_r.extent.width = 1; } else if (CurPos + 1 == t.CharCount) { // extra pixel for last char margin cur_r.extent.width = (SIZE)*pchar_deltas + 2; } else { // normal mid-line char cur_r.extent.width = (SIZE)*pchar_deltas + 1; } } else { // Insertion point cursor cur_r.extent.width = 1; } cur_r.corner.y = 0; cur_r.extent.height = r.extent.height; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&cur_r); } SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33)); if (ExPos >= 0 && ExPos < t.CharCount) { // handle extra characters t.CharCount = ExPos; font_DrawText (&t); // print extra chars SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x12, 0x00, 0x12), 0x33)); for (i = ExPos, pchar_deltas = char_deltas; i > 0; --i) t.baseline.x += (SIZE)*pchar_deltas++; t.pStr = skipUTF8Chars (t.pStr, ExPos); t.CharCount = (COUNT)~0; font_DrawText (&t); } else { // just print the text font_DrawText (&t); } } if (flags & DSME_SETFR) { r.corner.x = r.corner.y = 0; SetFlashRect (&r, (FRAME)0); } UnbatchGraphics (); SetContextClipRect (NULL_PTR); SetContext (OldContext); return (TRUE); } void DateToString (unsigned char *buf, size_t bufLen, BYTE month_index, BYTE day_index, COUNT year_index) { snprintf (buf, bufLen, "%s %02d" STR_MIDDLE_DOT "%04d", GAME_STRING (MONTHS_STRING_BASE + month_index - 1), day_index, year_index); } void DrawStatusMessage (const UNICODE *pStr) { RECT r; TEXT t; UNICODE buf[128]; CONTEXT OldContext; OldContext = SetContext (StatusContext); GetContextClipRect (&r); SetContext (OffScreenContext); SetContextFGFrame (Screen); r.corner.x += 2; r.corner.y += 130; r.extent.width = STATUS_MESSAGE_WIDTH; r.extent.height = STATUS_MESSAGE_HEIGHT; SetContextClipRect (&r); BatchGraphics (); SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x08, 0x00), 0x6E)); ClearDrawable (); if (pStr == (UNICODE *)~0) { if (pMenuState == 0 && CommData.ConversationPhrases /* Melnorme shenanigans */ && cur_comm == MELNORME_CONVERSATION) sprintf (buf, "%u %s", MAKE_WORD ( GET_GAME_STATE (MELNORME_CREDIT0), GET_GAME_STATE (MELNORME_CREDIT1) ), GAME_STRING (STATUS_STRING_BASE + 0)); // "Cr" else if (GET_GAME_STATE (CHMMR_BOMB_STATE) < 2) sprintf (buf, "%u %s", GLOBAL_SIS (ResUnits), GAME_STRING (STATUS_STRING_BASE + 1)); // "RU" else sprintf (buf, "%s %s", (optWhichMenu == OPT_PC) ? GAME_STRING (STATUS_STRING_BASE + 2) : STR_INFINITY_SIGN, // "UNLIMITED" GAME_STRING (STATUS_STRING_BASE + 1)); // "RU" pStr = buf; } else if (pStr == 0) { DateToString (buf, sizeof buf, GLOBAL (GameClock.month_index), GLOBAL (GameClock.day_index), GLOBAL (GameClock.year_index)); pStr = buf; } t.baseline.x = STATUS_MESSAGE_WIDTH >> 1; t.baseline.y = STATUS_MESSAGE_HEIGHT - 1; t.align = ALIGN_CENTER; t.pStr = pStr; t.CharCount = (COUNT)~0; SetContextFont (TinyFont); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x10, 0x00), 0x6B)); font_DrawText (&t); UnbatchGraphics (); SetContextClipRect (NULL_PTR); SetContext (OldContext); } void DrawCaptainsName (void) { RECT r; TEXT t; CONTEXT OldContext; FONT OldFont; COLOR OldColor; OldContext = SetContext (StatusContext); OldFont = SetContextFont (TinyFont); OldColor = SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); r.corner.x = 2 + 1; r.corner.y = 10; r.extent.width = SHIP_NAME_WIDTH - 2; r.extent.height = SHIP_NAME_HEIGHT; DrawFilledRectangle (&r); t.baseline.x = (STATUS_WIDTH >> 1) - 1; t.baseline.y = r.corner.y + 6; t.align = ALIGN_CENTER; t.pStr = GLOBAL_SIS (CommanderName); t.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x16, 0x0B, 0x1F), 0x38)); font_DrawText (&t); SetContextForeGroundColor (OldColor); SetContextFont (OldFont); SetContext (OldContext); } void DrawFlagshipName (BOOLEAN InStatusArea) { RECT r; TEXT t; FONT OldFont; COLOR OldColor; CONTEXT OldContext; FRAME OldFontEffect; UNICODE buf[250]; if (InStatusArea) { OldContext = SetContext (StatusContext); OldFont = SetContextFont (StarConFont); r.corner.x = 2; r.corner.y = 20; r.extent.width = SHIP_NAME_WIDTH; r.extent.height = SHIP_NAME_HEIGHT; t.pStr = GLOBAL_SIS (ShipName); } else { OldContext = SetContext (SpaceContext); OldFont = SetContextFont (MicroFont); r.corner.x = 0; r.corner.y = 1; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SHIP_NAME_HEIGHT; t.pStr = buf; sprintf (buf, "%s %s", GAME_STRING (NAMING_STRING_BASE + 1), GLOBAL_SIS (ShipName)); // XXX: this will not work with UTF-8 strings strupr (buf); } OldFontEffect = SetContextFontEffect (NULL); OldColor = SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.y = r.corner.y + (SHIP_NAME_HEIGHT - InStatusArea); t.align = ALIGN_CENTER; t.CharCount = (COUNT)~0; if (optWhichFonts == OPT_PC) SetContextFontEffect (SetAbsFrameIndex (FontGradFrame, InStatusArea ? 0 : 3)); else SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x14, 0x0A, 0x00), 0x0C)); font_DrawText (&t); SetContextFontEffect (OldFontEffect); SetContextForeGroundColor (OldColor); SetContextFont (OldFont); SetContext (OldContext); } void DrawFlagshipStats (void) { RECT r; TEXT t; FONT OldFont; COLOR OldColor; FRAME OldFontEffect; CONTEXT OldContext; UNICODE buf[128]; SIZE leading; BYTE i; BYTE energy_regeneration, energy_wait, turn_wait; COUNT max_thrust; DWORD fuel; /* collect stats */ #define ENERGY_REGENERATION 1 #define ENERGY_WAIT 10 #define MAX_THRUST 10 #define TURN_WAIT 17 energy_regeneration = ENERGY_REGENERATION; energy_wait = ENERGY_WAIT; max_thrust = MAX_THRUST; turn_wait = TURN_WAIT; fuel = 10 * FUEL_TANK_SCALE; for (i = 0; i < NUM_MODULE_SLOTS; i++) { switch (GLOBAL_SIS (ModuleSlots[i])) { case FUEL_TANK: fuel += FUEL_TANK_CAPACITY; break; case HIGHEFF_FUELSYS: fuel += HEFUEL_TANK_CAPACITY; break; case DYNAMO_UNIT: energy_wait -= 2; if (energy_wait < 4) energy_wait = 4; break; case SHIVA_FURNACE: energy_regeneration++; break; } } for (i = 0; i < NUM_DRIVE_SLOTS; ++i) if (GLOBAL_SIS (DriveSlots[i]) == FUSION_THRUSTER) max_thrust += 2; for (i = 0; i < NUM_JET_SLOTS; ++i) if (GLOBAL_SIS (JetSlots[i]) == TURNING_JETS) turn_wait -= 2; /* END collect stats */ OldContext = SetContext (SpaceContext); OldFont = SetContextFont (StarConFont); OldFontEffect = SetContextFontEffect (NULL); GetContextFontLeading (&leading); /* we need room to play. full screen width, 4 lines tall */ r.corner.x = 0; r.corner.y = SIS_SCREEN_HEIGHT - (4 * leading); r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = (4 * leading); OldColor = SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); /* now that we've cleared out our playground, compensate for the fact that the leading is way more than is generally needed. */ leading -= 3; t.baseline.x = SIS_SCREEN_WIDTH / 6; //wild-assed guess, but it worked t.baseline.y = r.corner.y + leading + 3; t.align = ALIGN_RIGHT; t.CharCount = (COUNT)~0; SetContextFontEffect (SetAbsFrameIndex (FontGradFrame, 4)); t.pStr = GAME_STRING (FLAGSHIP_STRING_BASE + 0); // "nose:" font_DrawText (&t); t.baseline.y += leading; t.pStr = GAME_STRING (FLAGSHIP_STRING_BASE + 1); // "spread:" font_DrawText (&t); t.baseline.y += leading; t.pStr = GAME_STRING (FLAGSHIP_STRING_BASE + 2); // "side:" font_DrawText (&t); t.baseline.y += leading; t.pStr = GAME_STRING (FLAGSHIP_STRING_BASE + 3); // "tail:" font_DrawText (&t); t.baseline.x += 5; t.baseline.y = r.corner.y + leading + 3; t.align = ALIGN_LEFT; t.pStr = buf; sprintf (buf, "%-7.7s", describeWeapon (GLOBAL_SIS (ModuleSlots[15]))); font_DrawText (&t); t.baseline.y += leading; sprintf (buf, "%-7.7s", describeWeapon (GLOBAL_SIS (ModuleSlots[14]))); font_DrawText (&t); t.baseline.y += leading; sprintf (buf, "%-7.7s", describeWeapon (GLOBAL_SIS (ModuleSlots[13]))); font_DrawText (&t); t.baseline.y += leading; sprintf (buf, "%-7.7s", describeWeapon (GLOBAL_SIS (ModuleSlots[0]))); font_DrawText (&t); t.baseline.x = r.extent.width - 25; t.baseline.y = r.corner.y + leading + 3; t.align = ALIGN_RIGHT; SetContextFontEffect (SetAbsFrameIndex (FontGradFrame, 5)); t.pStr = GAME_STRING (FLAGSHIP_STRING_BASE + 4); // "maximum velocity:" font_DrawText (&t); t.baseline.y += leading; t.pStr = GAME_STRING (FLAGSHIP_STRING_BASE + 5); // "turning rate:" font_DrawText (&t); t.baseline.y += leading; t.pStr = GAME_STRING (FLAGSHIP_STRING_BASE + 6); // "combat energy:" font_DrawText (&t); t.baseline.y += leading; t.pStr = GAME_STRING (FLAGSHIP_STRING_BASE + 7); // "maximum fuel:" font_DrawText (&t); t.baseline.x = r.extent.width - 2; t.baseline.y = r.corner.y + leading + 3; t.pStr = buf; sprintf (buf, "%4u", max_thrust * 4); font_DrawText (&t); t.baseline.y += leading; sprintf (buf, "%4u", 1 + TURN_WAIT - turn_wait); font_DrawText (&t); t.baseline.y += leading; { unsigned int energy_per_10_sec = (((100 * ONE_SECOND * energy_regeneration) / ((1 + energy_wait) * BATTLE_FRAME_RATE)) + 5) / 10; sprintf (buf, "%2u.%1u", energy_per_10_sec / 10, energy_per_10_sec % 10); } font_DrawText (&t); t.baseline.y += leading; sprintf (buf, "%4u", (fuel / FUEL_TANK_SCALE)); font_DrawText (&t); SetContextFontEffect (OldFontEffect); SetContextForeGroundColor (OldColor); SetContextFont (OldFont); SetContext (OldContext); } static const UNICODE * describeWeapon (BYTE moduleType) { switch (moduleType) { case GUN_WEAPON: return GAME_STRING (FLAGSHIP_STRING_BASE + 8); // "gun" case BLASTER_WEAPON: return GAME_STRING (FLAGSHIP_STRING_BASE + 9); // "blaster" case CANNON_WEAPON: return GAME_STRING (FLAGSHIP_STRING_BASE + 10); // "cannon" case BOMB_MODULE_0: case BOMB_MODULE_1: case BOMB_MODULE_2: case BOMB_MODULE_3: case BOMB_MODULE_4: case BOMB_MODULE_5: return GAME_STRING (FLAGSHIP_STRING_BASE + 11); // "n/a" default: return GAME_STRING (FLAGSHIP_STRING_BASE + 12); // "none" } } void DrawLanders (void) { BYTE i; SIZE width; RECT r; STAMP s; CONTEXT OldContext; OldContext = SetContext (StatusContext); s.frame = IncFrameIndex (FlagStatFrame); GetFrameRect (s.frame, &r); i = GLOBAL_SIS (NumLanders); r.corner.x = (STATUS_WIDTH >> 1) - r.corner.x; s.origin.x = r.corner.x - (((r.extent.width * i) + (2 * (i - 1))) >> 1); s.origin.y = 29; width = r.extent.width + 2; r.extent.width = (r.extent.width * MAX_LANDERS) + (2 * (MAX_LANDERS - 1)) + 2; r.corner.x -= r.extent.width >> 1; r.corner.y += s.origin.y; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); while (i--) { DrawStamp (&s); s.origin.x += width; } SetContext (OldContext); } void DrawStorageBays (BOOLEAN Refresh) { BYTE i; RECT r; CONTEXT OldContext; OldContext = SetContext (StatusContext); r.extent.width = 2; r.extent.height = 4; r.corner.y = 123; if (Refresh) { r.extent.width = NUM_MODULE_SLOTS * (r.extent.width + 1); r.corner.x = (STATUS_WIDTH >> 1) - (r.extent.width >> 1); SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); r.extent.width = 2; } i = (BYTE)CountSISPieces (STORAGE_BAY); if (i) { COUNT j; r.corner.x = (STATUS_WIDTH >> 1) - ((i * (r.extent.width + 1)) >> 1); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); for (j = GLOBAL_SIS (TotalElementMass); j >= STORAGE_BAY_CAPACITY; j -= STORAGE_BAY_CAPACITY) { DrawFilledRectangle (&r); r.corner.x += r.extent.width + 1; --i; } r.extent.height = (4 * j + (STORAGE_BAY_CAPACITY - 1)) / STORAGE_BAY_CAPACITY; if (r.extent.height) { r.corner.y += 4 - r.extent.height; DrawFilledRectangle (&r); r.extent.height = 4 - r.extent.height; if (r.extent.height) { r.corner.y = 123; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x06, 0x06, 0x06), 0x20)); DrawFilledRectangle (&r); } r.corner.x += r.extent.width + 1; --i; } r.extent.height = 4; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x06, 0x06, 0x06), 0x20)); while (i--) { DrawFilledRectangle (&r); r.corner.x += r.extent.width + 1; } } SetContext (OldContext); } void GetGaugeRect (PRECT pRect, BOOLEAN IsCrewRect) { pRect->extent.width = 24; pRect->corner.x = (STATUS_WIDTH >> 1) - (pRect->extent.width >> 1); pRect->extent.height = 5; pRect->corner.y = IsCrewRect ? 117 : 38; } static void DrawPC_SIS (void) { TEXT t; RECT r; GetGaugeRect (&r, FALSE); t.baseline.x = STATUS_WIDTH >> 1; t.baseline.y = r.corner.y - 1; t.align = ALIGN_CENTER; t.CharCount = (COUNT)~0; SetContextFont (TinyFont); SetContextForeGroundColor (BLACK_COLOR); r.corner.y -= 6; r.corner.x--; r.extent.width += 2; DrawFilledRectangle (&r); SetContextFontEffect (SetAbsFrameIndex (FontGradFrame, 1)); t.pStr = GAME_STRING (STATUS_STRING_BASE + 3); // "FUEL" font_DrawText (&t); r.corner.y += 79; t.baseline.y += 79; DrawFilledRectangle (&r); SetContextFontEffect (SetAbsFrameIndex (FontGradFrame, 2)); t.pStr = GAME_STRING (STATUS_STRING_BASE + 4); // "CREW" font_DrawText (&t); SetContextFontEffect (NULL); r.corner.x = 2 + 1; r.corner.y = 3; r.extent.width = 58; r.extent.height = 7; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x02, 0x04, 0x1E), 0x38)); t.baseline.y = r.corner.y + 6; t.pStr = GAME_STRING (STATUS_STRING_BASE + 5); // "CAPTAIN" font_DrawText (&t); } void DeltaSISGauges (SIZE crew_delta, SIZE fuel_delta, int resunit_delta) { STAMP s; RECT r; TEXT t; UNICODE buf[60]; CONTEXT OldContext; if (crew_delta == 0 && fuel_delta == 0 && resunit_delta == 0) return; OldContext = SetContext (StatusContext); BatchGraphics (); if (crew_delta == UNDEFINED_DELTA) { COUNT i; s.origin.x = s.origin.y = 0; s.frame = FlagStatFrame; DrawStamp (&s); if (optWhichFonts == OPT_PC) DrawPC_SIS(); s.origin.x = 1; s.origin.y = 0; for (i = 0; i < NUM_DRIVE_SLOTS; ++i) { BYTE which_piece; if ((which_piece = GLOBAL_SIS (DriveSlots[i])) < EMPTY_SLOT) { s.frame = SetAbsFrameIndex ( FlagStatFrame, which_piece + 1 + 0 ); DrawStamp (&s); s.frame = IncFrameIndex (s.frame); DrawStamp (&s); } s.origin.y -= 3; } s.origin.y = 0; for (i = 0; i < NUM_JET_SLOTS; ++i) { BYTE which_piece; if ((which_piece = GLOBAL_SIS (JetSlots[i])) < EMPTY_SLOT) { s.frame = SetAbsFrameIndex ( FlagStatFrame, which_piece + 1 + 1 ); DrawStamp (&s); s.frame = IncFrameIndex (s.frame); DrawStamp (&s); } s.origin.y -= 3; } s.origin.y = 1; s.origin.x = 1; // This properly centers the modules. for (i = 0; i < NUM_MODULE_SLOTS; ++i) { BYTE which_piece; if ((which_piece = GLOBAL_SIS (ModuleSlots[i])) < EMPTY_SLOT) { s.frame = SetAbsFrameIndex ( FlagStatFrame, which_piece + 1 + 2 ); DrawStamp (&s); } s.origin.y -= 3; } { HSTARSHIP hStarShip, hNextShip; PPOINT pship_pos; POINT ship_pos[MAX_COMBAT_SHIPS] = { SUPPORT_SHIP_PTS }; UnlockMutex (GraphicsLock); for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), pship_pos = ship_pos; hStarShip; hStarShip = hNextShip, ++pship_pos) { SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip ); hNextShip = _GetSuccLink (StarShipPtr); s.origin.x = pship_pos->x; s.origin.y = pship_pos->y; s.frame = StarShipPtr->ShipInfo.icons; LockMutex (GraphicsLock); DrawStamp (&s); UnlockMutex (GraphicsLock); UnlockStarShip ( &GLOBAL (built_ship_q), hStarShip ); } LockMutex (GraphicsLock); } } t.baseline.x = STATUS_WIDTH >> 1; t.align = ALIGN_CENTER; t.pStr = buf; SetContextFont (TinyFont); if (crew_delta != 0) { if (crew_delta != UNDEFINED_DELTA) { COUNT CrewCapacity; if (crew_delta < 0 && GLOBAL_SIS (CrewEnlisted) <= (COUNT)-crew_delta) GLOBAL_SIS (CrewEnlisted) = 0; else if ((GLOBAL_SIS (CrewEnlisted) += crew_delta) > (CrewCapacity = GetCPodCapacity (NULL_PTR))) GLOBAL_SIS (CrewEnlisted) = CrewCapacity; } sprintf (buf, "%u", GLOBAL_SIS (CrewEnlisted)); GetGaugeRect (&r, TRUE); t.baseline.y = r.corner.y + r.extent.height; t.CharCount = (COUNT)~0; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x0E, 0x00), 0x6C)); font_DrawText (&t); } if (fuel_delta != 0) { COUNT old_coarse_fuel, new_coarse_fuel; if (fuel_delta == UNDEFINED_DELTA) old_coarse_fuel = (COUNT)~0; else { DWORD FuelCapacity; old_coarse_fuel = (COUNT)( GLOBAL_SIS (FuelOnBoard) / FUEL_TANK_SCALE ); if (fuel_delta < 0 && GLOBAL_SIS (FuelOnBoard) <= (DWORD)-fuel_delta) GLOBAL_SIS (FuelOnBoard) = 0; else if ((GLOBAL_SIS (FuelOnBoard) += fuel_delta) > (FuelCapacity = GetFTankCapacity (NULL_PTR))) GLOBAL_SIS (FuelOnBoard) = FuelCapacity; } new_coarse_fuel = (COUNT)( GLOBAL_SIS (FuelOnBoard) / FUEL_TANK_SCALE ); if (new_coarse_fuel != old_coarse_fuel) { sprintf (buf, "%u", new_coarse_fuel); GetGaugeRect (&r, FALSE); t.baseline.y = r.corner.y + r.extent.height; t.CharCount = (COUNT)~0; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C)); font_DrawText (&t); } } if (crew_delta == UNDEFINED_DELTA) { DrawFlagshipName (TRUE); DrawCaptainsName (); DrawLanders (); DrawStorageBays (FALSE); } if (resunit_delta != 0) { if (resunit_delta != UNDEFINED_DELTA) { if (resunit_delta < 0 && GLOBAL_SIS (ResUnits) <= (DWORD)-resunit_delta) GLOBAL_SIS (ResUnits) = 0; else GLOBAL_SIS (ResUnits) += resunit_delta; DrawStatusMessage ((UNICODE *)~0); } else { r.corner.x = 2; r.corner.y = 130; r.extent.width = STATUS_MESSAGE_WIDTH; r.extent.height = STATUS_MESSAGE_HEIGHT; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x08, 0x00), 0x6E)); DrawFilledRectangle (&r); if ((pMenuState == 0 && CommData.ConversationPhrases /* Melnorme shenanigans */ && cur_comm == MELNORME_CONVERSATION) || (pMenuState && (pMenuState->InputFunc == DoStarBase || pMenuState->InputFunc == DoOutfit || pMenuState->InputFunc == DoShipyard))) DrawStatusMessage ((UNICODE *)~0); else DrawStatusMessage (NULL_PTR); } } UnbatchGraphics (); SetContext (OldContext); } COUNT GetCrewCount (void) { return (GLOBAL_SIS (CrewEnlisted)); } COUNT GetCPodCapacity (PPOINT ppt) { COORD x; COUNT slot, capacity; x = 207; capacity = 0; slot = NUM_MODULE_SLOTS - 1; do { if (GLOBAL_SIS (ModuleSlots[slot]) == CREW_POD) { if (ppt && capacity <= GLOBAL_SIS (CrewEnlisted) && capacity + CREW_POD_CAPACITY > GLOBAL_SIS (CrewEnlisted)) { COUNT pod_remainder, which_row; static const COLOR crew_rows[] = { BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1E, 0x09), 0x65), BUILD_COLOR (MAKE_RGB15 (0x00, 0x1E, 0x00), 0x65), BUILD_COLOR (MAKE_RGB15 (0x00, 0x1B, 0x00), 0x65), BUILD_COLOR (MAKE_RGB15 (0x00, 0x18, 0x00), 0x65), BUILD_COLOR (MAKE_RGB15 (0x00, 0x15, 0x00), 0x65), BUILD_COLOR (MAKE_RGB15 (0x00, 0x12, 0x00), 0x65), BUILD_COLOR (MAKE_RGB15 (0x00, 0x10, 0x00), 0x65), BUILD_COLOR (MAKE_RGB15 (0x00, 0x0D, 0x00), 0x65), BUILD_COLOR (MAKE_RGB15 (0x00, 0x0A, 0x00), 0x65), BUILD_COLOR (MAKE_RGB15 (0x00, 0x07, 0x00), 0x65), }; pod_remainder = GLOBAL_SIS (CrewEnlisted) - capacity; ppt->x = x - ((pod_remainder % CREW_PER_ROW) << 1); which_row = pod_remainder / CREW_PER_ROW; ppt->y = 34 - (which_row << 1); if (optWhichFonts == OPT_PC) SetContextForeGroundColor (crew_rows[which_row]); else SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x05, 0x10, 0x05), 0x65) ); } capacity += CREW_POD_CAPACITY; } x -= SHIP_PIECE_OFFSET; } while (slot--); return (capacity); } COUNT GetSBayCapacity (PPOINT ppt) { COORD x; COUNT slot, capacity; x = 207 - 8; capacity = 0; slot = NUM_MODULE_SLOTS - 1; do { if (GLOBAL_SIS (ModuleSlots[slot]) == STORAGE_BAY) { if (ppt && capacity < GLOBAL_SIS (TotalElementMass) && capacity + STORAGE_BAY_CAPACITY >= GLOBAL_SIS (TotalElementMass)) { COUNT bay_remainder, which_row; static const COLOR color_bars[] = { BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F), BUILD_COLOR (MAKE_RGB15 (0x1C, 0x1C, 0x1C), 0x11), BUILD_COLOR (MAKE_RGB15 (0x18, 0x18, 0x18), 0x13), BUILD_COLOR (MAKE_RGB15 (0x15, 0x15, 0x15), 0x15), BUILD_COLOR (MAKE_RGB15 (0x12, 0x12, 0x12), 0x17), BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), BUILD_COLOR (MAKE_RGB15 (0x0D, 0x0D, 0x0D), 0x1B), BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x1D), BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F), BUILD_COLOR (MAKE_RGB15 (0x05, 0x05, 0x05), 0x21), }; bay_remainder = GLOBAL_SIS (TotalElementMass) - capacity; if ((which_row = bay_remainder / SBAY_MASS_PER_ROW) == 0) SetContextForeGroundColor (BLACK_COLOR); else SetContextForeGroundColor (color_bars[--which_row]); ppt->x = x; ppt->y = 34 - (which_row << 1); } capacity += STORAGE_BAY_CAPACITY; } x -= SHIP_PIECE_OFFSET; } while (slot--); return (capacity); } DWORD GetFTankCapacity (PPOINT ppt) { COORD x; COUNT slot; DWORD capacity; x = 200; capacity = FUEL_RESERVE; slot = NUM_MODULE_SLOTS - 1; do { if (GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK || GLOBAL_SIS (ModuleSlots[slot]) == HIGHEFF_FUELSYS) { COUNT volume; volume = GLOBAL_SIS (ModuleSlots[slot]) == FUEL_TANK ? FUEL_TANK_CAPACITY : HEFUEL_TANK_CAPACITY; if (ppt && capacity <= GLOBAL_SIS (FuelOnBoard) && capacity + volume > GLOBAL_SIS (FuelOnBoard)) { COUNT which_row; static const COLOR fuel_colors[] = { BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D), BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C), BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7F), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7E), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7D), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7C), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x18, 0x00), 0x79), }; which_row = (COUNT)( (GLOBAL_SIS (FuelOnBoard) - capacity) * MAX_FUEL_BARS / HEFUEL_TANK_CAPACITY ); ppt->x = x + 1; if (volume == FUEL_TANK_CAPACITY) ppt->y = 27 - which_row; else ppt->y = 30 - which_row; SetContextForeGroundColor (fuel_colors[which_row]); SetContextBackGroundColor (fuel_colors[which_row + 1]); } capacity += volume; } x -= SHIP_PIECE_OFFSET; } while (slot--); return (capacity); } COUNT CountSISPieces (BYTE piece_type) { COUNT i, num_pieces; num_pieces = 0; if (piece_type == FUSION_THRUSTER) { for (i = 0; i < NUM_DRIVE_SLOTS; ++i) { if (GLOBAL_SIS (DriveSlots[i]) == piece_type) ++num_pieces; } } else if (piece_type == TURNING_JETS) { for (i = 0; i < NUM_JET_SLOTS; ++i) { if (GLOBAL_SIS (JetSlots[i]) == piece_type) ++num_pieces; } } else { for (i = 0; i < NUM_MODULE_SLOTS; ++i) { if (GLOBAL_SIS (ModuleSlots[i]) == piece_type) ++num_pieces; } } return (num_pieces); } Task flash_task = 0; RECT flash_rect; static FRAME flash_frame; static FRAME flash_screen_frame = 0; static int flash_changed; Mutex flash_mutex = 0; // XXX: these are currently defined in libs/graphics/sdl/3do_getbody.c // they should be sorted out and cleaned up at some point extern void arith_frame_blit (FRAME srcFrame, RECT *rsrc, FRAME dstFrame, RECT *rdst, int num, int denom); static int flash_rect_func (void *data) { #define NORMAL_STRENGTH 4 #define NORMAL_F_STRENGTH 0 #define CACHE_SIZE 10 DWORD TimeIn, WaitTime; SIZE strength, fstrength, incr; RECT cached_rect, framesize_rect; FRAME cached_frame = 0; FRAME cached_screen_frame = 0; Task task = (Task)data; int cached[CACHE_SIZE]; STAMP cached_stamp[CACHE_SIZE]; int i; for (i = 0; i < CACHE_SIZE; i++) { cached[i] = 0; cached_stamp[i].frame = 0; } fstrength = NORMAL_F_STRENGTH; incr = 1; strength = NORMAL_STRENGTH; TimeIn = GetTimeCounter (); WaitTime = ONE_SECOND / 16; while (!Task_ReadState(task, TASK_EXIT)) { CONTEXT OldContext; LockMutex (flash_mutex); if (flash_changed) { RECT screen_rect; cached_rect = flash_rect; cached_frame = flash_frame; if (cached_screen_frame) DestroyDrawable (ReleaseDrawable (cached_screen_frame)); flash_changed = 0; // Wait for the flash_screen_frame to get initialized FlushGraphics (); GetFrameRect (flash_screen_frame, &screen_rect); cached_screen_frame = CaptureDrawable (CreateDrawable (WANT_PIXMAP, screen_rect.extent.width, screen_rect.extent.height, 1)); screen_rect.corner.x = screen_rect.corner.y = 0; arith_frame_blit (flash_screen_frame, &screen_rect, cached_screen_frame, NULL, 0, 0); UnlockMutex (flash_mutex); if (cached_frame) GetFrameRect (cached_frame, &framesize_rect); for (i = 0; i < CACHE_SIZE; i++) { cached[i] = 0; if(cached_stamp[i].frame) DestroyDrawable (ReleaseDrawable (cached_stamp[i].frame)); cached_stamp[i].frame = 0; } } else UnlockMutex (flash_mutex); if (cached_rect.extent.width) { STAMP *pStamp; if (cached_frame) { #define MIN_F_STRENGTH -3 #define MAX_F_STRENGTH 3 int num = 0, denom = 0; if ((fstrength += incr) > MAX_F_STRENGTH) { fstrength = MAX_F_STRENGTH - 1; incr = -1; } else if (fstrength < MIN_F_STRENGTH) { fstrength = MIN_F_STRENGTH + 1; incr = 1; } if (cached[fstrength - MIN_F_STRENGTH]) pStamp = &cached_stamp[fstrength - MIN_F_STRENGTH]; else { RECT tmp_rect = framesize_rect; pStamp = &cached_stamp[fstrength - MIN_F_STRENGTH]; cached[fstrength - MIN_F_STRENGTH] = 1; pStamp->frame = CaptureDrawable (CreateDrawable (WANT_PIXMAP, framesize_rect.extent.width, framesize_rect.extent.height, 1)); pStamp->origin.x = framesize_rect.corner.x; pStamp->origin.y = framesize_rect.corner.y; tmp_rect.corner.x = 0; tmp_rect.corner.y = 0; if (fstrength != NORMAL_F_STRENGTH) { arith_frame_blit (cached_frame, &tmp_rect, pStamp->frame, NULL, fstrength > 0 ? fstrength : -fstrength, 16); if (fstrength < 0) { num = -8; denom = 8; } else { num = 8; denom = -8; } } arith_frame_blit (cached_screen_frame, &framesize_rect, pStamp->frame, &tmp_rect, num, denom); } } else { #define MIN_STRENGTH 4 #define MAX_STRENGTH 6 if ((strength += 2) > MAX_STRENGTH) strength = MIN_STRENGTH; if (cached[strength - MIN_STRENGTH]) pStamp = &cached_stamp[strength - MIN_STRENGTH]; else { RECT tmp_rect = cached_rect; pStamp = &cached_stamp[strength - MIN_STRENGTH]; cached[strength - MIN_STRENGTH] = 1; pStamp->frame = CaptureDrawable (CreateDrawable (WANT_PIXMAP, cached_rect.extent.width, cached_rect.extent.height, 1)); pStamp->origin.x = 0; pStamp->origin.y = 0; tmp_rect.corner.x = 0; tmp_rect.corner.y = 0; arith_frame_blit (cached_screen_frame, &tmp_rect, pStamp->frame, &tmp_rect, 4, 4); if (strength != 4) arith_frame_blit (cached_screen_frame, &tmp_rect, pStamp->frame, &tmp_rect, strength, 4); } } LockMutex (GraphicsLock); OldContext = SetContext (ScreenContext); SetContextClipRect (&cached_rect); // flash changed_can't be modified while GraphicSem is held if (! flash_changed) DrawStamp (pStamp); SetContextClipRect (NULL_PTR); // this will flush whatever SetContext (OldContext); UnlockMutex (GraphicsLock); } FlushGraphics (); SleepThreadUntil (TimeIn + WaitTime); TimeIn = GetTimeCounter (); } { if (cached_screen_frame) DestroyDrawable (ReleaseDrawable (cached_screen_frame)); for (i = 0; i < CACHE_SIZE; i++) { if(cached_stamp[i].frame) DestroyDrawable (ReleaseDrawable (cached_stamp[i].frame)); } } LockMutex (flash_mutex); flash_task = 0; UnlockMutex (flash_mutex); FinishTask (task); return(0); } void SetFlashRect (PRECT pRect, FRAME f) { RECT clip_r, temp_r, flash_rect1, old_r; CONTEXT OldContext; FRAME old_f; int create_flash = 0; if (! flash_mutex) flash_mutex = CreateMutex ("FlashRect Lock", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); old_r = flash_rect; old_f = flash_frame; flash_rect1 = flash_rect; if (pRect != SFR_MENU_3DO && pRect != SFR_MENU_ANY) { GetContextClipRect (&clip_r); OldContext = SetContext (ScreenContext); } else { //Don't flash when using the PC menu if (optWhichMenu == OPT_PC && pRect != SFR_MENU_ANY) { OldContext = SetContext (ScreenContext); pRect = 0; } else { OldContext = SetContext (StatusContext); GetContextClipRect (&clip_r); pRect = &temp_r; temp_r.corner.x = RADAR_X - clip_r.corner.x; temp_r.corner.y = RADAR_Y - clip_r.corner.y; temp_r.extent.width = RADAR_WIDTH; temp_r.extent.height = RADAR_HEIGHT; SetContext (ScreenContext); } } if (pRect == 0 || pRect->extent.width == 0) { flash_rect1.extent.width = 0; if (flash_task) { UnlockMutex (GraphicsLock); ConcludeTask (flash_task); LockMutex (GraphicsLock); } } else { flash_rect1 = *pRect; flash_rect1.corner.x += clip_r.corner.x; flash_rect1.corner.y += clip_r.corner.y; create_flash = 1; } LockMutex (flash_mutex); flash_frame = f; flash_rect = flash_rect1; if (old_r.extent.width && (old_r.extent.width != flash_rect.extent.width || old_r.extent.height != flash_rect.extent.height || old_r.corner.x != flash_rect.corner.x || old_r.corner.y != flash_rect.corner.y || old_f != flash_frame)) { if (flash_screen_frame) { STAMP old_s; old_s.origin.x = old_r.corner.x; old_s.origin.y = old_r.corner.y; old_s.frame = flash_screen_frame; DrawStamp (&old_s); DestroyDrawable (ReleaseDrawable (flash_screen_frame)); flash_screen_frame = 0; } else log_add (log_Debug, "Couldn't locate flash_screen_rect"); } if (flash_rect.extent.width) { if (flash_screen_frame) DestroyDrawable (ReleaseDrawable (flash_screen_frame)); flash_screen_frame = CaptureDrawable (LoadDisplayPixmap (&flash_rect, (FRAME)0)); } flash_changed = 1; UnlockMutex (flash_mutex); // we create the thread after the LoadIntoExtraScreen // so there is no race between the FlushGraphics in flash_task // and the Enqueue in LoadIntoExtraScreen if (create_flash && flash_task == 0) { flash_task = AssignTask (flash_rect_func, 2048, "flash rectangle"); } SetContext (OldContext); } void SaveFlagshipState (void) { if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { // Player is in HyperSpace or QuasiSpace. // Update 'GLOBAL (ShipStamp.frame)' to the direction the flagship // is facing. HELEMENT hElement, hNextElement; // Find the flagship element. for (hElement = GetHeadElement (); hElement != 0; hElement = hNextElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); hNextElement = GetSuccElement (ElementPtr); if (ElementPtr->state_flags & PLAYER_SHIP) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); GLOBAL (ShipStamp.frame) = (FRAME)MAKE_DWORD ( StarShipPtr->ShipFacing + 1, 0); hNextElement = 0; } UnlockElement (hElement); } } else if (pSolarSysState) { // Player is in a solar system. UWORD index1, index2; FRAME frame; frame = GLOBAL (ShipStamp.frame); if (pSolarSysState->MenuState.Initialized < 3) { index1 = GetFrameIndex (frame) + 1; if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) { index2 = 0; } else { index2 = (UWORD)(pSolarSysState->pBaseDesc->pPrevDesc - pSolarSysState->PlanetDesc + 1); GLOBAL (ip_location) = pSolarSysState->SunDesc[0].location; } } else { // In orbit around a planet. // Update the starinfo.dat file if necessary. if (GET_GAME_STATE (PLANETARY_CHANGE)) { PutPlanetInfo (); SET_GAME_STATE (PLANETARY_CHANGE, 0); } index1 = LOWORD (frame); index2 = 1; if (pSolarSysState->pOrbitalDesc != pSolarSysState->pBaseDesc->pPrevDesc) index2 += pSolarSysState->pOrbitalDesc - pSolarSysState->pBaseDesc + 1; index2 = MAKE_WORD (HIWORD (frame), index2); } GLOBAL (ShipStamp.frame) = (FRAME)MAKE_DWORD (index1, index2); } } uqm-0.6.2/sc2/src/sc2code/nameref.h0000600000175000017500000000261510543202101015365 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _NAMEREF_H #define _NAMEREF_H #include "restypes.h" #define LoadCodeRes LoadCodeResInstance #define LoadGraphic LoadGraphicInstance #define LoadFont LoadGraphicInstance #define LoadColorMap LoadColorMapInstance #define LoadStringTable LoadStringTableInstance #define LoadSound LoadSoundInstance #define LoadMusic LoadMusicInstance #define INIT_INSTANCES() do \ { \ InstallGraphicResTypes (GFXRES, FONTRES); \ InstallStringTableResType (STRTAB); \ InstallAudioResTypes (SNDRES, MUSICRES); \ InstallCodeResType (CODE); \ } while (0) #define UNINIT_INSTANCES() #endif /* _NAMEREF_H */ uqm-0.6.2/sc2/src/sc2code/respkg.h0000600000175000017500000001550510543202101015245 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ enum { INIT_PACKAGE = 1, TITLE_PACKAGE, ARILOU_SHIP_PACKAGE, CHMMR_SHIP_PACKAGE, EARTHLING_SHIP_PACKAGE, ORZ_SHIP_PACKAGE, PKUNK_SHIP_PACKAGE, SHOFIXTI_SHIP_PACKAGE, SPATHI_SHIP_PACKAGE, SUPOX_SHIP_PACKAGE, THRADD_SHIP_PACKAGE, UTWIG_SHIP_PACKAGE, VUX_SHIP_PACKAGE, YEHAT_SHIP_PACKAGE, MELNORME_SHIP_PACKAGE, DRUUGE_SHIP_PACKAGE, ILWRATH_SHIP_PACKAGE, MYCON_SHIP_PACKAGE, SLYLANDRO_SHIP_PACKAGE, UMGAH_SHIP_PACKAGE, URQUAN_SHIP_PACKAGE, ZOQFOTPIK_SHIP_PACKAGE, SYREEN_SHIP_PACKAGE, BLACKURQ_SHIP_PACKAGE, ANDROSYN_SHIP_PACKAGE, CHENJESU_SHIP_PACKAGE, MMRNMHRM_SHIP_PACKAGE, KERNEL_PACKAGE, SC2KERNEL_PACKAGE, MICROFONT_PACKAGE, SC2DATA_PACKAGE, MENU_SOUND_PACKAGE, SOUND_PACKAGE, SPACE_PACKAGE, AMBIENT_HYPER_PACKAGE, HYPER_PACKAGE, ARISPACE_PACKAGE, HYPERSPACE_MUSIC_PACKAGE, QUASISPACE_MUSIC_PACKAGE, INIT_PACKAGE, IP_PACKAGE, LANDER_PACKAGE, ORBIT_VIEW_PACKAGE, EARTH_PACKAGE, CANNISTER_PACKAGE, LIFE00_PACKAGE, LIFE01_PACKAGE, LIFE02_PACKAGE, LIFE03_PACKAGE, LIFE04_PACKAGE, LIFE05_PACKAGE, LIFE06_PACKAGE, LIFE07_PACKAGE, LIFE08_PACKAGE, LIFE09_PACKAGE, LIFE10_PACKAGE, LIFE11_PACKAGE, LIFE12_PACKAGE, LIFE13_PACKAGE, LIFE14_PACKAGE, LIFE15_PACKAGE, LIFE16_PACKAGE, LIFE17_PACKAGE, LIFE18_PACKAGE, LIFE19_PACKAGE, LIFE20_PACKAGE, LIFE21_PACKAGE, LIFE22_PACKAGE, LIFE23_PACKAGE, LIFE24_PACKAGE, LIFE25_PACKAGE, OOLITE_PACKAGE, YTTRIC_COLOR_PACKAGE, YTTRIC_XLAT_PACKAGE, QD_COLOR_PACKAGE, QD_XLAT_PACKAGE, LANTHANIDE_COLOR_PACKAGE, TREASURE_COLOR_PACKAGE, UREA_COLOR_PACKAGE, UREA_XLAT_PACKAGE, METAL_PACKAGE, RADIOACTIVE_COLOR_PACKAGE, OPALESCENT_COLOR_PACKAGE, OPALESCENT_XLAT_PACKAGE, CYANIC_COLOR_PACKAGE, ACID_COLOR_PACKAGE, ALKALI_COLOR_PACKAGE, HALIDE_COLOR_PACKAGE, GREEN_COLOR_PACKAGE, COPPER_COLOR_PACKAGE, CARBIDE_COLOR_PACKAGE, ULTRAMARINE_COLOR_PACKAGE, NOBLE_COLOR_PACKAGE, AZURE_COLOR_PACKAGE, CHONDRITE_PACKAGE, PURPLE_COLOR_PACKAGE, SUPER_DENSE_COLOR_PACKAGE, PELLUCID_COLOR_PACKAGE, DUST_COLOR_PACKAGE, MAROON_COLOR_PACKAGE, CIMMERIAN_COLOR_PACKAGE, INFRARED_COLOR_PACKAGE, SELENIC_COLOR_PACKAGE, AURIC_COLOR_PACKAGE, FLUORESCENT_COLOR_PACKAGE, ULTRAVIOLET_COLOR_PACKAGE, PLUTONIC_COLOR_PACKAGE, RAINBOW_COLOR_PACKAGE, CRACKED_PACKAGE, SAPPHIRE_COLOR_PACKAGE, SAPPHIRE_XLAT_PACKAGE, ORGANIC_COLOR_PACKAGE, XENOLITHIC_COLOR_PACKAGE, REDUX_PACKAGE, PRIMORDIAL_COLOR_PACKAGE, EMERALD_COLOR_PACKAGE, CHLORINE_COLOR_PACKAGE, CHLORINE_XLAT_PACKAGE, MAGNETIC_COLOR_PACKAGE, WATER_COLOR_PACKAGE, TELLURIC_COLOR_PACKAGE, HYDROCARBON_COLOR_PACKAGE, IODINE_COLOR_PACKAGE, VINYLOGOUS_COLOR_PACKAGE, RUBY_COLOR_PACKAGE, MAGMA_COLOR_PACKAGE, CRIMSON_COLOR_PACKAGE, GAS_XLAT_PACKAGE, BLU_GAS_CT_PACKAGE, CYA_GAS_CT_PACKAGE, GRN_GAS_CT_PACKAGE, GRY_GAS_CT_PACKAGE, ORA_GAS_CT_PACKAGE, PUR_GAS_CT_PACKAGE, RED_GAS_CT_PACKAGE, VIO_GAS_CT_PACKAGE, YEL_GAS_CT_PACKAGE, REPORT_PACKAGE, MOONBASE_PACKAGE, MAIDENS_PACKAGE, CHMMR_BASE_PACKAGE, AQUA_PACKAGE, BURV_BCS_PACKAGE, TAALO_DEVICE_PACKAGE, SUN_DEVICE_PACKAGE, VAULT_PACKAGE, WRECK_PACKAGE, BOMB_PACKAGE, BEAST_PACKAGE, EGG_CASE_PACKAGE, SPAPLUTO_PACKAGE, BURV_RUINS_PACKAGE, ANDROSYNTH_RUINS_PACKAGE, DRUUGE_RUINS_PACKAGE, PKUNK_RUINS_PACKAGE, RACE_RUINS_PACKAGE, RACE_RUINS_TEXT_PACKAGE, UMGAH_BCS_PACKAGE, IP_MUSIC_PACKAGE, ORBIT_MUSIC_PACKAGE, MELEE_BGROUND_PACKAGE, MELEE_PICK_PACKAGE, SC2_SEGUE_PACKAGE, SC2_PICK_PACKAGE, ARILOU_CONVERSATION_PACKAGE, CHMMR_CONVERSATION_PACKAGE, COMMANDER_CONVERSATION_PACKAGE, ORZ_CONVERSATION_PACKAGE, PKUNK_CONVERSATION_PACKAGE, SHOFIXTI_CONVERSATION_PACKAGE, SPATHI_CONVERSATION_PACKAGE, SUPOX_CONVERSATION_PACKAGE, THRADD_CONVERSATION_PACKAGE, UTWIG_CONVERSATION_PACKAGE, VUX_CONVERSATION_PACKAGE, YEHAT_CONVERSATION_PACKAGE, MELNORME_CONVERSATION_PACKAGE, DRUUGE_CONVERSATION_PACKAGE, ILWRATH_CONVERSATION_PACKAGE, MYCON_CONVERSATION_PACKAGE, SLYLANDRO_CONVERSATION_PACKAGE, UMGAH_CONVERSATION_PACKAGE, URQUAN_CONVERSATION_PACKAGE, ZOQFOTPIK_CONVERSATION_PACKAGE, SYREEN_CONVERSATION_PACKAGE, BLACKURQ_CONVERSATION_PACKAGE, TALKING_PET_CONVERSATION_PACKAGE, SLYLANDRO_HOME_CONVERSATION_PACKAGE, PLAYER_CONVERSATION_PACKAGE, SIS_PACKAGE, SAMATRA_PACKAGE, URQUAN_PROBE_PACKAGE, RESTART_PACKAGE, MODULE_PACKAGE, OUTFIT_PACKAGE, OUTFIT_MUSIC_PACKAGE, BLUEPRINT_PACKAGE, SHIPYARD_MUSIC_PACKAGE, STARBASE_PACKAGE, SAMATRA_BATTLE_PACKAGE, SHIELDED_BATTLE_PACKAGE, PLANET00_PACKAGE, PLANET01_PACKAGE, PLANET02_PACKAGE, PLANET03_PACKAGE, PLANET04_PACKAGE, PLANET05_PACKAGE, PLANET06_PACKAGE, PLANET07_PACKAGE, PLANET08_PACKAGE, PLANET09_PACKAGE, PLANET10_PACKAGE, PLANET11_PACKAGE, PLANET12_PACKAGE, PLANET13_PACKAGE, PLANET14_PACKAGE, PLANET15_PACKAGE, PLANET16_PACKAGE, PLANET17_PACKAGE, PLANET18_PACKAGE, PLANET19_PACKAGE, PLANET20_PACKAGE, PLANET21_PACKAGE, PLANET22_PACKAGE, PLANET23_PACKAGE, PLANET24_PACKAGE, PLANET25_PACKAGE, PLANET26_PACKAGE, PLANET27_PACKAGE, PLANET28_PACKAGE, PLANET29_PACKAGE, PLANET30_PACKAGE, PLANET31_PACKAGE, PLANET32_PACKAGE, PLANET33_PACKAGE, PLANET34_PACKAGE, PLANET35_PACKAGE, PLANET36_PACKAGE, PLANET37_PACKAGE, PLANET38_PACKAGE, PLANET39_PACKAGE, PLANET40_PACKAGE, PLANET41_PACKAGE, PLANET42_PACKAGE, PLANET43_PACKAGE, PLANET44_PACKAGE, PLANET45_PACKAGE, PLANET46_PACKAGE, PLANET47_PACKAGE, PLANET48_PACKAGE, PLANET49_PACKAGE, PLANET50_PACKAGE, PLANET51_PACKAGE, PLANET52_PACKAGE, PLANET53_PACKAGE, PLANET54_PACKAGE, PLANET55_PACKAGE, PLANET56_PACKAGE, PLANET57_PACKAGE, PLANET58_PACKAGE, BATTLE_MUSIC_PACKAGE, CREDITBKGD_PACKAGE, UNUSED_01_PACKAGE_, UNUSED_02_PACKAGE_, UNUSED_03_PACKAGE_, UNUSED_04_PACKAGE_, UNUSED_05_PACKAGE_, UNUSED_06_PACKAGE_, UNUSED_07_PACKAGE_, UNUSED_08_PACKAGE_, UNUSED_09_PACKAGE_, UNUSED_10_PACKAGE_, UNUSED_11_PACKAGE_, UNUSED_12_PACKAGE_, UNUSED_13_PACKAGE_, UNUSED_14_PACKAGE_, UNUSED_15_PACKAGE_, UNUSED_16_PACKAGE_, UNUSED_17_PACKAGE_, UNUSED_18_PACKAGE_, UNUSED_19_PACKAGE_, CREDIT_MUSIC_PACKAGE, SISSKEL_PACKAGE, ORBENTER_PACKAGE, MENUBKG_PACKAGE, INTRO_PACKAGE, FINAL_PACKAGE, CREDIT_FONTS_PACKAGE, CREDITS_PACKAGE, JOYSTICK_ALPHA_PACKAGE, }; uqm-0.6.2/sc2/src/sc2code/border.c0000600000175000017500000001315710543202101015223 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "libs/gfxlib.h" #include "libs/threadlib.h" #include "colors.h" #include "setup.h" #include "sis.h" #include "units.h" #include "util.h" void InitSISContexts (void) { RECT r; SetContext (StatusContext); SetContext (SpaceContext); SetContextFGFrame (Screen); r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT; SetContextClipRect (&r); } void DrawSISFrame (void) { RECT r; SetContext (ScreenContext); BatchGraphics (); { SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); r.corner.x = 0; r.corner.y = 0; r.extent.width = SIS_ORG_X + SIS_SCREEN_WIDTH + 1; r.extent.height = SIS_ORG_Y - 1; DrawFilledRectangle (&r); r.corner.x = 0; r.corner.y = 0; r.extent.width = SIS_ORG_X - 1; r.extent.height = SIS_ORG_Y + SIS_SCREEN_HEIGHT + 1; DrawFilledRectangle (&r); r.corner.x = 0; r.corner.y = r.extent.height; r.extent.width = SIS_ORG_X + SIS_SCREEN_WIDTH + 1; r.extent.height = SCREEN_HEIGHT - SIS_ORG_Y + SIS_SCREEN_HEIGHT; DrawFilledRectangle (&r); r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH + 1; r.corner.y = 0; r.extent.width = SCREEN_WIDTH - r.corner.x; r.extent.height = SCREEN_HEIGHT; DrawFilledRectangle (&r); r.corner.x = SIS_ORG_X - 1; r.corner.y = SIS_ORG_Y - 1; r.extent.width = SIS_SCREEN_WIDTH + 2; r.extent.height = SIS_SCREEN_HEIGHT + 2; DrawStarConBox (&r, 1, BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F), TRUE, BLACK_COLOR); r.corner.y = 0; r.extent.height = SIS_ORG_Y; r.corner.x = SIS_ORG_X; r.extent.width = SIS_SCREEN_WIDTH - 69; DrawStarConBox (&r, 1, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x0E), 0x54), BUILD_COLOR (MAKE_RGB15 (0x00, 0x01, 0x1C), 0x4E), TRUE, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); r.extent.width = 57; r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH - 57; DrawStarConBox (&r, 1, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x0E), 0x54), BUILD_COLOR (MAKE_RGB15 (0x00, 0x01, 0x1C), 0x4E), TRUE, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); SetContextForeGroundColor (BLACK_COLOR); r.corner.x = SAFE_X + SPACE_WIDTH - 1; r.corner.y = 0; r.extent.width = 1; r.extent.height = SCREEN_HEIGHT; DrawFilledRectangle (&r); r.corner.x = SAFE_X + SPACE_WIDTH; r.corner.y = SAFE_Y + 139; DrawPoint (&r.corner); r.corner.x = SCREEN_WIDTH - 1; DrawPoint (&r.corner); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); r.corner.y = 1; r.extent.width = 1; r.extent.height = SAFE_Y + 8; r.corner.x = SIS_ORG_X - 1; DrawFilledRectangle (&r); r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH - 57 - 1; DrawFilledRectangle (&r); r.corner.x = 0; r.corner.y = SCREEN_HEIGHT - 1; r.extent.width = SAFE_X + SPACE_WIDTH - 1; r.extent.height = 1; DrawFilledRectangle (&r); r.corner.x = SAFE_X + SPACE_WIDTH - 2; r.corner.y = 0; r.extent.width = 1; r.extent.height = SCREEN_HEIGHT - 1; DrawFilledRectangle (&r); r.corner.x = SCREEN_WIDTH - 1; r.corner.y = 0; r.extent.width = 1; r.extent.height = SAFE_Y + 139; DrawFilledRectangle (&r); r.corner.x = SAFE_X + SPACE_WIDTH; r.corner.y = SCREEN_HEIGHT - 1; r.extent.width = SCREEN_WIDTH - r.corner.x; r.extent.height = 1; DrawFilledRectangle (&r); r.corner.x = SCREEN_WIDTH - 1; r.corner.y = SAFE_Y + 140; r.extent.width = 1; r.extent.height = (SCREEN_HEIGHT - 1) - r.corner.y; DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); r.corner.y = 1; r.extent.width = 1; r.extent.height = SAFE_Y + 8; r.corner.x = SIS_ORG_X + (SIS_SCREEN_WIDTH - 69); DrawFilledRectangle (&r); r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH; ++r.extent.height; DrawFilledRectangle (&r); r.corner.y = 0; r.extent.width = (SAFE_X + SPACE_WIDTH - 2) - r.corner.x; r.extent.height = 1; DrawFilledRectangle (&r); r.corner.x = 0; r.extent.width = SIS_ORG_X - r.corner.x; DrawFilledRectangle (&r); r.corner.x = SIS_ORG_X + (SIS_SCREEN_WIDTH - 69); r.extent.width = (SIS_ORG_X + SIS_SCREEN_WIDTH - 57) - r.corner.x; DrawFilledRectangle (&r); r.corner.x = 0; r.corner.y = 1; r.extent.width = 1; r.extent.height = (SCREEN_HEIGHT - 1) - r.corner.y; DrawFilledRectangle (&r); r.corner.x = SAFE_X + SPACE_WIDTH; r.corner.y = 0; r.extent.width = 1; r.extent.height = SAFE_Y + 139; DrawFilledRectangle (&r); r.corner.x = SAFE_X + SPACE_WIDTH + 1; r.corner.y = SAFE_Y + 139; r.extent.width = STATUS_WIDTH - 2; r.extent.height = 1; DrawFilledRectangle (&r); r.corner.x = SAFE_X + SPACE_WIDTH; r.corner.y = SAFE_Y + 140; r.extent.width = 1; r.extent.height = SCREEN_HEIGHT - r.corner.y; DrawFilledRectangle (&r); } InitSISContexts (); ClearSISRect (DRAW_SIS_DISPLAY); UnbatchGraphics (); } uqm-0.6.2/sc2/src/sc2code/demo.c0000600000175000017500000000547410543202103014677 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "demo.h" #include "declib.h" #if DEMO_MODE || CREATE_JOURNAL static DECODE_REF journal_fh; static char journal_buf[1024 #if CREATE_JOURNAL * 8 #else /* DEMO_MODE */ * 2 #endif ]; INPUT_REF DemoInput; #endif #if DEMO_MODE static INPUT_REF OldArrowInput; INPUT_STATE demo_input (INPUT_REF InputRef, INPUT_STATE InputState) { if (InputState || AnyButtonPress () || cread ( (PBYTE)&InputState, sizeof (InputState), 1, journal_fh ) == 0) { cclose (journal_fh); journal_fh = 0; StopMusic (); StopSound (); FreeKernel (); exit (1); } return (InputState); } #endif /* DEMO_MODE */ #if CREATE_JOURNAL void JournalInput (INPUT_STATE InputState) { if (ArrowInput != DemoInput && journal_fh) cwrite ((PBYTE)&InputState, sizeof (InputState), 1, journal_fh); } #endif /* CREATE_JOURNAL */ #if DEMO_MODE || CREATE_JOURNAL void OpenJournal (void) { DWORD start_seed; #if CREATE_JOURNAL if (create_journal) { if (journal_fh = copen (journal_buf, MEMORY_STREAM, STREAM_WRITE)) { start_seed = SeedRandomNumbers (); cwrite ((PBYTE)&start_seed, sizeof (start_seed), 1, journal_fh); } } else #endif /* CREATE_JOURNAL */ { uio_Stream *fp; if (fp = res_OpenResFile ("starcon.jnl", "rb")) { ReadResFile (journal_buf, 1, sizeof (journal_buf), fp); res_CloseResFile (fp); if (journal_fh = copen (journal_buf, MEMORY_STREAM, STREAM_READ)) { OldArrowInput = ArrowInput; ArrowInput = DemoInput; PlayerInput[0] = PlayerInput[1] = DemoInput; FlushInput (); cread ((PBYTE)&start_seed, sizeof (start_seed), 1, journal_fh); TFB_SeedRandom (start_seed); } } } } BOOLEAN CloseJournal (void) { if (journal_fh) { uio_Stream *fp; cclose (journal_fh); journal_fh = 0; if (ArrowInput == DemoInput) { ArrowInput = OldArrowInput; return (FALSE); } #if CREATE_JOURNAL else if (fp = res_OpenResFile ("starcon.jnl", "wb")) { WriteResFile (journal_buf, 1, sizeof (journal_buf), fp); res_CloseResFile (fp); } #endif /* CREATE_JOURNAL */ } return (TRUE); } #endif uqm-0.6.2/sc2/src/sc2code/credits.h0000600000175000017500000000154710543202100015407 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _CREDITS_H #define _CREDITS_H #include "libs/compiler.h" extern void Credits (BOOLEAN WithOuttakes); #endif /* _CREDITS_H */ uqm-0.6.2/sc2/src/sc2code/starmap.c0000600000175000017500000000507310543202103015415 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "encount.h" #include "gamestr.h" #include "globdata.h" #include "libs/compiler.h" #include "libs/gfxlib.h" STAR_DESCPTR star_array; STAR_DESCPTR CurStarDescPtr = 0; STAR_DESCPTR FindStar (STAR_DESCPTR LastSDPtr, PPOINT puniverse, SIZE xbounds, SIZE ybounds) { COORD min_y, max_y; SIZE lo, hi; STAR_DESCPTR BaseSDPtr; if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { BaseSDPtr = star_array; hi = NUM_SOLAR_SYSTEMS - 1; } else { #define NUM_HYPER_VORTICES 15 BaseSDPtr = &star_array[NUM_SOLAR_SYSTEMS + 1]; hi = (NUM_HYPER_VORTICES + 1) - 1; } if (LastSDPtr == NULL_PTR) lo = 0; else if ((lo = LastSDPtr - BaseSDPtr + 1) > hi) return (0); else hi = lo; if (ybounds <= 0) min_y = max_y = puniverse->y; else { min_y = puniverse->y - ybounds; max_y = puniverse->y + ybounds; } while (lo < hi) { SIZE mid; mid = (lo + hi) >> 1; if (BaseSDPtr[mid].star_pt.y >= min_y) hi = mid - 1; else lo = mid + 1; } LastSDPtr = &BaseSDPtr[lo]; if (ybounds < 0 || LastSDPtr->star_pt.y <= max_y) { COORD min_x, max_x; if (xbounds <= 0) min_x = max_x = puniverse->x; else { min_x = puniverse->x - xbounds; max_x = puniverse->x + xbounds; } do { if ((ybounds < 0 || LastSDPtr->star_pt.y >= min_y) && (xbounds < 0 || (LastSDPtr->star_pt.x >= min_x && LastSDPtr->star_pt.x <= max_x)) ) return (LastSDPtr); } while ((++LastSDPtr)->star_pt.y <= max_y); } return (0); } void GetClusterName (STAR_DESCPTR pSD, UNICODE buf[]) { UNICODE *pBuf, *pStr; pBuf = buf; if (pSD->Prefix) { pStr = GAME_STRING (STAR_NUMBER_BASE + pSD->Prefix - 1); if (pStr) { while ((*pBuf++ = *pStr++)) ; pBuf[-1] = ' '; } } if ((pStr = GAME_STRING (pSD->Postfix)) == 0) *pBuf = '\0'; else { while ((*pBuf++ = *pStr++)) ; } } uqm-0.6.2/sc2/src/sc2code/starcon.c0000644000175000017500000001653610552532777015464 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "encount.h" #include "element.h" #include "fmv.h" #include "gameev.h" #include "types.h" #include "globdata.h" #include "load.h" #include "resinst.h" #include "restart.h" #include "starbase.h" #include "setup.h" #include "master.h" #include "controls.h" #include "starcon.h" #include "uqmdebug.h" #include "libs/tasklib.h" #include "libs/log.h" #include "uqmversion.h" #include "options.h" // Open or close the periodically occuring QuasiSpace portal. // A seperate thread is always inside this function when the player // is in hyperspace. This thread awakens every BATTLE_FRAME_RATE seconds. // It then changes the appearant portal size when necessary. static int arilou_gate_task(void *data) { BYTE counter; DWORD TimeIn; Task task = (Task) data; TimeIn = GetTimeCounter (); counter = GET_GAME_STATE (ARILOU_SPACE_COUNTER); while (!Task_ReadState (task, TASK_EXIT)) { SetSemaphore (GLOBAL (GameClock.clock_sem)); if (GET_GAME_STATE (ARILOU_SPACE) == OPENING) { if (++counter == 10) counter = 9; } else { if (counter-- == 0) counter = 0; } LockMutex (GraphicsLock); SET_GAME_STATE (ARILOU_SPACE_COUNTER, counter); UnlockMutex (GraphicsLock); ClearSemaphore (GLOBAL (GameClock.clock_sem)); SleepThreadUntil (TimeIn + BATTLE_FRAME_RATE); TimeIn = GetTimeCounter (); } FinishTask (task); return(0); } static void BackgroundInitKernel (DWORD TimeOut) { LoadMasterShipList (); TaskSwitch (); InitGameKernel (); while ((GetTimeCounter () <= TimeOut) && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) { UpdateInputState (); TaskSwitch (); } } #define DEBUG_PSYTRON 0 /* TODO: Remove these declarations once threading is gone. */ extern int snddriver, soundflags; int Starcon2Main (void *threadArg) { #if DEBUG_PSYTRON || CREATE_JOURNAL { int ac = argc; char **av = argv; while (--ac > 0) { ++av; if ((*av)[0] == '-') { switch ((*av)[1]) { #ifdef DEBUG_PSYTRON case 'd': { extern BYTE debug_psytron; debug_psytron = atoi (&(*av)[2]); break; } #endif //DEBUG_PSYTRON #if CREATE_JOURNAL case 'j': ++create_journal; break; #endif //CREATE_JOURNAL } } } } #endif //DEBUG_PSYTRON || CREATE_JOURNAL /* TODO: Put initAudio back in main where it belongs once threading * is gone. */ extern sint32 initAudio (sint32 driver, sint32 flags); initAudio (snddriver, soundflags); if (LoadKernel (0,0)) { log_add (log_Info, "We've loaded the Kernel"); Logo (); GLOBAL (CurrentActivity) = 0; // show splash and init the kernel in the meantime SplashScreen (BackgroundInitKernel); // OpenJournal (); while (StartGame ()) { InitSIS (); InitGameClock (); AddInitialGameEvents(); do { SuspendGameClock (); #ifdef DEBUG if (debugHook != NULL) { void (*saveDebugHook) (void); saveDebugHook = debugHook; debugHook = NULL; // No further debugHook calls unless the called // function resets debugHook. (*saveDebugHook) (); continue; } #endif if (!((GLOBAL (CurrentActivity) | NextActivity) & CHECK_LOAD)) ZeroVelocityComponents ( &GLOBAL (velocity) ); //not going into talking pet conversation else if (GLOBAL (CurrentActivity) & CHECK_LOAD) GLOBAL (CurrentActivity) = NextActivity; if ((GLOBAL (CurrentActivity) & START_ENCOUNTER) || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) { if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2 && !GET_GAME_STATE (STARBASE_AVAILABLE)) { /* BGD mode */ InstallBombAtEarth (); } else if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) == (BYTE)~0 || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) { GLOBAL (CurrentActivity) |= START_ENCOUNTER; VisitStarBase (); } else { GLOBAL (CurrentActivity) |= START_ENCOUNTER; RaceCommunication (); } if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_ENCOUNTER; if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY) GLOBAL (CurrentActivity) |= START_INTERPLANETARY; } } else if (GLOBAL (CurrentActivity) & START_INTERPLANETARY) { GLOBAL (CurrentActivity) = MAKE_WORD (IN_INTERPLANETARY, 0); ExploreSolarSys (); #ifdef TESTING if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) { if (!(GLOBAL (CurrentActivity) & START_ENCOUNTER) && (CurStarDescPtr = FindStar (NULL_PTR, &GLOBAL (autopilot), 0, 0))) { GLOBAL (autopilot.x) = ~0; GLOBAL (autopilot.y) = ~0; GLOBAL (ShipStamp.frame) = 0; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; } } #endif //TESTING } else { Task ArilouTask; GLOBAL (CurrentActivity) = MAKE_WORD (IN_HYPERSPACE, 0); ArilouTask = AssignTask (arilou_gate_task, 128, "quasispace portal manager"); TaskSwitch (); Battle (); if (ArilouTask) Task_SetState (ArilouTask, TASK_EXIT); } LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); LastActivity = GLOBAL (CurrentActivity); if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) && (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE //if died for some reason || GLOBAL_SIS (CrewEnlisted) == (COUNT)~0)) { if (GET_GAME_STATE (KOHR_AH_KILLED_ALL)) InitCommunication (BLACKURQ_CONVERSATION); //surrendered to Ur-Quan else if (GLOBAL (CurrentActivity) & CHECK_RESTART) GLOBAL (CurrentActivity) &= ~CHECK_RESTART; break; } } while (!(GLOBAL (CurrentActivity) & CHECK_ABORT)); StopSound (); UninitGameClock (); UninitSIS (); } // CloseJournal (); FreeGameData (); } else { log_add (log_Fatal, "\n *** FATAL ERROR: Could not load basic content ***\n\nUQM requires at least the base content pack to run properly."); log_add (log_Fatal, "This file is typically called uqm-%d.%d.0.uqm. UQM was expecting it", UQM_MAJOR_VERSION, UQM_MINOR_VERSION); log_add (log_Fatal, "in the %s/packages directory.", baseContentPath); log_add (log_Fatal, "Either your installation did not install the content pack at all, or it\ninstalled it in a different directory.\n\nFix your installation and rerun UQM.\n\n *******************\n"); exit (EXIT_FAILURE); } FreeKernel (); // XXX: the abort can now be changed to something cleaner; // something to terminate the for(;;) loop in main() TFB_Abort (); (void) threadArg; /* Satisfying compiler (unused parameter) */ return 0; } uqm-0.6.2/sc2/src/sc2code/sis.h0000600000175000017500000001452210543202101014546 0ustar joeyjoey#ifndef _SIS_H #define _SIS_H #include "planets/planets.h" enum { PM_SCAN = 0, PM_STARMAP, PM_DEVICES, PM_CARGO, PM_ROSTER, PM_SAVE_LOAD0, PM_NAVIGATE, PM_MIN_SCAN, PM_ENE_SCAN, PM_BIO_SCAN, PM_EXIT_MENU0, PM_AUTO_SCAN, PM_LAUNCH_LANDER, PM_SAVE_GAME, PM_LOAD_GAME, PM_QUIT_GAME, PM_CHANGE_SETTINGS, PM_EXIT_MENU1, PM_CONVERSE, PM_ATTACK, PM_SAVE_LOAD1, PM_FUEL, PM_MODULE, PM_SAVE_LOAD2, PM_EXIT_MENU2, PM_CREW, PM_SAVE_LOAD3, PM_EXIT_MENU3, PM_SOUND_ON, PM_SOUND_OFF, PM_MUSIC_ON, PM_MUSIC_OFF, PM_CYBORG_OFF, PM_CYBORG_NORMAL, PM_CYBORG_DOUBLE, PM_CYBORG_SUPER, PM_CHANGE_CAPTAIN, PM_CHANGE_SHIP, PM_EXIT_MENU4, PM_NO_QUIT, PM_YES_QUIT, PM_ALT_SCAN, PM_ALT_STARMAP, PM_ALT_MANIFEST, PM_ALT_SAVE0, PM_ALT_NAVIGATE, PM_ALT_CARGO, PM_ALT_DEVICES, PM_ALT_ROSTER, PM_ALT_EXITMENU0, PM_ALT_MSCAN, PM_ALT_ESCAN, PM_ALT_BSCAN, PM_ALT_ASCAN, PM_ALT_DISPATCH, PM_ALT_EXITMENU1 }; #define CLEAR_SIS_RADAR (1 << 2) #define DRAW_SIS_DISPLAY (1 << 3) #define UNDEFINED_DELTA 0x7FFF #define RADAR_X (4 + (SCREEN_WIDTH - STATUS_WIDTH - SAFE_X)) #define RADAR_WIDTH (STATUS_WIDTH - 8) #define RADAR_HEIGHT 53 #define RADAR_Y (SIS_ORG_Y + SIS_SCREEN_HEIGHT - RADAR_HEIGHT) #define NUM_RADAR_SCREENS 12 #define MAG_SHIFT 2 /* driving on planet */ #define SHIP_NAME_WIDTH 60 #define SHIP_NAME_HEIGHT 7 #define NUM_DRIVE_SLOTS 11 #define NUM_JET_SLOTS 8 #define NUM_MODULE_SLOTS 16 #define CREW_POD_CAPACITY 50 #define STORAGE_BAY_CAPACITY 500 /* km cubed */ #define FUEL_TANK_SCALE 100 #define FUEL_TANK_CAPACITY (50 * FUEL_TANK_SCALE) #define HEFUEL_TANK_CAPACITY (100 * FUEL_TANK_SCALE) #define MODULE_COST_SCALE 50 #define CREW_EXPENSE_THRESHOLD 1000 #define CREW_PER_ROW 5 #define SBAY_MASS_PER_ROW 50 #define MAX_FUEL_BARS 10 #define FUEL_VOLUME_PER_ROW (HEFUEL_TANK_CAPACITY / MAX_FUEL_BARS) #define FUEL_RESERVE FUEL_VOLUME_PER_ROW #define MAX_COMBAT_SHIPS 12 #define MAX_BATTLE_GROUPS 64 #define IP_SHIP_THRUST_INCREMENT 8 #define IP_SHIP_TURN_WAIT 17 #define IP_SHIP_TURN_DECREMENT 2 #define BOGUS_MASS 5 #define BIO_CREDIT_VALUE 2 enum { PLANET_LANDER = 0, /* thruster types */ FUSION_THRUSTER, /* jet types */ TURNING_JETS, /* module types */ CREW_POD, STORAGE_BAY, FUEL_TANK, HIGHEFF_FUELSYS, DYNAMO_UNIT, SHIVA_FURNACE, GUN_WEAPON, BLASTER_WEAPON, CANNON_WEAPON, TRACKING_SYSTEM, ANTIMISSILE_DEFENSE, NUM_PURCHASE_MODULES, BOMB_MODULE_0 = NUM_PURCHASE_MODULES, BOMB_MODULE_1, BOMB_MODULE_2, BOMB_MODULE_3, BOMB_MODULE_4, BOMB_MODULE_5, NUM_MODULES = 20 /* must be last entry */ }; #define EMPTY_SLOT NUM_MODULES #define NUM_BOMB_MODULES 10 #define DRIVE_SIDE_X 31 #define DRIVE_SIDE_Y 56 #define DRIVE_TOP_X 33 #define DRIVE_TOP_Y (65 + 21) #define JET_SIDE_X 71 #define JET_SIDE_Y 48 #define JET_TOP_X 70 #define JET_TOP_Y (73 + 21) #define MODULE_SIDE_X 17 #define MODULE_SIDE_Y 14 #define MODULE_TOP_X 17 #define MODULE_TOP_Y (96 + 21) #define SHIP_PIECE_OFFSET 12 #define MAX_BUILT_SHIPS 12 /* Maximum number of ships escorting the SIS */ #define MAX_LANDERS 10 #define SUPPORT_SHIP_PTS \ {3 + 0, 30 + (2 * 16)}, \ {3 + 42, 30 + (2 * 16)}, \ {3 + 0, 30 + (3 * 16)}, \ {3 + 42, 30 + (3 * 16)}, \ {3 + 0, 30 + (1 * 16)}, \ {3 + 42, 30 + (1 * 16)}, \ {3 + 0, 30 + (4 * 16)}, \ {3 + 42, 30 + (4 * 16)}, \ {3 + 0, 30 + (0 * 16)}, \ {3 + 42, 30 + (0 * 16)}, \ {3 + 0, 30 + (5 * 16)}, \ {3 + 42, 30 + (5 * 16)}, #define SIS_MESSAGE_WIDTH (SIS_SCREEN_WIDTH - 69 - 2) #define SIS_MESSAGE_HEIGHT 8 #define SIS_TITLE_WIDTH 55 #define SIS_TITLE_HEIGHT 8 #define STATUS_MESSAGE_WIDTH 60 #define STATUS_MESSAGE_HEIGHT 7 #define SIS_NAME_SIZE 16 typedef struct { SDWORD log_x, log_y; DWORD ResUnits; DWORD FuelOnBoard; COUNT CrewEnlisted; // Number of crew on board, not counting the captain. // Set to (COUNT) ~0 to indicate game over. COUNT TotalElementMass, TotalBioMass; BYTE ModuleSlots[NUM_MODULE_SLOTS]; BYTE DriveSlots[NUM_DRIVE_SLOTS]; BYTE JetSlots[NUM_JET_SLOTS]; BYTE NumLanders; COUNT ElementAmounts[NUM_ELEMENT_CATEGORIES]; UNICODE ShipName[SIS_NAME_SIZE]; UNICODE CommanderName[SIS_NAME_SIZE]; UNICODE PlanetName[SIS_NAME_SIZE]; } SIS_STATE; typedef SIS_STATE *PSIS_STATE; #define MAX_EXCLUSIVE_DEVICES 16 typedef struct { SIS_STATE SS; BYTE Activity; BYTE Flags; BYTE day_index, month_index; COUNT year_index; BYTE MCreditLo, MCreditHi; BYTE NumShips, NumDevices; BYTE ShipList[MAX_BUILT_SHIPS]; BYTE DeviceList[MAX_EXCLUSIVE_DEVICES]; } SUMMARY_DESC; #define OVERRIDE_LANDER_FLAGS (1 << 7) #define AFTER_BOMB_INSTALLED (1 << 7) extern BOOLEAN InitSIS (void); extern void UninitSIS (void); extern void SeedUniverse (void); extern BOOLEAN LoadHyperspace (void); extern BOOLEAN FreeHyperspace (void); extern void MoveSIS (PSIZE pdx, PSIZE pdy); extern void RepairSISBorder (void); extern void InitSISContexts (void); extern void DrawSISFrame (void); extern void ClearSISRect (BYTE ClearFlags); extern void SetFlashRect (PRECT pRect, FRAME f); #define SFR_MENU_3DO ((PRECT)~0L) #define SFR_MENU_ANY ((PRECT)~1L) extern void DrawHyperCoords (POINT puniverse); extern void DrawSISTitle (UNICODE *pStr); extern BOOLEAN DrawSISMessageEx (const UNICODE *pStr, SIZE CurPos, SIZE ExPos, COUNT flags); #define DSME_NONE 0 #define DSME_SETFR (1 << 0) #define DSME_CLEARFR (1 << 1) #define DSME_BLOCKCUR (1 << 2) extern void DrawSISMessage (const UNICODE *pStr); extern void DrawGameDate (void); extern void DateToString (unsigned char *buf, size_t bufLen, BYTE month_index, BYTE day_index, COUNT year_index); extern void DrawStatusMessage (const UNICODE *pStr); extern void DrawLanders (void); extern void DrawStorageBays (BOOLEAN Refresh); extern void GetGaugeRect (PRECT pRect, BOOLEAN IsCrewRect); extern void DrawFlagshipStats (void); extern void SaveFlagshipState (void); extern void DeltaSISGauges (SIZE crew_delta, SIZE fuel_delta, int resunit_delta); extern COUNT GetCrewCount (void); extern COUNT GetCPodCapacity (PPOINT ppt); extern COUNT GetLBayCapacity (PPOINT ppt); extern COUNT GetSBayCapacity (PPOINT ppt); extern DWORD GetFTankCapacity (PPOINT ppt); extern COUNT CountSISPieces (BYTE piece_type); extern BOOLEAN DoMenuChooser (PMENU_STATE pMS, BYTE BaseState); extern void DrawMenuStateStrings (BYTE beg_index, SWORD NewState); extern void DoMenuOptions (void); extern void DrawFlagshipName (BOOLEAN InStatusArea); extern void DrawCaptainsName (void); #endif /* _SIS_H */ uqm-0.6.2/sc2/src/sc2code/restart.h0000600000175000017500000000153410543202103015435 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _RESTART_H #define _RESTART_H #include "libs/compiler.h" extern BOOLEAN StartGame (void); #endif /* _RESTART_H */ uqm-0.6.2/sc2/src/sc2code/star3do.res0000600000175000017500000007566010543202103015705 0ustar joeyjoeyINCLUDE star3do.typ PACKAGE INIT_PACKAGE starcon.pkg KEY_CONFIG JOYSTICK_KEYS starcon.key PATH lbm STRTAB STARCON_COLOR_MAP scclrtab.ct PACKAGE TITLE_PACKAGE starcon.pkg GFXRES TITLE_ANIM title.ani PATH . PACKAGE ARILOU_SHIP_PACKAGE starcon.pkg RES_INDEX ARILOU_SHIP_INDEX arilou.shp PACKAGE CHMMR_SHIP_PACKAGE starcon.pkg RES_INDEX CHMMR_SHIP_INDEX chmmr.shp PACKAGE EARTHLING_SHIP_PACKAGE starcon.pkg RES_INDEX EARTHLING_SHIP_INDEX human.shp PACKAGE ORZ_SHIP_PACKAGE starcon.pkg RES_INDEX ORZ_SHIP_INDEX orz.shp PACKAGE PKUNK_SHIP_PACKAGE starcon.pkg RES_INDEX PKUNK_SHIP_INDEX pkunk.shp PACKAGE SHOFIXTI_SHIP_PACKAGE starcon.pkg RES_INDEX SHOFIXTI_SHIP_INDEX shofixti.shp PACKAGE SPATHI_SHIP_PACKAGE starcon.pkg RES_INDEX SPATHI_SHIP_INDEX spathi.shp PACKAGE SUPOX_SHIP_PACKAGE starcon.pkg RES_INDEX SUPOX_SHIP_INDEX supox.shp PACKAGE THRADD_SHIP_PACKAGE starcon.pkg RES_INDEX THRADD_SHIP_INDEX thradd.shp PACKAGE UTWIG_SHIP_PACKAGE starcon.pkg RES_INDEX UTWIG_SHIP_INDEX utwig.shp PACKAGE VUX_SHIP_PACKAGE starcon.pkg RES_INDEX VUX_SHIP_INDEX vux.shp PACKAGE YEHAT_SHIP_PACKAGE starcon.pkg RES_INDEX YEHAT_SHIP_INDEX yehat.shp PACKAGE MELNORME_SHIP_PACKAGE starcon.pkg RES_INDEX MELNORME_SHIP_INDEX melnorme.shp PACKAGE DRUUGE_SHIP_PACKAGE starcon.pkg RES_INDEX DRUUGE_SHIP_INDEX druuge.shp PACKAGE ILWRATH_SHIP_PACKAGE starcon.pkg RES_INDEX ILWRATH_SHIP_INDEX ilwrath.shp PACKAGE MYCON_SHIP_PACKAGE starcon.pkg RES_INDEX MYCON_SHIP_INDEX mycon.shp PACKAGE SLYLANDRO_SHIP_PACKAGE starcon.pkg RES_INDEX SLYLANDRO_SHIP_INDEX slylandr.shp PACKAGE UMGAH_SHIP_PACKAGE starcon.pkg RES_INDEX UMGAH_SHIP_INDEX umgah.shp PACKAGE URQUAN_SHIP_PACKAGE starcon.pkg RES_INDEX URQUAN_SHIP_INDEX urquan.shp PACKAGE ZOQFOTPIK_SHIP_PACKAGE starcon.pkg RES_INDEX ZOQFOTPIK_SHIP_INDEX zoqfot.shp PACKAGE SYREEN_SHIP_PACKAGE starcon.pkg RES_INDEX SYREEN_SHIP_INDEX syreen.shp PACKAGE BLACKURQ_SHIP_PACKAGE starcon.pkg RES_INDEX BLACKURQ_SHIP_INDEX blackurq.shp PACKAGE ANDROSYN_SHIP_PACKAGE starcon.pkg RES_INDEX ANDROSYN_SHIP_INDEX androsyn.shp PACKAGE CHENJESU_SHIP_PACKAGE starcon.pkg RES_INDEX CHENJESU_SHIP_INDEX chenjesu.shp PACKAGE MMRNMHRM_SHIP_PACKAGE starcon.pkg RES_INDEX MMRNMHRM_SHIP_INDEX mmrnmhrm.shp PATH lbm PACKAGE KERNEL_PACKAGE starcon.pkg FONTRES STARCON_FONT starcon.fon FONTRES TINY_FONT tiny.fon GFXRES STATUS_MASK_PMAP_ANIM status.ani GFXRES ACTIVITY_ANIM activity.ani STRTAB STARCON_GAME_STRINGS starcon.txt PACKAGE SC2KERNEL_PACKAGE starcon.pkg GFXRES PLAYMENU_ANIM playmenu.ani PACKAGE MICROFONT_PACKAGE starcon.pkg FONTRES MICRO_FONT micro.fon PACKAGE SC2DATA_PACKAGE starcon.pkg GFXRES FLAGSTAT_MASK_PMAP_ANIM flagstat.ani GFXRES MISCDATA_MASK_PMAP_ANIM miscdata.ani PACKAGE MENU_SOUND_PACKAGE starcon.pkg SNDRES MENU_SOUNDS menusnd.snd PACKAGE SOUND_PACKAGE starcon.pkg SNDRES GAME_SOUNDS gamesnd.snd PACKAGE SPACE_PACKAGE starcon.pkg GFXRES STAR_MASK_PMAP_ANIM stars.ani GFXRES ASTEROID_BIG_MASK_PMAP_ANIM astbig.ani GFXRES ASTEROID_MED_MASK_PMAP_ANIM astmed.ani GFXRES ASTEROID_SML_MASK_PMAP_ANIM astsml.ani GFXRES BLAST_BIG_MASK_PMAP_ANIM blabig.ani GFXRES BLAST_MED_MASK_PMAP_ANIM blamed.ani GFXRES BLAST_SML_MASK_PMAP_ANIM blasml.ani GFXRES BOOM_BIG_MASK_PMAP_ANIM boobig.ani GFXRES BOOM_MED_MASK_PMAP_ANIM boomed.ani GFXRES BOOM_SML_MASK_PMAP_ANIM boosml.ani PACKAGE AMBIENT_HYPER_PACKAGE starcon.pkg GFXRES AMBIENT_MASK_PMAP_ANIM ambanim.ani PACKAGE HYPER_PACKAGE starcon.pkg GFXRES HYPERSTARS_MASK_PMAP_ANIM hyperstr.ani STRTAB HYPER_COLOR_TAB hyperpal.ct PACKAGE ARISPACE_PACKAGE starcon.pkg GFXRES ARISPACE_MASK_PMAP_ANIM arispace.ani STRTAB ARISPACE_COLOR_TAB arispace.ct PACKAGE HYPERSPACE_MUSIC_PACKAGE starcon.pkg MUSICRES HYPERSPACE_MUSIC hyper.mod PACKAGE QUASISPACE_MUSIC_PACKAGE starcon.pkg MUSICRES QUASISPACE_MUSIC arispace.mod PATH ipanims PACKAGE INIT_PACKAGE starcon.pkg GFXRES IPBKGND_MASK_PMAP_ANIM obbkgnd.ani PACKAGE IP_PACKAGE starcon.pkg GFXRES SISIP_MASK_PMAP_ANIM sis_ip.ani GFXRES ORBPLAN_MASK_PMAP_ANIM orbplan.ani STRTAB ORBPLAN_COLOR_MAP orbplan.ct GFXRES SUN_MASK_PMAP_ANIM ip_sun.ani PACKAGE LANDER_PACKAGE starcon.pkg GFXRES LANDER_MASK_PMAP_ANIM lander.ani SNDRES LANDER_SOUNDS landsnds.snd GFXRES QUAKE_MASK_PMAP_ANIM quake.ani GFXRES LIGHTNING_MASK_ANIM lightnin.ani GFXRES LAVA_MASK_PMAP_ANIM lavaspot.ani GFXRES LANDER_SHIELD_MASK_ANIM lndrshld.ani GFXRES LANDER_LAUNCH_MASK_PMAP_ANIM launch.ani GFXRES LANDER_RETURN_MASK_PMAP_ANIM return.ani PACKAGE ORBIT_VIEW_PACKAGE starcon.pkg GFXRES ORBIT_VIEW_ANIM orbview.ani PACKAGE EARTH_PACKAGE starcon.pkg GFXRES EARTH_MASK_ANIM eartmask.ani PACKAGE CANNISTER_PACKAGE starcon.pkg GFXRES CANNISTER_MASK_PMAP_ANIM lifecan.ani PACKAGE LIFE00_PACKAGE starcon.pkg GFXRES LIFE00_MASK_PMAP_ANIM lifea.ani PACKAGE LIFE01_PACKAGE starcon.pkg GFXRES LIFE01_MASK_PMAP_ANIM lifeb.ani PACKAGE LIFE02_PACKAGE starcon.pkg GFXRES LIFE02_MASK_PMAP_ANIM lifec.ani PACKAGE LIFE03_PACKAGE starcon.pkg GFXRES LIFE03_MASK_PMAP_ANIM lifed.ani PACKAGE LIFE04_PACKAGE starcon.pkg GFXRES LIFE04_MASK_PMAP_ANIM lifee.ani PACKAGE LIFE05_PACKAGE starcon.pkg GFXRES LIFE05_MASK_PMAP_ANIM lifef.ani PACKAGE LIFE06_PACKAGE starcon.pkg GFXRES LIFE06_MASK_PMAP_ANIM lifeg.ani PACKAGE LIFE07_PACKAGE starcon.pkg GFXRES LIFE07_MASK_PMAP_ANIM lifeh.ani PACKAGE LIFE08_PACKAGE starcon.pkg GFXRES LIFE08_MASK_PMAP_ANIM lifei.ani PACKAGE LIFE09_PACKAGE starcon.pkg GFXRES LIFE09_MASK_PMAP_ANIM lifej.ani PACKAGE LIFE10_PACKAGE starcon.pkg GFXRES LIFE10_MASK_PMAP_ANIM lifek.ani PACKAGE LIFE11_PACKAGE starcon.pkg GFXRES LIFE11_MASK_PMAP_ANIM lifel.ani PACKAGE LIFE12_PACKAGE starcon.pkg GFXRES LIFE12_MASK_PMAP_ANIM lifem.ani PACKAGE LIFE13_PACKAGE starcon.pkg GFXRES LIFE13_MASK_PMAP_ANIM lifen.ani PACKAGE LIFE14_PACKAGE starcon.pkg GFXRES LIFE14_MASK_PMAP_ANIM lifeo.ani PACKAGE LIFE15_PACKAGE starcon.pkg GFXRES LIFE15_MASK_PMAP_ANIM lifep.ani PACKAGE LIFE16_PACKAGE starcon.pkg GFXRES LIFE16_MASK_PMAP_ANIM lifeq.ani PACKAGE LIFE17_PACKAGE starcon.pkg GFXRES LIFE17_MASK_PMAP_ANIM lifer.ani PACKAGE LIFE18_PACKAGE starcon.pkg GFXRES LIFE18_MASK_PMAP_ANIM lifes.ani PACKAGE LIFE19_PACKAGE starcon.pkg GFXRES LIFE19_MASK_PMAP_ANIM lifet.ani PACKAGE LIFE20_PACKAGE starcon.pkg GFXRES LIFE20_MASK_PMAP_ANIM lifew.ani PACKAGE LIFE21_PACKAGE starcon.pkg GFXRES LIFE21_MASK_PMAP_ANIM lifex.ani PACKAGE LIFE22_PACKAGE starcon.pkg GFXRES LIFE22_MASK_PMAP_ANIM lifey.ani PACKAGE LIFE23_PACKAGE starcon.pkg GFXRES LIFE23_MASK_PMAP_ANIM lifeu.ani PACKAGE LIFE24_PACKAGE starcon.pkg GFXRES LIFE24_MASK_PMAP_ANIM lifev.ani PACKAGE LIFE25_PACKAGE starcon.pkg GFXRES LIFE25_MASK_PMAP_ANIM lifez.ani PACKAGE OOLITE_PACKAGE starcon.pkg STRTAB OOLITE_COLOR_TAB str_cts_.ct STRTAB OOLITE_XLAT_TAB mtl2xlts.xlt PACKAGE YTTRIC_COLOR_PACKAGE starcon.pkg STRTAB YTTRIC_COLOR_TAB wr1_cts_.ct PACKAGE YTTRIC_XLAT_PACKAGE starcon.pkg STRTAB YTTRIC_XLAT_TAB rst_xlts.xlt PACKAGE QD_COLOR_PACKAGE starcon.pkg STRTAB QUASI_DEGENERATE_COLOR_TAB co2_cts_.ct PACKAGE QD_XLAT_PACKAGE starcon.pkg STRTAB QUASI_DEGENERATE_XLAT_TAB bnd_xlts.xlt PACKAGE LANTHANIDE_COLOR_PACKAGE starcon.pkg STRTAB LANTHANIDE_COLOR_TAB ylgscts_.ct PACKAGE TREASURE_COLOR_PACKAGE starcon.pkg STRTAB TREASURE_COLOR_TAB lll_cts_.ct PACKAGE UREA_COLOR_PACKAGE starcon.pkg STRTAB UREA_COLOR_TAB ylgscts_.ct PACKAGE UREA_XLAT_PACKAGE starcon.pkg STRTAB UREA_XLAT_TAB den_xlts.xlt PACKAGE METAL_PACKAGE starcon.pkg STRTAB METAL_COLOR_TAB mtl_cts_.ct STRTAB METAL_XLAT_TAB mtl1xlts.xlt PACKAGE RADIOACTIVE_COLOR_PACKAGE starcon.pkg STRTAB RADIOACTIVE_COLOR_TAB rrr_cts_.ct PACKAGE OPALESCENT_COLOR_PACKAGE starcon.pkg STRTAB OPALESCENT_COLOR_TAB ice_cts_.ct PACKAGE OPALESCENT_XLAT_PACKAGE starcon.pkg STRTAB OPALESCENT_XLAT_TAB ice_xlts.xlt PACKAGE CYANIC_COLOR_PACKAGE starcon.pkg STRTAB CYANIC_COLOR_TAB qqq_cts_.ct PACKAGE ACID_COLOR_PACKAGE starcon.pkg STRTAB ACID_COLOR_TAB rst_cts_.ct PACKAGE ALKALI_COLOR_PACKAGE starcon.pkg STRTAB ALKALI_COLOR_TAB bnd_cts_.ct PACKAGE HALIDE_COLOR_PACKAGE starcon.pkg STRTAB HALIDE_COLOR_TAB rdx_cts_.ct PACKAGE GREEN_COLOR_PACKAGE starcon.pkg STRTAB GREEN_COLOR_TAB nnn_cts_.ct PACKAGE COPPER_COLOR_PACKAGE starcon.pkg STRTAB COPPER_COLOR_TAB qqq_cts_.ct PACKAGE CARBIDE_COLOR_PACKAGE starcon.pkg STRTAB CARBIDE_COLOR_TAB rrr_cts_.ct PACKAGE ULTRAMARINE_COLOR_PACKAGE starcon.pkg STRTAB ULTRAMARINE_COLOR_TAB den_cts_.ct PACKAGE NOBLE_COLOR_PACKAGE starcon.pkg STRTAB NOBLE_COLOR_TAB blgscts_.ct PACKAGE AZURE_COLOR_PACKAGE starcon.pkg STRTAB AZURE_COLOR_TAB www_cts_.ct PACKAGE CHONDRITE_PACKAGE starcon.pkg STRTAB CHONDRITE_COLOR_TAB grv_cts_.ct STRTAB CHONDRITE_XLAT_TAB grv_xlts.xlt PACKAGE PURPLE_COLOR_PACKAGE starcon.pkg STRTAB PURPLE_COLOR_TAB vigscts_.ct PACKAGE SUPER_DENSE_COLOR_PACKAGE starcon.pkg STRTAB SUPER_DENSE_COLOR_TAB kkk_cts_.ct PACKAGE PELLUCID_COLOR_PACKAGE starcon.pkg STRTAB PELLUCID_COLOR_TAB prgscts_.ct PACKAGE DUST_COLOR_PACKAGE starcon.pkg STRTAB DUST_COLOR_TAB dst_cts_.ct PACKAGE MAROON_COLOR_PACKAGE starcon.pkg STRTAB MAROON_COLOR_TAB dst_cts_.ct PACKAGE CIMMERIAN_COLOR_PACKAGE starcon.pkg STRTAB CIMMERIAN_COLOR_TAB jjj_cts_.ct PACKAGE INFRARED_COLOR_PACKAGE starcon.pkg STRTAB INFRARED_COLOR_TAB dst_cts_.ct PACKAGE SELENIC_COLOR_PACKAGE starcon.pkg STRTAB SELENIC_COLOR_TAB lit_cts_.ct PACKAGE AURIC_COLOR_PACKAGE starcon.pkg STRTAB AURIC_COLOR_TAB ylgscts_.ct PACKAGE FLUORESCENT_COLOR_PACKAGE starcon.pkg STRTAB FLUORESCENT_COLOR_TAB vigscts_.ct PACKAGE ULTRAVIOLET_COLOR_PACKAGE starcon.pkg STRTAB ULTRAVIOLET_COLOR_TAB vigscts_.ct PACKAGE PLUTONIC_COLOR_PACKAGE starcon.pkg STRTAB PLUTONIC_COLOR_TAB orgscts_.ct PACKAGE RAINBOW_COLOR_PACKAGE starcon.pkg STRTAB RAINBOW_COLOR_TAB rai_cts_.ct STRTAB RAINBOW_XLAT_TAB rai_xlts.xlt PACKAGE CRACKED_PACKAGE starcon.pkg STRTAB CRACKED_COLOR_TAB hel_cts_.ct STRTAB CRACKED_XLAT_TAB hel_xlts.xlt PACKAGE SAPPHIRE_COLOR_PACKAGE starcon.pkg STRTAB SAPPHIRE_COLOR_TAB cry_cts_.ct PACKAGE SAPPHIRE_XLAT_PACKAGE starcon.pkg STRTAB SAPPHIRE_XLAT_TAB cry_xlts.xlt PACKAGE ORGANIC_COLOR_PACKAGE starcon.pkg STRTAB ORGANIC_COLOR_TAB bnd_cts_.ct PACKAGE XENOLITHIC_COLOR_PACKAGE starcon.pkg STRTAB XENOLITHIC_COLOR_TAB cygscts_.ct PACKAGE REDUX_PACKAGE starcon.pkg STRTAB REDUX_COLOR_TAB rdx_cts_.ct STRTAB REDUX_XLAT_TAB rdx1xlts.xlt PACKAGE PRIMORDIAL_COLOR_PACKAGE starcon.pkg STRTAB PRIMORDIAL_COLOR_TAB co2_cts_.ct PACKAGE EMERALD_COLOR_PACKAGE starcon.pkg STRTAB EMERALD_COLOR_TAB eme_cts_.ct PACKAGE CHLORINE_COLOR_PACKAGE starcon.pkg STRTAB CHLORINE_COLOR_TAB rst_cts_.ct PACKAGE CHLORINE_XLAT_PACKAGE starcon.pkg STRTAB CHLORINE_XLAT_TAB h2o_xlts.xlt PACKAGE MAGNETIC_COLOR_PACKAGE starcon.pkg STRTAB MAGNETIC_COLOR_TAB rdx_cts_.ct PACKAGE WATER_COLOR_PACKAGE starcon.pkg STRTAB WATER_COLOR_TAB h2o_cts_.ct PACKAGE TELLURIC_COLOR_PACKAGE starcon.pkg STRTAB TELLURIC_COLOR_TAB h2o_cts_.ct PACKAGE HYDROCARBON_COLOR_PACKAGE starcon.pkg STRTAB HYDROCARBON_COLOR_TAB www_cts_.ct PACKAGE IODINE_COLOR_PACKAGE starcon.pkg STRTAB IODINE_COLOR_TAB co2_cts_.ct PACKAGE VINYLOGOUS_COLOR_PACKAGE starcon.pkg STRTAB VINYLOGOUS_COLOR_TAB wr1_cts_.ct PACKAGE RUBY_COLOR_PACKAGE starcon.pkg STRTAB RUBY_COLOR_TAB rub_cts_.ct PACKAGE MAGMA_COLOR_PACKAGE starcon.pkg STRTAB MAGMA_COLOR_TAB rrr_cts_.ct PACKAGE CRIMSON_COLOR_PACKAGE starcon.pkg STRTAB CRIMSON_COLOR_TAB bbb_cts_.ct PACKAGE GAS_XLAT_PACKAGE starcon.pkg STRTAB GAS_XLAT_TAB gasg.xlt PACKAGE BLU_GAS_CT_PACKAGE starcon.pkg STRTAB BLU_GAS_COLOR_TAB blugasgi.ct PACKAGE CYA_GAS_CT_PACKAGE starcon.pkg STRTAB CYA_GAS_COLOR_TAB cyagasgi.ct PACKAGE GRN_GAS_CT_PACKAGE starcon.pkg STRTAB GRN_GAS_COLOR_TAB grngasgi.ct PACKAGE GRY_GAS_CT_PACKAGE starcon.pkg STRTAB GRY_GAS_COLOR_TAB grygasgi.ct PACKAGE ORA_GAS_CT_PACKAGE starcon.pkg STRTAB ORA_GAS_COLOR_TAB oragasgi.ct PACKAGE PUR_GAS_CT_PACKAGE starcon.pkg STRTAB PUR_GAS_COLOR_TAB purgasgi.ct PACKAGE RED_GAS_CT_PACKAGE starcon.pkg STRTAB RED_GAS_COLOR_TAB redgasgi.ct PACKAGE VIO_GAS_CT_PACKAGE starcon.pkg STRTAB VIO_GAS_COLOR_TAB viogasgi.ct PACKAGE YEL_GAS_CT_PACKAGE starcon.pkg STRTAB YEL_GAS_COLOR_TAB yelgasgi.ct PACKAGE REPORT_PACKAGE starcon.pkg FONTRES LANDER_FONT lander.fon PACKAGE MOONBASE_PACKAGE starcon.pkg GFXRES MOONBASE_MASK_PMAP_ANIM moonbase.ani STRTAB MOONBASE_STRTAB moonbase.txt PACKAGE MAIDENS_PACKAGE starcon.pkg GFXRES MAIDENS_MASK_PMAP_ANIM maidens.ani STRTAB MAIDENS_STRTAB maidens.txt PACKAGE CHMMR_BASE_PACKAGE starcon.pkg STRTAB CHMMR_BASE_STRTAB chmmrbas.txt PACKAGE AQUA_PACKAGE starcon.pkg GFXRES AQUA_MASK_PMAP_ANIM aquhelix.ani STRTAB AQUA_STRTAB aquhelix.txt PACKAGE BURV_BCS_PACKAGE starcon.pkg GFXRES BURV_BCS_MASK_PMAP_ANIM drutrans.ani STRTAB BURV_BCS_STRTAB drutrans.txt PACKAGE TAALO_DEVICE_PACKAGE starcon.pkg GFXRES TAALO_DEVICE_MASK_PMAP_ANIM taadevic.ani STRTAB TAALO_DEVICE_STRTAB taadevic.txt PACKAGE SUN_DEVICE_PACKAGE starcon.pkg GFXRES SUN_DEVICE_MASK_PMAP_ANIM sundevic.ani STRTAB SUN_DEVICE_STRTAB sundevic.txt PACKAGE VAULT_PACKAGE starcon.pkg GFXRES VAULT_MASK_PMAP_ANIM syrvault.ani STRTAB VAULT_STRTAB syrvault.txt PACKAGE WRECK_PACKAGE starcon.pkg GFXRES WRECK_MASK_PMAP_ANIM urqwreck.ani STRTAB WRECK_STRTAB urqwreck.txt PACKAGE BOMB_PACKAGE starcon.pkg GFXRES BOMB_MASK_PMAP_ANIM utwbomb.ani STRTAB BOMB_STRTAB utwbomb.txt PACKAGE BEAST_PACKAGE starcon.pkg STRTAB BEAST_STRTAB vuxbeast.txt PACKAGE EGG_CASE_PACKAGE starcon.pkg GFXRES EGG_CASE_MASK_PMAP_ANIM eggcase.ani STRTAB EGG_CASE_STRTAB eggcase.txt PACKAGE SPAPLUTO_PACKAGE starcon.pkg GFXRES SPAPLUTO_MASK_PMAP_ANIM spapluto.ani STRTAB SPAPLUTO_STRTAB spapluto.txt PACKAGE BURV_RUINS_PACKAGE starcon.pkg STRTAB BURV_RUINS_STRTAB burruins.txt PACKAGE ANDROSYNTH_RUINS_PACKAGE starcon.pkg STRTAB ANDROSYNTH_RUINS_STRTAB andruins.txt PACKAGE DRUUGE_RUINS_PACKAGE starcon.pkg STRTAB DRUUGE_RUINS_STRTAB sphere.txt PACKAGE PKUNK_RUINS_PACKAGE starcon.pkg STRTAB PKUNK_RUINS_STRTAB spindle.txt PACKAGE RACE_RUINS_PACKAGE starcon.pkg GFXRES RUINS_MASK_PMAP_ANIM ruins.ani PACKAGE RACE_RUINS_TEXT_PACKAGE starcon.pkg STRTAB RUINS_STRTAB ruins.txt PACKAGE UMGAH_BCS_PACKAGE starcon.pkg GFXRES UMGAH_BCS_MASK_PMAP_ANIM umgtrans.ani STRTAB UMGAH_BCS_STRTAB umgtrans.txt PACKAGE IP_MUSIC_PACKAGE starcon.pkg MUSICRES IP_MUSIC space.mod PACKAGE ORBIT_MUSIC_PACKAGE starcon.pkg MUSICRES ORBIT1_MUSIC orbit1.mod MUSICRES ORBIT2_MUSIC orbit2.mod MUSICRES ORBIT3_MUSIC orbit3.mod MUSICRES ORBIT4_MUSIC orbit4.mod MUSICRES ORBIT5_MUSIC orbit5.mod PATH melee PACKAGE MELEE_BGROUND_PACKAGE starcon.pkg GFXRES MELEE_SCREEN_PMAP_ANIM melebkgd.ani PACKAGE MELEE_PICK_PACKAGE starcon.pkg GFXRES MELEE_PICK_MASK_PMAP_ANIM melee.ani PATH lbm PACKAGE SC2_SEGUE_PACKAGE starcon.pkg GFXRES SEGUE_PMAP_ANIM segue.ani MUSICRES REDALERT_MUSIC redalert.mod PACKAGE SC2_PICK_PACKAGE starcon.pkg GFXRES SC2_PICK_PMAP_ANIM pickship.ani PATH . PACKAGE ARILOU_CONVERSATION_PACKAGE starcon.pkg RES_INDEX ARILOU_CONVERSATION arilou.con PACKAGE CHMMR_CONVERSATION_PACKAGE starcon.pkg RES_INDEX CHMMR_CONVERSATION chmmr.con PACKAGE COMMANDER_CONVERSATION_PACKAGE starcon.pkg RES_INDEX COMMANDER_CONVERSATION comandr.con PACKAGE ORZ_CONVERSATION_PACKAGE starcon.pkg RES_INDEX ORZ_CONVERSATION orz.con PACKAGE PKUNK_CONVERSATION_PACKAGE starcon.pkg RES_INDEX PKUNK_CONVERSATION pkunk.con PACKAGE SHOFIXTI_CONVERSATION_PACKAGE starcon.pkg RES_INDEX SHOFIXTI_CONVERSATION shofixt.con PACKAGE SPATHI_CONVERSATION_PACKAGE starcon.pkg RES_INDEX SPATHI_CONVERSATION spathi.con PACKAGE SUPOX_CONVERSATION_PACKAGE starcon.pkg RES_INDEX SUPOX_CONVERSATION supox.con PACKAGE THRADD_CONVERSATION_PACKAGE starcon.pkg RES_INDEX THRADD_CONVERSATION thradd.con PACKAGE UTWIG_CONVERSATION_PACKAGE starcon.pkg RES_INDEX UTWIG_CONVERSATION utwig.con PACKAGE VUX_CONVERSATION_PACKAGE starcon.pkg RES_INDEX VUX_CONVERSATION vux.con PACKAGE YEHAT_CONVERSATION_PACKAGE starcon.pkg RES_INDEX YEHAT_CONVERSATION yehat.con PACKAGE MELNORME_CONVERSATION_PACKAGE starcon.pkg RES_INDEX MELNORME_CONVERSATION melnorm.con PACKAGE DRUUGE_CONVERSATION_PACKAGE starcon.pkg RES_INDEX DRUUGE_CONVERSATION druuge.con PACKAGE ILWRATH_CONVERSATION_PACKAGE starcon.pkg RES_INDEX ILWRATH_CONVERSATION ilwrath.con PACKAGE MYCON_CONVERSATION_PACKAGE starcon.pkg RES_INDEX MYCON_CONVERSATION mycon.con PACKAGE SLYLANDRO_CONVERSATION_PACKAGE starcon.pkg RES_INDEX SLYLANDRO_CONVERSATION slyland.con PACKAGE UMGAH_CONVERSATION_PACKAGE starcon.pkg RES_INDEX UMGAH_CONVERSATION umgah.con PACKAGE URQUAN_CONVERSATION_PACKAGE starcon.pkg RES_INDEX URQUAN_CONVERSATION urquan.con PACKAGE ZOQFOTPIK_CONVERSATION_PACKAGE starcon.pkg RES_INDEX ZOQFOTPIK_CONVERSATION zoqfot.con PACKAGE SYREEN_CONVERSATION_PACKAGE starcon.pkg RES_INDEX SYREEN_CONVERSATION syreen.con PACKAGE BLACKURQ_CONVERSATION_PACKAGE starcon.pkg RES_INDEX BLACKURQ_CONVERSATION blackur.con PACKAGE TALKING_PET_CONVERSATION_PACKAGE starcon.pkg RES_INDEX TALKING_PET_CONVERSATION talkpet.con PACKAGE SLYLANDRO_HOME_CONVERSATION_PACKAGE starcon.pkg RES_INDEX SLYLANDRO_HOME_CONVERSATION slyhome.con PATH lbm PACKAGE PLAYER_CONVERSATION_PACKAGE starcon.pkg FONTRES PLAYER_FONT player.fon PATH . PACKAGE SIS_PACKAGE starcon.pkg RES_INDEX SIS_RES_INDEX sis.dat PACKAGE SAMATRA_PACKAGE starcon.pkg RES_INDEX SAMATRA_RES_INDEX lastbat.sc2 PACKAGE URQUAN_PROBE_PACKAGE starcon.pkg RES_INDEX PROBE_RES_INDEX probe.sc2 PATH lbm PACKAGE RESTART_PACKAGE starcon.pkg GFXRES RESTART_PMAP_ANIM newgame.ani PACKAGE MODULE_PACKAGE starcon.pkg GFXRES MODULES_PMAP_ANIM modules.ani PACKAGE OUTFIT_PACKAGE starcon.pkg GFXRES SISMODS_MASK_PMAP_ANIM sismods.ani GFXRES OUTFIT_PMAP_ANIM outfit.ani PACKAGE OUTFIT_MUSIC_PACKAGE starcon.pkg MUSICRES OUTFIT_MUSIC outfit.mod PACKAGE BLUEPRINT_PACKAGE starcon.pkg GFXRES SISBLU_MASK_ANIM sisblu.ani GFXRES SHIPYARD_PMAP_ANIM shipyard.ani PACKAGE SHIPYARD_MUSIC_PACKAGE starcon.pkg MUSICRES SHIPYARD_MUSIC shipyard.mod PACKAGE STARBASE_PACKAGE starcon.pkg MUSICRES STARBASE_MUSIC starbase.mod GFXRES STARBASE_ANIM starbase.ani PACKAGE SAMATRA_BATTLE_PACKAGE starcon.pkg GFXRES SAMATRA_BIG_MASK_PMAP_ANIM sam__big.ani PACKAGE SHIELDED_BATTLE_PACKAGE starcon.pkg GFXRES SHIELDED_BIG_MASK_PMAP_ANIM shie_big.ani GFXRES SHIELDED_MED_MASK_PMAP_ANIM shie_med.ani GFXRES SHIELDED_SML_MASK_PMAP_ANIM shie_sml.ani PACKAGE PLANET00_PACKAGE starcon.pkg GFXRES PLANET00_BIG_MASK_PMAP_ANIM ool__big.ani GFXRES PLANET00_MED_MASK_PMAP_ANIM ool__med.ani GFXRES PLANET00_SML_MASK_PMAP_ANIM ool__sml.ani PACKAGE PLANET01_PACKAGE starcon.pkg GFXRES PLANET01_BIG_MASK_PMAP_ANIM ytt__big.ani GFXRES PLANET01_MED_MASK_PMAP_ANIM ytt__med.ani GFXRES PLANET01_SML_MASK_PMAP_ANIM ytt__sml.ani PACKAGE PLANET02_PACKAGE starcon.pkg GFXRES PLANET02_BIG_MASK_PMAP_ANIM deg__big.ani GFXRES PLANET02_MED_MASK_PMAP_ANIM deg__med.ani GFXRES PLANET02_SML_MASK_PMAP_ANIM deg__sml.ani PACKAGE PLANET03_PACKAGE starcon.pkg GFXRES PLANET03_BIG_MASK_PMAP_ANIM lan__big.ani GFXRES PLANET03_MED_MASK_PMAP_ANIM lan__med.ani GFXRES PLANET03_SML_MASK_PMAP_ANIM lan__sml.ani PACKAGE PLANET04_PACKAGE starcon.pkg GFXRES PLANET04_BIG_MASK_PMAP_ANIM tre__big.ani GFXRES PLANET04_MED_MASK_PMAP_ANIM tre__med.ani GFXRES PLANET04_SML_MASK_PMAP_ANIM tre__sml.ani PACKAGE PLANET05_PACKAGE starcon.pkg GFXRES PLANET05_BIG_MASK_PMAP_ANIM ure__big.ani GFXRES PLANET05_MED_MASK_PMAP_ANIM ure__med.ani GFXRES PLANET05_SML_MASK_PMAP_ANIM ure__sml.ani PACKAGE PLANET06_PACKAGE starcon.pkg GFXRES PLANET06_BIG_MASK_PMAP_ANIM mtl__big.ani GFXRES PLANET06_MED_MASK_PMAP_ANIM mtl__med.ani GFXRES PLANET06_SML_MASK_PMAP_ANIM mtl__sml.ani PACKAGE PLANET07_PACKAGE starcon.pkg GFXRES PLANET07_BIG_MASK_PMAP_ANIM rad__big.ani GFXRES PLANET07_MED_MASK_PMAP_ANIM rad__med.ani GFXRES PLANET07_SML_MASK_PMAP_ANIM rad__sml.ani PACKAGE PLANET08_PACKAGE starcon.pkg GFXRES PLANET08_BIG_MASK_PMAP_ANIM opa__big.ani GFXRES PLANET08_MED_MASK_PMAP_ANIM opa__med.ani GFXRES PLANET08_SML_MASK_PMAP_ANIM opa__sml.ani PACKAGE PLANET09_PACKAGE starcon.pkg GFXRES PLANET09_BIG_MASK_PMAP_ANIM cya__big.ani GFXRES PLANET09_MED_MASK_PMAP_ANIM cya__med.ani GFXRES PLANET09_SML_MASK_PMAP_ANIM cya__sml.ani PACKAGE PLANET10_PACKAGE starcon.pkg GFXRES PLANET10_BIG_MASK_PMAP_ANIM aci__big.ani GFXRES PLANET10_MED_MASK_PMAP_ANIM aci__med.ani GFXRES PLANET10_SML_MASK_PMAP_ANIM aci__sml.ani PACKAGE PLANET11_PACKAGE starcon.pkg GFXRES PLANET11_BIG_MASK_PMAP_ANIM alk__big.ani GFXRES PLANET11_MED_MASK_PMAP_ANIM alk__med.ani GFXRES PLANET11_SML_MASK_PMAP_ANIM alk__sml.ani PACKAGE PLANET12_PACKAGE starcon.pkg GFXRES PLANET12_BIG_MASK_PMAP_ANIM hal__big.ani GFXRES PLANET12_MED_MASK_PMAP_ANIM hal__med.ani GFXRES PLANET12_SML_MASK_PMAP_ANIM hal__sml.ani PACKAGE PLANET13_PACKAGE starcon.pkg GFXRES PLANET13_BIG_MASK_PMAP_ANIM gre__big.ani GFXRES PLANET13_MED_MASK_PMAP_ANIM gre__med.ani GFXRES PLANET13_SML_MASK_PMAP_ANIM gre__sml.ani PACKAGE PLANET14_PACKAGE starcon.pkg GFXRES PLANET14_BIG_MASK_PMAP_ANIM cop__big.ani GFXRES PLANET14_MED_MASK_PMAP_ANIM cop__med.ani GFXRES PLANET14_SML_MASK_PMAP_ANIM cop__sml.ani PACKAGE PLANET15_PACKAGE starcon.pkg GFXRES PLANET15_BIG_MASK_PMAP_ANIM car__big.ani GFXRES PLANET15_MED_MASK_PMAP_ANIM car__med.ani GFXRES PLANET15_SML_MASK_PMAP_ANIM car__sml.ani PACKAGE PLANET16_PACKAGE starcon.pkg GFXRES PLANET16_BIG_MASK_PMAP_ANIM ult__big.ani GFXRES PLANET16_MED_MASK_PMAP_ANIM ult__med.ani GFXRES PLANET16_SML_MASK_PMAP_ANIM ult__sml.ani PACKAGE PLANET17_PACKAGE starcon.pkg GFXRES PLANET17_BIG_MASK_PMAP_ANIM nob__big.ani GFXRES PLANET17_MED_MASK_PMAP_ANIM nob__med.ani GFXRES PLANET17_SML_MASK_PMAP_ANIM nob__sml.ani PACKAGE PLANET18_PACKAGE starcon.pkg GFXRES PLANET18_BIG_MASK_PMAP_ANIM azu__big.ani GFXRES PLANET18_MED_MASK_PMAP_ANIM azu__med.ani GFXRES PLANET18_SML_MASK_PMAP_ANIM azu__sml.ani PACKAGE PLANET19_PACKAGE starcon.pkg GFXRES PLANET19_BIG_MASK_PMAP_ANIM cho__big.ani GFXRES PLANET19_MED_MASK_PMAP_ANIM cho__med.ani GFXRES PLANET19_SML_MASK_PMAP_ANIM cho__sml.ani PACKAGE PLANET20_PACKAGE starcon.pkg GFXRES PLANET20_BIG_MASK_PMAP_ANIM pur__big.ani GFXRES PLANET20_MED_MASK_PMAP_ANIM pur__med.ani GFXRES PLANET20_SML_MASK_PMAP_ANIM pur__sml.ani PACKAGE PLANET21_PACKAGE starcon.pkg GFXRES PLANET21_BIG_MASK_PMAP_ANIM sup__big.ani GFXRES PLANET21_MED_MASK_PMAP_ANIM sup__med.ani GFXRES PLANET21_SML_MASK_PMAP_ANIM sup__sml.ani PACKAGE PLANET22_PACKAGE starcon.pkg GFXRES PLANET22_BIG_MASK_PMAP_ANIM pel__big.ani GFXRES PLANET22_MED_MASK_PMAP_ANIM pel__med.ani GFXRES PLANET22_SML_MASK_PMAP_ANIM pel__sml.ani PACKAGE PLANET23_PACKAGE starcon.pkg GFXRES PLANET23_BIG_MASK_PMAP_ANIM dus__big.ani GFXRES PLANET23_MED_MASK_PMAP_ANIM dus__med.ani GFXRES PLANET23_SML_MASK_PMAP_ANIM dus__sml.ani PACKAGE PLANET24_PACKAGE starcon.pkg GFXRES PLANET24_BIG_MASK_PMAP_ANIM mar__big.ani GFXRES PLANET24_MED_MASK_PMAP_ANIM mar__med.ani GFXRES PLANET24_SML_MASK_PMAP_ANIM mar__sml.ani PACKAGE PLANET25_PACKAGE starcon.pkg GFXRES PLANET25_BIG_MASK_PMAP_ANIM cim__big.ani GFXRES PLANET25_MED_MASK_PMAP_ANIM cim__med.ani GFXRES PLANET25_SML_MASK_PMAP_ANIM cim__sml.ani PACKAGE PLANET26_PACKAGE starcon.pkg GFXRES PLANET26_BIG_MASK_PMAP_ANIM inf__big.ani GFXRES PLANET26_MED_MASK_PMAP_ANIM inf__med.ani GFXRES PLANET26_SML_MASK_PMAP_ANIM inf__sml.ani PACKAGE PLANET27_PACKAGE starcon.pkg GFXRES PLANET27_BIG_MASK_PMAP_ANIM sel__big.ani GFXRES PLANET27_MED_MASK_PMAP_ANIM sel__med.ani GFXRES PLANET27_SML_MASK_PMAP_ANIM sel__sml.ani PACKAGE PLANET28_PACKAGE starcon.pkg GFXRES PLANET28_BIG_MASK_PMAP_ANIM aur__big.ani GFXRES PLANET28_MED_MASK_PMAP_ANIM aur__med.ani GFXRES PLANET28_SML_MASK_PMAP_ANIM aur__sml.ani PACKAGE PLANET29_PACKAGE starcon.pkg GFXRES PLANET29_BIG_MASK_PMAP_ANIM flu__big.ani GFXRES PLANET29_MED_MASK_PMAP_ANIM flu__med.ani GFXRES PLANET29_SML_MASK_PMAP_ANIM flu__sml.ani PACKAGE PLANET30_PACKAGE starcon.pkg GFXRES PLANET30_BIG_MASK_PMAP_ANIM ult__big.ani GFXRES PLANET30_MED_MASK_PMAP_ANIM ult__med.ani GFXRES PLANET30_SML_MASK_PMAP_ANIM ult__sml.ani PACKAGE PLANET31_PACKAGE starcon.pkg GFXRES PLANET31_BIG_MASK_PMAP_ANIM plu__big.ani GFXRES PLANET31_MED_MASK_PMAP_ANIM plu__med.ani GFXRES PLANET31_SML_MASK_PMAP_ANIM plu__sml.ani PACKAGE PLANET32_PACKAGE starcon.pkg GFXRES PLANET32_BIG_MASK_PMAP_ANIM rai__big.ani GFXRES PLANET32_MED_MASK_PMAP_ANIM rai__med.ani GFXRES PLANET32_SML_MASK_PMAP_ANIM rai__sml.ani PACKAGE PLANET33_PACKAGE starcon.pkg GFXRES PLANET33_BIG_MASK_PMAP_ANIM cra__big.ani GFXRES PLANET33_MED_MASK_PMAP_ANIM cra__med.ani GFXRES PLANET33_SML_MASK_PMAP_ANIM cra__sml.ani PACKAGE PLANET34_PACKAGE starcon.pkg GFXRES PLANET34_BIG_MASK_PMAP_ANIM sap__big.ani GFXRES PLANET34_MED_MASK_PMAP_ANIM sap__med.ani GFXRES PLANET34_SML_MASK_PMAP_ANIM sap__sml.ani PACKAGE PLANET35_PACKAGE starcon.pkg GFXRES PLANET35_BIG_MASK_PMAP_ANIM org__big.ani GFXRES PLANET35_MED_MASK_PMAP_ANIM org__med.ani GFXRES PLANET35_SML_MASK_PMAP_ANIM org__sml.ani PACKAGE PLANET36_PACKAGE starcon.pkg GFXRES PLANET36_BIG_MASK_PMAP_ANIM xen__big.ani GFXRES PLANET36_MED_MASK_PMAP_ANIM xen__med.ani GFXRES PLANET36_SML_MASK_PMAP_ANIM xen__sml.ani PACKAGE PLANET37_PACKAGE starcon.pkg GFXRES PLANET37_BIG_MASK_PMAP_ANIM red__big.ani GFXRES PLANET37_MED_MASK_PMAP_ANIM red__med.ani GFXRES PLANET37_SML_MASK_PMAP_ANIM red__sml.ani PACKAGE PLANET38_PACKAGE starcon.pkg GFXRES PLANET38_BIG_MASK_PMAP_ANIM pri__big.ani GFXRES PLANET38_MED_MASK_PMAP_ANIM pri__med.ani GFXRES PLANET38_SML_MASK_PMAP_ANIM pri__sml.ani PACKAGE PLANET39_PACKAGE starcon.pkg GFXRES PLANET39_BIG_MASK_PMAP_ANIM eme__big.ani GFXRES PLANET39_MED_MASK_PMAP_ANIM eme__med.ani GFXRES PLANET39_SML_MASK_PMAP_ANIM eme__sml.ani PACKAGE PLANET40_PACKAGE starcon.pkg GFXRES PLANET40_BIG_MASK_PMAP_ANIM chl__big.ani GFXRES PLANET40_MED_MASK_PMAP_ANIM chl__med.ani GFXRES PLANET40_SML_MASK_PMAP_ANIM chl__sml.ani PACKAGE PLANET41_PACKAGE starcon.pkg GFXRES PLANET41_BIG_MASK_PMAP_ANIM mgn__big.ani GFXRES PLANET41_MED_MASK_PMAP_ANIM mgn__med.ani GFXRES PLANET41_SML_MASK_PMAP_ANIM mgn__sml.ani PACKAGE PLANET42_PACKAGE starcon.pkg GFXRES PLANET42_BIG_MASK_PMAP_ANIM wat__big.ani GFXRES PLANET42_MED_MASK_PMAP_ANIM wat__med.ani GFXRES PLANET42_SML_MASK_PMAP_ANIM wat__sml.ani PACKAGE PLANET43_PACKAGE starcon.pkg GFXRES PLANET43_BIG_MASK_PMAP_ANIM tel__big.ani GFXRES PLANET43_MED_MASK_PMAP_ANIM tel__med.ani GFXRES PLANET43_SML_MASK_PMAP_ANIM tel__sml.ani PACKAGE PLANET44_PACKAGE starcon.pkg GFXRES PLANET44_BIG_MASK_PMAP_ANIM hyd__big.ani GFXRES PLANET44_MED_MASK_PMAP_ANIM hyd__med.ani GFXRES PLANET44_SML_MASK_PMAP_ANIM hyd__sml.ani PACKAGE PLANET45_PACKAGE starcon.pkg GFXRES PLANET45_BIG_MASK_PMAP_ANIM iod__big.ani GFXRES PLANET45_MED_MASK_PMAP_ANIM iod__med.ani GFXRES PLANET45_SML_MASK_PMAP_ANIM iod__sml.ani PACKAGE PLANET46_PACKAGE starcon.pkg GFXRES PLANET46_BIG_MASK_PMAP_ANIM vin__big.ani GFXRES PLANET46_MED_MASK_PMAP_ANIM vin__med.ani GFXRES PLANET46_SML_MASK_PMAP_ANIM vin__sml.ani PACKAGE PLANET47_PACKAGE starcon.pkg GFXRES PLANET47_BIG_MASK_PMAP_ANIM rub__big.ani GFXRES PLANET47_MED_MASK_PMAP_ANIM rub__med.ani GFXRES PLANET47_SML_MASK_PMAP_ANIM rub__sml.ani PACKAGE PLANET48_PACKAGE starcon.pkg GFXRES PLANET48_BIG_MASK_PMAP_ANIM mgm__big.ani GFXRES PLANET48_MED_MASK_PMAP_ANIM mgm__med.ani GFXRES PLANET48_SML_MASK_PMAP_ANIM mgm__sml.ani PACKAGE PLANET49_PACKAGE starcon.pkg GFXRES PLANET49_BIG_MASK_PMAP_ANIM cri__big.ani GFXRES PLANET49_MED_MASK_PMAP_ANIM cri__med.ani GFXRES PLANET49_SML_MASK_PMAP_ANIM cri__sml.ani PACKAGE PLANET50_PACKAGE starcon.pkg GFXRES PLANET50_BIG_MASK_PMAP_ANIM blg__big.ani GFXRES PLANET50_MED_MASK_PMAP_ANIM blg__med.ani GFXRES PLANET50_SML_MASK_PMAP_ANIM blg__sml.ani PACKAGE PLANET51_PACKAGE starcon.pkg GFXRES PLANET51_BIG_MASK_PMAP_ANIM cyg__big.ani GFXRES PLANET51_MED_MASK_PMAP_ANIM cyg__med.ani GFXRES PLANET51_SML_MASK_PMAP_ANIM cyg__sml.ani PACKAGE PLANET52_PACKAGE starcon.pkg GFXRES PLANET52_BIG_MASK_PMAP_ANIM gng__big.ani GFXRES PLANET52_MED_MASK_PMAP_ANIM gng__med.ani GFXRES PLANET52_SML_MASK_PMAP_ANIM gng__sml.ani PACKAGE PLANET53_PACKAGE starcon.pkg GFXRES PLANET53_BIG_MASK_PMAP_ANIM gyg__big.ani GFXRES PLANET53_MED_MASK_PMAP_ANIM gyg__med.ani GFXRES PLANET53_SML_MASK_PMAP_ANIM gyg__sml.ani PACKAGE PLANET54_PACKAGE starcon.pkg GFXRES PLANET54_BIG_MASK_PMAP_ANIM org__big.ani GFXRES PLANET54_MED_MASK_PMAP_ANIM org__med.ani GFXRES PLANET54_SML_MASK_PMAP_ANIM org__sml.ani PACKAGE PLANET55_PACKAGE starcon.pkg GFXRES PLANET55_BIG_MASK_PMAP_ANIM pug__big.ani GFXRES PLANET55_MED_MASK_PMAP_ANIM pug__med.ani GFXRES PLANET55_SML_MASK_PMAP_ANIM pug__sml.ani PACKAGE PLANET56_PACKAGE starcon.pkg GFXRES PLANET56_BIG_MASK_PMAP_ANIM reg__big.ani GFXRES PLANET56_MED_MASK_PMAP_ANIM reg__med.ani GFXRES PLANET56_SML_MASK_PMAP_ANIM reg__sml.ani PACKAGE PLANET57_PACKAGE starcon.pkg GFXRES PLANET57_BIG_MASK_PMAP_ANIM vig__big.ani GFXRES PLANET57_MED_MASK_PMAP_ANIM vig__med.ani GFXRES PLANET57_SML_MASK_PMAP_ANIM vig__sml.ani PACKAGE PLANET58_PACKAGE starcon.pkg GFXRES PLANET58_BIG_MASK_PMAP_ANIM yeg__big.ani GFXRES PLANET58_MED_MASK_PMAP_ANIM yeg__med.ani GFXRES PLANET58_SML_MASK_PMAP_ANIM yeg__sml.ani PACKAGE BATTLE_MUSIC_PACKAGE starcon.pkg MUSICRES BATTLE_MUSIC battle.mod PACKAGE CREDIT00_PACKAGE starcon.pkg GFXRES CREDIT00_ANIM credit00.ani PACKAGE CREDIT01_PACKAGE starcon.pkg GFXRES CREDIT01_ANIM credit01.ani PACKAGE CREDIT02_PACKAGE starcon.pkg GFXRES CREDIT02_ANIM credit02.ani PACKAGE CREDIT03_PACKAGE starcon.pkg GFXRES CREDIT03_ANIM credit03.ani PACKAGE CREDIT04_PACKAGE starcon.pkg GFXRES CREDIT04_ANIM credit04.ani PACKAGE CREDIT05_PACKAGE starcon.pkg GFXRES CREDIT05_ANIM credit05.ani PACKAGE CREDIT06_PACKAGE starcon.pkg GFXRES CREDIT06_ANIM credit06.ani PACKAGE CREDIT07_PACKAGE starcon.pkg GFXRES CREDIT07_ANIM credit07.ani PACKAGE CREDIT08_PACKAGE starcon.pkg GFXRES CREDIT08_ANIM credit08.ani PACKAGE CREDIT09_PACKAGE starcon.pkg GFXRES CREDIT09_ANIM credit09.ani PACKAGE CREDIT10_PACKAGE starcon.pkg GFXRES CREDIT10_ANIM credit10.ani PACKAGE CREDIT11_PACKAGE starcon.pkg GFXRES CREDIT11_ANIM credit11.ani PACKAGE CREDIT12_PACKAGE starcon.pkg GFXRES CREDIT12_ANIM credit12.ani PACKAGE CREDIT13_PACKAGE starcon.pkg GFXRES CREDIT13_ANIM credit13.ani PACKAGE CREDIT14_PACKAGE starcon.pkg GFXRES CREDIT14_ANIM credit14.ani PACKAGE CREDIT15_PACKAGE starcon.pkg GFXRES CREDIT15_ANIM credit15.ani PACKAGE CREDIT16_PACKAGE starcon.pkg GFXRES CREDIT16_ANIM credit16.ani PACKAGE CREDIT17_PACKAGE starcon.pkg GFXRES CREDIT17_ANIM credit17.ani PACKAGE CREDIT18_PACKAGE starcon.pkg GFXRES CREDIT18_ANIM credit18.ani PACKAGE CREDIT19_PACKAGE starcon.pkg GFXRES CREDIT19_ANIM credit19.ani PACKAGE CREDIT_MUSIC_PACKAGE starcon.pkg MUSICRES CREDITS_MUSIC credits.mod uqm-0.6.2/sc2/src/sc2code/planets/0000755000175000017500000000000010552600274015266 5ustar joeyjoeyuqm-0.6.2/sc2/src/sc2code/planets/genthrad.c0000600000175000017500000001510610543202100017203 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "nameref.h" #include "resinst.h" #include "setup.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateThradd (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { DWORD rand_val, old_rand; if (CurStarDescPtr->Index != AQUA_HELIX_DEFINED) { COUNT i, which_node; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } else if (!GET_GAME_STATE (AQUA_HELIX)) { old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; pSolarSysState->SysInfo.PlanetInfo.CurType = 0; if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; else { pSolarSysState->CurNode = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { SET_GAME_STATE (HELIX_VISITS, 0); SET_GAME_STATE (AQUA_HELIX, 1); SET_GAME_STATE (AQUA_HELIX_ON_SHIP, 1); SET_GAME_STATE (HELIX_UNPROTECTED, 1); } } TFB_SeedRandom (old_rand); break; } } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); if (CurStarDescPtr->Index == AQUA_HELIX_DEFINED) { pSolarSysState->PlanetDesc[0].data_index = PRIMORDIAL_WORLD; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 65L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); } else { pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 0; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 98L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); } break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { if (ActivateStarShip (THRADDASH_SHIP, SPHERE_TRACKING) && (CurStarDescPtr->Index == THRADD_DEFINED || (!GET_GAME_STATE (HELIX_UNPROTECTED) && (BYTE)(GET_GAME_STATE (THRADD_MISSION) - 1) >= 3))) { NotifyOthers (THRADDASH_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (THRADDASH_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; if (CurStarDescPtr->Index == THRADD_DEFINED) { SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); } else { SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); } InitCommunication (THRADD_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) break; GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); if (CurStarDescPtr->Index == THRADD_DEFINED || (!GET_GAME_STATE (HELIX_UNPROTECTED) && (BYTE)(GET_GAME_STATE (THRADD_MISSION) - 1) >= 3)) break; LockMutex (GraphicsLock); RepairSISBorder (); UnlockMutex (GraphicsLock); } if (CurStarDescPtr->Index == AQUA_HELIX_DEFINED && !GET_GAME_STATE (AQUA_HELIX)) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (AQUA_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (AQUA_STRTAB) ); } else if (CurStarDescPtr->Index == THRADD_DEFINED) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (RUINS_STRTAB) ); } } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/pl_stuff.c0000600000175000017500000001260110543202100017226 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "planets/planets.h" #include "setup.h" #include "libs/graphics/gfx_common.h" #include "libs/graphics/drawable.h" #include "planets/scan.h" #include // define USE_ADDITIVE_SCAN_BLIT to use additive blittting // instead of transparency for the planet scans. // It still doesn't look right though (it is too bright) #define USE_ADDITIVE_SCAN_BLIT // XXX: these are currently defined in libs/graphics/sdl/3do_getbody.c // they should be sorted out and cleaned up at some point extern DWORD frame_mapRGBA (FRAME FramePtr, UBYTE r, UBYTE g, UBYTE b, UBYTE a); extern void fill_frame_rgb (FRAME FramePtr, DWORD color, int x0, int y0, int x, int y); extern void arith_frame_blit (FRAME srcFrame, RECT *rsrc, FRAME dstFrame, RECT *rdst, int num, int denom); // RotatePlanet // This will take care of zooming into a planet on orbit, generating the planet frames // And applying the shield. // The speed to zoom in. #define PLANET_ZOOM_SPEED 2 PRECT RotatePlanet (int x, int dx, int dy, COUNT scale_amt, UBYTE zoom_from, PRECT zoomr) { STAMP s; FRAME pFrame[2]; COUNT i, num_frames, old_scale; RECT *rp = NULL; CONTEXT OldContext; PLANET_ORBIT *Orbit = &pSolarSysState->Orbit; int base = GSCALE_IDENTITY; num_frames = 1; pFrame[0] = Orbit->PlanetFrameArray; if (Orbit->ObjectFrame) { pFrame[1] = Orbit->ObjectFrame; num_frames++; } if (scale_amt) { if (zoomr->extent.width) rp = zoomr; // we're zooming in, take care of scaling the frames //Translate the planet so it comes from the bottom right corner dx += ((zoom_from & 0x01) ? 1 : -1) * dx * (base - scale_amt) / base; dy += ((zoom_from & 0x02) ? 1 : -1) * dy * (base - scale_amt) / base; } //LockMutex (GraphicsLock); // PauseRotate needs to be checked twice. It is first checked // at the rotate_planet_task function to bypass rendering the // planet (and thus slowinng down other parts of te code. It // is checked here because it is possile that PauseRotate was // set between then and now, and we don't want too push // anything onto the DrawQueue in that case. If the locking // operation is moved before the RenderLevelMasks call, one of // the two PauseRotate checks can be removed. //if (((PSOLARSYS_STATE volatile)pSolarSysState)->PauseRotate !=1) { OldContext = SetContext (SpaceContext); BatchGraphics (); if (rp) RepairBackRect (rp); s.origin.x = dx; s.origin.y = dy; old_scale = GetGraphicScale (); SetGraphicScale (scale_amt); for (i = 0; i < num_frames; i++) { s.frame = pFrame[i]; DrawStamp (&s); } SetGraphicScale (old_scale); UnbatchGraphics (); SetContext (OldContext); } //UnlockMutex (GraphicsLock); if (scale_amt && scale_amt != base) { GetFrameRect (pFrame[num_frames - 1], zoomr); zoomr->corner.x += dx; zoomr->corner.y += dy; return zoomr; } return NULL; (void)x; // unused param } void DrawPlanet (int x, int y, int dy, unsigned int rgb) { STAMP s; UBYTE a = 128; PLANET_ORBIT *Orbit = &pSolarSysState->Orbit; s.origin.x = x; s.origin.y = y; s.frame = pSolarSysState->TopoFrame; BatchGraphics (); if (! rgb) { // no tint -- just draw the surface DrawStamp (&s); } else { // apply different scan type tints UBYTE r, g, b; DWORD p; COUNT framew, frameh; RECT srect, drect, *psrect = NULL, *pdrect = NULL; FRAME tintFrame[2]; tintFrame[0] = SetAbsFrameIndex (Orbit->TintFrame, 0); tintFrame[1] = SetAbsFrameIndex (Orbit->TintFrame, 1); framew = GetFrameWidth (tintFrame[0]); frameh = GetFrameHeight (tintFrame[0]); if (rgb != pSolarSysState->Tint_rgb) { pSolarSysState->Tint_rgb = rgb; // Buffer the topoMap to the tintFrame; arith_frame_blit (s.frame, NULL, tintFrame[0], NULL, 0, 0); r = (rgb & (0x1f << 10)) >> 8; g = (rgb & (0x1f << 5)) >> 3; b = (rgb & 0x1f) << 2; #ifdef USE_ADDITIVE_SCAN_BLIT a = 255; #endif p = frame_mapRGBA (tintFrame[1], r, g, b, a); fill_frame_rgb (tintFrame[1], p, 0, 0, 0, 0); } drect.corner.x = 0; drect.extent.width = framew; srect.corner.x = 0; srect.corner.y = 0; srect.extent.width = framew; if (dy >= 0 && dy <= frameh) { drect.corner.y = dy; drect.extent.height = 1; pdrect = &drect; srect.extent.height = 1; psrect = &srect; } if (dy < 0) { drect.corner.y = -dy; drect.extent.height = frameh + dy; pdrect = &drect; srect.extent.height = frameh + dy; psrect = &srect; } if (dy <= frameh) { #ifdef USE_ADDITIVE_SCAN_BLIT arith_frame_blit (tintFrame[1], psrect, tintFrame[0], pdrect, 0, -1); #else arith_frame_blit (tintFrame[1], psrect, tintFrame[0], pdrect, 0, 0); #endif } s.frame = tintFrame[0]; DrawStamp (&s); } UnbatchGraphics (); } uqm-0.6.2/sc2/src/sc2code/planets/gendru.c0000600000175000017500000001156610543202100016701 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "lander.h" #include "nameref.h" #include "resinst.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateDruuge (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i, which_node; DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; if (!GET_GAME_STATE (ROSY_SPHERE)) pSolarSysState->SysInfo.PlanetInfo.CurType = 0; else pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i)) { pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << i); if (!GET_GAME_STATE (ROSY_SPHERE)) { ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; SET_GAME_STATE (ROSY_SPHERE, 1); SET_GAME_STATE (ROSY_SPHERE_ON_SHIP, 1); } } if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); memmove (&pSolarSysState->PlanetDesc[1], &pSolarSysState->PlanetDesc[0], sizeof (pSolarSysState->PlanetDesc[0]) * pSolarSysState->SunDesc[0].NumPlanets); ++pSolarSysState->SunDesc[0].NumPlanets; pSolarSysState->PlanetDesc[0].data_index = DUST_WORLD; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 50L / 100; pSolarSysState->PlanetDesc[0].NumPlanets = 0; angle = HALF_CIRCLE - OCTANT; pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].rand_seed = MAKE_DWORD ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { if (ActivateStarShip (DRUUGE_SHIP, SPHERE_TRACKING)) { NotifyOthers (DRUUGE_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (DRUUGE_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); InitCommunication (DRUUGE_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } else { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (DRUUGE_RUINS_STRTAB) ); if (GET_GAME_STATE (ROSY_SPHERE)) pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetAbsStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 1 ); } } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/scan.c0000600000175000017500000011000410543202100016324 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "controls.h" #include "encount.h" #include "gamestr.h" #include "lifeform.h" #include "nameref.h" #include "options.h" #include "resinst.h" #include "settings.h" #include "load.h" #include "util.h" #include "lander.h" #include "setup.h" #include "sounds.h" #include "state.h" #include "libs/graphics/gfx_common.h" #include "libs/inplib.h" #include "libs/mathlib.h" extern FRAME SpaceJunkFrame; // define SPIN_ON_SCAN to allow the planet to spin // while scaning is going on #undef SPIN_ON_SCAN #define FLASH_INDEX 105 #define FLASH_WIDTH 9 #define FLASH_HEIGHT 9 CONTEXT ScanContext; void RepairBackRect (PRECT pRect) { RECT new_r, old_r; GetContextClipRect (&old_r); new_r.corner.x = pRect->corner.x + old_r.corner.x; new_r.corner.y = pRect->corner.y + old_r.corner.y; new_r.extent = pRect->extent; new_r.extent.height += new_r.corner.y & 1; new_r.corner.y &= ~1; DrawFromExtraScreen (&new_r); } static void EraseCoarseScan (void) { RECT r, tr; const int leftScanWidth = 80; const int rightScanWidth = 80; const int leftScanOffset = 5; const int rightScanOffset = 50; const int nameEraseWidth = SIS_SCREEN_WIDTH - 2; LockMutex (GraphicsLock); SetContext (SpaceContext); r.corner.x = (SIS_SCREEN_WIDTH >> 1) - (nameEraseWidth >> 1); r.corner.y = 13 - 10; r.extent.width = nameEraseWidth; r.extent.height = 14; RepairBackRect (&r); GetFrameRect (SetAbsFrameIndex (SpaceJunkFrame, 20), &tr); r = tr; r.corner.x += leftScanOffset; r.extent.width = leftScanWidth; RepairBackRect (&r); r = tr; r.corner.x += (r.extent.width - rightScanOffset); r.extent.width = rightScanWidth; RepairBackRect (&r); UnlockMutex (GraphicsLock); } static void PrintScanTitlePC (TEXT *t, RECT *r, const char *txt, int xpos) { t->baseline.x = xpos; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x15), 0x3B)); t->pStr = txt; t->CharCount = (COUNT)~0; font_DrawText (t); TextRect (t, r, NULL_PTR); t->baseline.x += r->extent.width; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x19), 0x3B)); } static void MakeScanValue (UNICODE *buf, long val, const UNICODE *extra) { if (val >= 10 * 100) { // 1 decimal place sprintf (buf, "%ld.%ld%s", val / 100, (val / 10) % 10, extra); } else { // 2 decimal places sprintf (buf, "%ld.%02ld%s", val / 100, val % 100, extra); } } static void PrintCoarseScanPC (void) { #define SCAN_LEADING_PC 14 SDWORD val; TEXT t; RECT r; UNICODE buf[200]; LockMutex (GraphicsLock); SetContext (SpaceContext); if (CurStarDescPtr->Index == SOL_DEFINED) { if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->SunDesc[0]) utf8StringCopy (buf, sizeof (buf), GLOBAL_SIS (PlanetName)); else { switch (pSolarSysState->pOrbitalDesc->pPrevDesc - pSolarSysState->PlanetDesc) { case 2: /* EARTH */ utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 9)); break; case 4: /* JUPITER */ switch (pSolarSysState->pOrbitalDesc - pSolarSysState->MoonDesc) { case 0: utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 10)); break; case 1: utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 11)); break; case 2: utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 12)); break; case 3: utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 13)); break; } break; case 5: /* SATURN */ utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 14)); break; case 7: /* NEPTUNE */ utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 15)); break; } } } else { val = pSolarSysState->pOrbitalDesc->data_index & ~PLANET_SHIELDED; if (val >= FIRST_GAS_GIANT) sprintf (buf, "%s", GAME_STRING (SCAN_STRING_BASE + 4 + 51)); else sprintf (buf, "%s %s", GAME_STRING (SCAN_STRING_BASE + 4 + val), GAME_STRING (SCAN_STRING_BASE + 4 + 50)); } t.align = ALIGN_CENTER; t.baseline.x = SIS_SCREEN_WIDTH >> 1; t.baseline.y = 13; t.pStr = buf; t.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x15), 0x3B)); SetContextFont (MicroFont); font_DrawText (&t); SetContextFont (TinyFont); UnlockMutex (GraphicsLock); #define LEFT_SIDE_BASELINE_X_PC 5 #define RIGHT_SIDE_BASELINE_X_PC (SIS_SCREEN_WIDTH - 75) #define SCAN_BASELINE_Y_PC 40 t.baseline.y = SCAN_BASELINE_Y_PC; t.align = ALIGN_LEFT; LockMutex (GraphicsLock); PrintScanTitlePC (&t, &r, GAME_STRING (ORBITSCAN_STRING_BASE), LEFT_SIDE_BASELINE_X_PC); // "Orbit: " val = ((pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist * 100L + (EARTH_RADIUS >> 1)) / EARTH_RADIUS); MakeScanValue (buf, val, GAME_STRING (ORBITSCAN_STRING_BASE + 1)); // " a.u." t.pStr = buf; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING_PC; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); PrintScanTitlePC (&t, &r, GAME_STRING (ORBITSCAN_STRING_BASE + 2), LEFT_SIDE_BASELINE_X_PC); // "Atmo: " if (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity == GAS_GIANT_ATMOSPHERE) utf8StringCopy (buf, sizeof (buf), GAME_STRING (ORBITSCAN_STRING_BASE + 3)); // "Super Thick" else if (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity == 0) utf8StringCopy (buf, sizeof (buf), GAME_STRING (ORBITSCAN_STRING_BASE + 4)); // "Vacuum" else { val = (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity * 100 + (EARTH_ATMOSPHERE >> 1)) / EARTH_ATMOSPHERE; MakeScanValue (buf, val, GAME_STRING (ORBITSCAN_STRING_BASE + 5)); // " atm" } t.pStr = buf; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING_PC; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); PrintScanTitlePC (&t, &r, GAME_STRING (ORBITSCAN_STRING_BASE + 6), LEFT_SIDE_BASELINE_X_PC); // "Temp: " sprintf (buf, "%d" STR_DEGREE_SIGN " c", pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature); t.pStr = buf; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING_PC; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); PrintScanTitlePC (&t, &r, GAME_STRING (ORBITSCAN_STRING_BASE + 7), LEFT_SIDE_BASELINE_X_PC); // "Weather: " if (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity == 0) t.pStr = GAME_STRING (ORBITSCAN_STRING_BASE + 8); // "None" else { sprintf (buf, "%s %u", GAME_STRING (ORBITSCAN_STRING_BASE + 9), // "Class" pSolarSysState->SysInfo.PlanetInfo.Weather + 1); t.pStr = buf; } t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING_PC; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); PrintScanTitlePC (&t, &r, GAME_STRING (ORBITSCAN_STRING_BASE + 10), LEFT_SIDE_BASELINE_X_PC); // "Tectonics: " if (PLANSIZE (pSolarSysState->SysInfo.PlanetInfo.PlanDataPtr->Type) == GAS_GIANT) t.pStr = GAME_STRING (ORBITSCAN_STRING_BASE + 8); // "None" else { sprintf (buf, "%s %u", GAME_STRING (ORBITSCAN_STRING_BASE + 9), // "Class" pSolarSysState->SysInfo.PlanetInfo.Tectonics + 1); t.pStr = buf; } t.CharCount = (COUNT)~0; font_DrawText (&t); UnlockMutex (GraphicsLock); t.baseline.y = SCAN_BASELINE_Y_PC; LockMutex (GraphicsLock); PrintScanTitlePC (&t, &r, GAME_STRING (ORBITSCAN_STRING_BASE + 11), RIGHT_SIDE_BASELINE_X_PC); // "Mass: " val = pSolarSysState->SysInfo.PlanetInfo.PlanetRadius; val = (val * val * val / 100L * pSolarSysState->SysInfo.PlanetInfo.PlanetDensity + ((100L * 100L) >> 1)) / (100L * 100L); if (val == 0) val = 1; MakeScanValue (buf, val, GAME_STRING (ORBITSCAN_STRING_BASE + 12)); // " e.s." t.pStr = buf; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING_PC; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); PrintScanTitlePC (&t, &r, GAME_STRING (ORBITSCAN_STRING_BASE + 13), RIGHT_SIDE_BASELINE_X_PC); // "Radius: " val = pSolarSysState->SysInfo.PlanetInfo.PlanetRadius; MakeScanValue (buf, val, GAME_STRING (ORBITSCAN_STRING_BASE + 12)); // " e.s." t.pStr = buf; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING_PC; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); PrintScanTitlePC (&t, &r, GAME_STRING (ORBITSCAN_STRING_BASE + 14), RIGHT_SIDE_BASELINE_X_PC); // "Gravity: " val = pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity; if (val == 0) val = 1; MakeScanValue (buf, val, GAME_STRING (ORBITSCAN_STRING_BASE + 15)); // " g." t.pStr = buf; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING_PC; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); PrintScanTitlePC (&t, &r, GAME_STRING (ORBITSCAN_STRING_BASE + 16), RIGHT_SIDE_BASELINE_X_PC); // "Day: " val = (SDWORD)pSolarSysState->SysInfo.PlanetInfo.RotationPeriod * 10 / 24; MakeScanValue (buf, val, GAME_STRING (ORBITSCAN_STRING_BASE + 17)); // " days" t.pStr = buf; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING_PC; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); PrintScanTitlePC (&t, &r, GAME_STRING (ORBITSCAN_STRING_BASE + 18), RIGHT_SIDE_BASELINE_X_PC); // "Tilt: " val = pSolarSysState->SysInfo.PlanetInfo.AxialTilt; if (val < 0) val = -val; t.pStr = buf; sprintf (buf, "%d" STR_DEGREE_SIGN, val); t.CharCount = (COUNT)~0; font_DrawText (&t); UnlockMutex (GraphicsLock); } static void PrintCoarseScan3DO (void) { #define SCAN_LEADING 19 SDWORD val; TEXT t; STAMP s; UNICODE buf[200]; LockMutex (GraphicsLock); SetContext (SpaceContext); if (CurStarDescPtr->Index == SOL_DEFINED) { if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->SunDesc[0]) utf8StringCopy (buf, sizeof (buf), GLOBAL_SIS (PlanetName)); else { switch (pSolarSysState->pOrbitalDesc->pPrevDesc - pSolarSysState->PlanetDesc) { case 2: /* EARTH */ utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 9)); break; case 4: /* JUPITER */ switch (pSolarSysState->pOrbitalDesc - pSolarSysState->MoonDesc) { case 0: utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 10)); break; case 1: utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 11)); break; case 2: utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 12)); break; case 3: utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 13)); break; } break; case 5: /* SATURN */ utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 14)); break; case 7: /* NEPTUNE */ utf8StringCopy (buf, sizeof (buf), GAME_STRING (PLANET_NUMBER_BASE + 15)); break; } } } else { val = pSolarSysState->pOrbitalDesc->data_index & ~PLANET_SHIELDED; if (val >= FIRST_GAS_GIANT) sprintf (buf, "%s", GAME_STRING (SCAN_STRING_BASE + 4 + 51)); else sprintf (buf, "%s %s", GAME_STRING (SCAN_STRING_BASE + 4 + val), GAME_STRING (SCAN_STRING_BASE + 4 + 50)); } t.align = ALIGN_CENTER; t.baseline.x = SIS_SCREEN_WIDTH >> 1; t.baseline.y = 13; t.pStr = buf; t.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x19), 0x3B)); SetContextFont (MicroFont); font_DrawText (&t); s.origin.x = s.origin.y = 0; s.origin.x = 16 - SAFE_X; s.frame = SetAbsFrameIndex (SpaceJunkFrame, 20); DrawStamp (&s); UnlockMutex (GraphicsLock); #define LEFT_SIDE_BASELINE_X (27 + (16 - SAFE_X)) #define RIGHT_SIDE_BASELINE_X (SIS_SCREEN_WIDTH - LEFT_SIDE_BASELINE_X) #define SCAN_BASELINE_Y 25 t.baseline.x = LEFT_SIDE_BASELINE_X; t.baseline.y = SCAN_BASELINE_Y; t.align = ALIGN_LEFT; LockMutex (GraphicsLock); t.pStr = buf; val = ((pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist * 100L + (EARTH_RADIUS >> 1)) / EARTH_RADIUS); MakeScanValue (buf, val, STR_EARTH_SIGN); t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); t.pStr = buf; if (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity == GAS_GIANT_ATMOSPHERE) strcpy (buf, STR_INFINITY_SIGN); else { val = (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity * 100 + (EARTH_ATMOSPHERE >> 1)) / EARTH_ATMOSPHERE; MakeScanValue (buf, val, STR_EARTH_SIGN); } t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); t.pStr = buf; sprintf (buf, "%d" STR_DEGREE_SIGN, pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature); t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); t.pStr = buf; sprintf (buf, "<%u>", pSolarSysState->SysInfo.PlanetInfo.AtmoDensity == 0 ? 0 : (pSolarSysState->SysInfo.PlanetInfo.Weather + 1)); t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); t.pStr = buf; sprintf (buf, "<%u>", PLANSIZE ( pSolarSysState->SysInfo.PlanetInfo.PlanDataPtr->Type ) == GAS_GIANT ? 0 : (pSolarSysState->SysInfo.PlanetInfo.Tectonics + 1)); t.CharCount = (COUNT)~0; font_DrawText (&t); UnlockMutex (GraphicsLock); t.baseline.x = RIGHT_SIDE_BASELINE_X; t.baseline.y = SCAN_BASELINE_Y; t.align = ALIGN_RIGHT; LockMutex (GraphicsLock); t.pStr = buf; val = pSolarSysState->SysInfo.PlanetInfo.PlanetRadius; val = (val * val * val / 100L * pSolarSysState->SysInfo.PlanetInfo.PlanetDensity + ((100L * 100L) >> 1)) / (100L * 100L); if (val == 0) val = 1; MakeScanValue (buf, val, STR_EARTH_SIGN); t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); t.pStr = buf; val = pSolarSysState->SysInfo.PlanetInfo.PlanetRadius; MakeScanValue (buf, val, STR_EARTH_SIGN); t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); t.pStr = buf; val = pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity; if (val == 0) val = 1; MakeScanValue (buf, val, STR_EARTH_SIGN); t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); t.pStr = buf; val = pSolarSysState->SysInfo.PlanetInfo.AxialTilt; if (val < 0) val = -val; sprintf (buf, "%d" STR_DEGREE_SIGN, val); t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += SCAN_LEADING; UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); t.pStr = buf; val = (SDWORD)pSolarSysState->SysInfo.PlanetInfo.RotationPeriod * 10 / 24; MakeScanValue (buf, val, STR_EARTH_SIGN); t.CharCount = (COUNT)~0; font_DrawText (&t); UnlockMutex (GraphicsLock); } static void SetPlanetLoc (POINT new_pt) { RECT r; STAMP s; pSolarSysState->MenuState.first_item = new_pt; new_pt.x >>= MAG_SHIFT; new_pt.y >>= MAG_SHIFT; LockMutex (GraphicsLock); SetContext (ScanContext); s.origin.x = pMenuState->flash_rect0.corner.x - (FLASH_WIDTH >> 1); s.origin.y = pMenuState->flash_rect0.corner.y - (FLASH_HEIGHT >> 1); s.frame = pMenuState->flash_frame0; DrawStamp (&s); pMenuState->flash_rect0.corner = new_pt; GetContextClipRect (&r); r.corner.x += pMenuState->flash_rect0.corner.x - (FLASH_WIDTH >> 1); r.corner.y += pMenuState->flash_rect0.corner.y - (FLASH_HEIGHT >> 1); r.extent.width = FLASH_WIDTH; r.extent.height = FLASH_HEIGHT; LoadDisplayPixmap (&r, pMenuState->flash_frame0); UnlockMutex (GraphicsLock); TaskSwitch (); } int flash_planet_loc_func(void *data) { DWORD TimeIn; BYTE c, val; PRIMITIVE p; Task task = (Task) data; SetPrimType (&p, STAMPFILL_PRIM); SetPrimNextLink (&p, END_OF_LIST); p.Object.Stamp.origin.x = p.Object.Stamp.origin.y = -1; p.Object.Stamp.frame = SetAbsFrameIndex (MiscDataFrame, FLASH_INDEX); c = 0x00; val = -0x02; TimeIn = 0; while (!Task_ReadState(task, TASK_EXIT)) { DWORD T; CONTEXT OldContext; LockMutex (GraphicsLock); T = GetTimeCounter (); if (p.Object.Stamp.origin.x != pMenuState->flash_rect0.corner.x || p.Object.Stamp.origin.y != pMenuState->flash_rect0.corner.y) { c = 0x00; val = -0x02; } else { if (T < TimeIn) { UnlockMutex (GraphicsLock); TaskSwitch (); continue; } if (c == 0x00 || c == 0x1A) val = -val; c += val; } p.Object.Stamp.origin = pMenuState->flash_rect0.corner; SetPrimColor (&p, BUILD_COLOR (MAKE_RGB15 (c, c, c), c)); OldContext = SetContext (ScanContext); DrawBatch (&p, 0, 0); SetContext (OldContext); TimeIn = T + (ONE_SECOND >> 4); UnlockMutex (GraphicsLock); TaskSwitch (); } FinishTask (task); return(0); } static BOOLEAN DoScan (PMENU_STATE pMS); static BOOLEAN PickPlanetSide (PMENU_STATE pMS) { BOOLEAN select, cancel; select = PulsedInputState.menu[KEY_MENU_SELECT]; cancel = PulsedInputState.menu[KEY_MENU_CANCEL]; if (GLOBAL (CurrentActivity) & CHECK_ABORT) { if (pMenuState->flash_task) { ConcludeTask(pMenuState->flash_task); pMenuState->flash_task = 0; } goto ExitPlanetSide; } if (!pMS->Initialized) { pMS->InputFunc = PickPlanetSide; SetMenuRepeatDelay (0, 0, 0, FALSE); SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); if (!select) { RECT r; pMS->Initialized = TRUE; LockMutex (GraphicsLock); SetContext (ScanContext); pMenuState->flash_rect0.corner.x = pSolarSysState->MenuState.first_item.x >> MAG_SHIFT; pMenuState->flash_rect0.corner.y = pSolarSysState->MenuState.first_item.y >> MAG_SHIFT; GetContextClipRect (&r); r.corner.x += pMenuState->flash_rect0.corner.x - (FLASH_WIDTH >> 1); r.corner.y += pMenuState->flash_rect0.corner.y - (FLASH_HEIGHT >> 1); r.extent.width = FLASH_WIDTH; r.extent.height = FLASH_HEIGHT; LoadDisplayPixmap (&r, pMenuState->flash_frame0); SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); InitLander (0); pMenuState->flash_task = AssignTask (flash_planet_loc_func, 2048, "flash planet location"); } } else if (select || cancel) { STAMP s; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); LockMutex (GraphicsLock); DrawStatusMessage (NULL_PTR); UnlockMutex (GraphicsLock); FlushInput (); if (pMenuState->flash_task) { ConcludeTask (pMenuState->flash_task); pMenuState->flash_task = 0; } if (!select) SetPlanetLoc (pSolarSysState->MenuState.first_item); else { COUNT fuel_required; fuel_required = (COUNT)( pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity << 1 ); if (fuel_required > 3 * FUEL_TANK_SCALE) fuel_required = 3 * FUEL_TANK_SCALE; EraseCoarseScan (); LockMutex (GraphicsLock); DeltaSISGauges (0, -(SIZE)fuel_required, 0); SetContext (ScanContext); s.origin = pMenuState->flash_rect0.corner; s.frame = SetAbsFrameIndex (MiscDataFrame, FLASH_INDEX); DrawStamp (&s); UnlockMutex (GraphicsLock); PlanetSide (pMS); if (GLOBAL (CurrentActivity) & CHECK_ABORT) goto ExitPlanetSide; if (GET_GAME_STATE (FOUND_PLUTO_SPATHI) == 1) { HSTARSHIP hStarShip; if (pMenuState->flash_task) { ConcludeTask (pMenuState->flash_task); pMenuState->flash_task = 0; } NextActivity |= CHECK_LOAD; /* fake a load game */ GLOBAL (CurrentActivity) |= START_ENCOUNTER; EncounterGroup = 0; PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); hStarShip = CloneShipFragment (SPATHI_SHIP, &GLOBAL (npc_built_ship_q), 1); if (hStarShip) { BYTE captains_name_index; COUNT which_player; STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); which_player = StarShipPlayer (StarShipPtr); captains_name_index = NAME_OFFSET + NUM_CAPTAINS_NAMES; OwnStarShip (StarShipPtr, which_player, captains_name_index); UnlockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); } SaveFlagshipState (); return (FALSE); } if (optWhichCoarseScan == OPT_PC) PrintCoarseScanPC (); else PrintCoarseScan3DO (); } DrawMenuStateStrings (PM_MIN_SCAN, DISPATCH_SHUTTLE); LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); ExitPlanetSide: SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); pMS->InputFunc = DoScan; pMS->CurState = DISPATCH_SHUTTLE; SetDefaultMenuRepeatDelay (); } else { SIZE dx = 0, dy = 0; POINT new_pt; new_pt = pSolarSysState->MenuState.first_item; if (PulsedInputState.menu[KEY_MENU_LEFT]) dx = -1; if (PulsedInputState.menu[KEY_MENU_RIGHT]) dx = 1; if (PulsedInputState.menu[KEY_MENU_UP]) dy = -1; if (PulsedInputState.menu[KEY_MENU_DOWN]) dy = 1; dx = dx << MAG_SHIFT; if (dx) { new_pt.x += dx; if (new_pt.x < 0) new_pt.x += (MAP_WIDTH << MAG_SHIFT); else if (new_pt.x >= (MAP_WIDTH << MAG_SHIFT)) new_pt.x -= (MAP_WIDTH << MAG_SHIFT); } dy = dy << MAG_SHIFT; if (dy) { new_pt.y += dy; if (new_pt.y < 0 || new_pt.y >= (MAP_HEIGHT << MAG_SHIFT)) new_pt.y = pSolarSysState->MenuState.first_item.y; } if (new_pt.x != pSolarSysState->MenuState.first_item.x || new_pt.y != pSolarSysState->MenuState.first_item.y) { DWORD TimeIn; TimeIn = GetTimeCounter (); SetPlanetLoc (new_pt); SleepThreadUntil (TimeIn + ONE_SECOND / 40); } } return (TRUE); } #define NUM_FLASH_COLORS 8 static void DrawScannedStuff (COUNT y, BYTE CurState) { HELEMENT hElement, hNextElement; COLOR OldColor; OldColor = SetContextForeGroundColor (0); for (hElement = GetHeadElement (); hElement; hElement = hNextElement) { ELEMENTPTR ElementPtr; //COLOR OldColor; SIZE dy; LockElement (hElement, &ElementPtr); hNextElement = GetSuccElement (ElementPtr); dy = y - ElementPtr->current.location.y; if (LOBYTE (ElementPtr->life_span) == CurState && dy >= 0)// && dy <= 3) { COUNT i; //DWORD Time; STAMP s; ElementPtr->state_flags |= APPEARING; s.origin = ElementPtr->current.location; s.frame = ElementPtr->current.image.frame; if (dy >= NUM_FLASH_COLORS) { i = (COUNT)(GetFrameIndex (ElementPtr->next.image.frame) - GetFrameIndex (ElementPtr->current.image.frame) + 1); do { DrawStamp (&s); s.frame = IncFrameIndex (s.frame); } while (--i); } else { BYTE r, g, b; COLOR c; // mineral -- white --> turquoise?? (contrasts with red) // energy -- white --> red (contrasts with white) // bio -- white --> violet (contrasts with green) b = (BYTE)(0x1f - 0x1f * dy / (NUM_FLASH_COLORS - 1)); switch (CurState) { case (MINERAL_SCAN): r = b; g = 0x1f; b = 0x1f; break; case (ENERGY_SCAN): r = 0x1f; g = b; break; case (BIOLOGICAL_SCAN): r = 0x1f; g = b; b = 0x1f; break; } c = BUILD_COLOR (MAKE_RGB15 (r, g, b), 0); SetContextForeGroundColor (c); i = (COUNT)(GetFrameIndex (ElementPtr->next.image.frame) - GetFrameIndex (ElementPtr->current.image.frame) + 1); do { DrawFilledStamp (&s); s.frame = IncFrameIndex (s.frame); } while (--i); } } UnlockElement (hElement); } SetContextForeGroundColor (OldColor); } static BOOLEAN DoScan (PMENU_STATE pMS) { DWORD TimeIn, WaitTime; BOOLEAN select, cancel; select = PulsedInputState.menu[KEY_MENU_SELECT]; cancel = PulsedInputState.menu[KEY_MENU_CANCEL]; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); if (!pMS->Initialized) { pMS->Initialized = TRUE; pMS->InputFunc = DoScan; } else if (cancel || (select && pMS->CurState == EXIT_SCAN)) { LockMutex (GraphicsLock); SetContext (SpaceContext); BatchGraphics (); DrawPlanet (SIS_SCREEN_WIDTH - MAP_WIDTH, SIS_SCREEN_HEIGHT - MAP_HEIGHT, 0, 0); UnbatchGraphics (); UnlockMutex (GraphicsLock); EraseCoarseScan (); // DrawMenuStateStrings (PM_SCAN, SCAN); return (FALSE); } else if (select) { BYTE min_scan, max_scan; RECT r; BOOLEAN PressState, ButtonState; if (pMS->CurState == DISPATCH_SHUTTLE) { COUNT fuel_required; UNICODE buf[100]; if ((pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) || (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity == GAS_GIANT_ATMOSPHERE)) { // cannot dispatch to shielded planets or gas giants PlayMenuSound (MENU_SOUND_FAILURE); return (TRUE); } fuel_required = (COUNT)( pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity << 1 ); if (fuel_required > 3 * FUEL_TANK_SCALE) fuel_required = 3 * FUEL_TANK_SCALE; if (GLOBAL_SIS (FuelOnBoard) < (DWORD)fuel_required || GLOBAL_SIS (NumLanders) == 0 || GLOBAL_SIS (CrewEnlisted) == 0) { PlayMenuSound (MENU_SOUND_FAILURE); return (TRUE); } sprintf (buf, "%s%1.1f", GAME_STRING (NAVIGATION_STRING_BASE + 5), (float) fuel_required / FUEL_TANK_SCALE); LockMutex (GraphicsLock); ClearSISRect (CLEAR_SIS_RADAR); DrawStatusMessage (buf); UnlockMutex (GraphicsLock); LockMutex (GraphicsLock); SetContext (ScanContext); BatchGraphics (); DrawPlanet (0, 0, 0, 0); DrawScannedObjects (FALSE); UnbatchGraphics (); UnlockMutex (GraphicsLock); pMS->Initialized = FALSE; pMS->CurFrame = 0; return PickPlanetSide (pMS); } // Various scans if (pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) { // cannot scan shielded planets PlayMenuSound (MENU_SOUND_FAILURE); return (TRUE); } pSolarSysState->MenuState.Initialized += 4; #ifndef SPIN_ON_SCAN pSolarSysState->PauseRotate = 1; #endif min_scan = pMS->CurState; if (min_scan != AUTO_SCAN) max_scan = min_scan; else { min_scan = MINERAL_SCAN; max_scan = BIOLOGICAL_SCAN; } do { TEXT t; SWORD i; t.baseline.x = SIS_SCREEN_WIDTH >> 1; t.baseline.y = SIS_SCREEN_HEIGHT - MAP_HEIGHT - 7; t.align = ALIGN_CENTER; t.CharCount = (COUNT)~0; pSolarSysState->CurNode = (COUNT)~0; (*pSolarSysState->GenFunc) ((BYTE)(min_scan + GENERATE_MINERAL)); pMS->delta_item = (SIZE)pSolarSysState->CurNode; t.pStr = GAME_STRING (SCAN_STRING_BASE + min_scan); LockMutex (GraphicsLock); SetContext (SpaceContext); r.corner.x = 0; r.corner.y = t.baseline.y - 10; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = t.baseline.y - r.corner.y + 1; RepairBackRect (&r); SetContextFont (MicroFont); switch (min_scan) { case MINERAL_SCAN: SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x13, 0x00, 0x00), 0x2C)); break; case ENERGY_SCAN: SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0C, 0x0C, 0x0C), 0x1C)); break; case BIOLOGICAL_SCAN: SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x0E, 0x00), 0x6C)); break; } font_DrawText (&t); SetContext (ScanContext); UnlockMutex (GraphicsLock); { DWORD rgb; switch (min_scan) { case MINERAL_SCAN: rgb = MAKE_RGB15 (0x1f, 0x00, 0x00); break; case ENERGY_SCAN: rgb = MAKE_RGB15 (0x1f, 0x1f, 0x1f); break; case BIOLOGICAL_SCAN: rgb = MAKE_RGB15 (0x00, 0x1f, 0x00); break; } LockMutex (GraphicsLock); BatchGraphics (); DrawPlanet (0, 0, 0, 0); UnbatchGraphics (); UnlockMutex (GraphicsLock); PressState = AnyButtonPress (TRUE); WaitTime = (ONE_SECOND << 1) / MAP_HEIGHT; // LockMutex (GraphicsLock); TimeIn = GetTimeCounter (); for (i = 0; i < MAP_HEIGHT + NUM_FLASH_COLORS + 1; i++) { ButtonState = AnyButtonPress (TRUE); if (PressState) { PressState = ButtonState; ButtonState = FALSE; } if (ButtonState) i = -i; LockMutex (GraphicsLock); BatchGraphics (); DrawPlanet (0, 0, i, rgb); if (i < 0) i = MAP_HEIGHT + NUM_FLASH_COLORS; if (pMS->delta_item) DrawScannedStuff (i, min_scan); UnbatchGraphics (); UnlockMutex (GraphicsLock); // FlushGraphics (); SleepThreadUntil (TimeIn + WaitTime); TimeIn = GetTimeCounter (); } // UnlockMutex (GraphicsLock); pSolarSysState->Tint_rgb = 0; } } while (++min_scan <= max_scan); LockMutex (GraphicsLock); SetContext (SpaceContext); r.corner.x = 0; r.corner.y = (SIS_SCREEN_HEIGHT - MAP_HEIGHT - 7) - 10; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = (SIS_SCREEN_HEIGHT - MAP_HEIGHT - 7) - r.corner.y + 1; RepairBackRect (&r); SetContext (ScanContext); if (pMS->CurState == AUTO_SCAN) { DrawPlanet (0, 0, 0, 0); DrawScannedObjects (FALSE); UnlockMutex (GraphicsLock); pMS->CurState = DISPATCH_SHUTTLE; DrawMenuStateStrings (PM_MIN_SCAN, pMS->CurState); } else UnlockMutex (GraphicsLock); pSolarSysState->MenuState.Initialized -= 4; pSolarSysState->PauseRotate = 0; FlushInput (); } else if (optWhichMenu == OPT_PC || (!(pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) && pSolarSysState->SysInfo.PlanetInfo.AtmoDensity != GAS_GIANT_ATMOSPHERE)) DoMenuChooser (pMS, PM_MIN_SCAN); return (TRUE); } void ScanSystem (void) { RECT r; MENU_STATE MenuState; MenuState.InputFunc = DoScan; MenuState.Initialized = FALSE; MenuState.flash_task = 0; { #define REPAIR_SCAN (1 << 6) extern BYTE draw_sys_flags; if (draw_sys_flags & REPAIR_SCAN) { RECT r; r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT; LoadIntoExtraScreen (&r); draw_sys_flags &= ~REPAIR_SCAN; } } if (optWhichMenu == OPT_3DO && ((pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) || pSolarSysState->SysInfo.PlanetInfo.AtmoDensity == GAS_GIANT_ATMOSPHERE)) { MenuState.CurState = EXIT_SCAN; ScanContext = 0; } else { MenuState.CurState = AUTO_SCAN; pSolarSysState->MenuState.first_item.x = (MAP_WIDTH >> 1) << MAG_SHIFT; pSolarSysState->MenuState.first_item.y = (MAP_HEIGHT >> 1) << MAG_SHIFT; LockMutex (GraphicsLock); ScanContext = CaptureContext (CreateContext ()); SetContext (ScanContext); MenuState.flash_rect0.extent.width = FLASH_WIDTH; MenuState.flash_rect0.extent.height = FLASH_HEIGHT; MenuState.flash_frame0 = CaptureDrawable ( CreateDrawable (WANT_PIXMAP | MAPPED_TO_DISPLAY, FLASH_WIDTH, FLASH_HEIGHT, 1)); SetContextFGFrame (Screen); r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH; r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT; r.extent.width = MAP_WIDTH; r.extent.height = MAP_HEIGHT; SetContextClipRect (&r); DrawScannedObjects (FALSE); UnlockMutex (GraphicsLock); } DrawMenuStateStrings (PM_MIN_SCAN, MenuState.CurState); if (optWhichCoarseScan == OPT_PC) PrintCoarseScanPC (); else PrintCoarseScan3DO (); pMenuState = &MenuState; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); DoInput ((PVOID)&MenuState, FALSE); pMenuState = 0; if (ScanContext) { LockMutex (GraphicsLock); SetContext (SpaceContext); DestroyDrawable (ReleaseDrawable (MenuState.flash_frame0)); DestroyContext (ReleaseContext (ScanContext)); ScanContext = 0; UnlockMutex (GraphicsLock); } } void GeneratePlanetSide (void) { SIZE scan; BYTE life_init_tab[MAX_LIFE_VARIATION]; InitDisplayList (); if (pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) return; memset (life_init_tab, 0, sizeof (life_init_tab)); for (scan = BIOLOGICAL_SCAN; scan >= MINERAL_SCAN; --scan) { COUNT num_nodes; FRAME f; f = SetAbsFrameIndex (MiscDataFrame, NUM_SCANDOT_TRANSITIONS * (scan - ENERGY_SCAN)); pSolarSysState->CurNode = (COUNT)~0; (*pSolarSysState->GenFunc) ((BYTE)(scan + GENERATE_MINERAL)); num_nodes = pSolarSysState->CurNode; while (num_nodes--) { HELEMENT hNodeElement; ELEMENTPTR NodeElementPtr; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[scan] & (1L << num_nodes)) continue; hNodeElement = AllocElement (); if (!hNodeElement) continue; LockElement (hNodeElement, &NodeElementPtr); pSolarSysState->CurNode = num_nodes; (*pSolarSysState->GenFunc) ((BYTE)(scan + GENERATE_MINERAL)); NodeElementPtr->life_span = MAKE_WORD (scan, num_nodes + 1); NodeElementPtr->state_flags = BAD_GUY; NodeElementPtr->current.location.x = pSolarSysState->SysInfo.PlanetInfo.CurPt.x; NodeElementPtr->current.location.y = pSolarSysState->SysInfo.PlanetInfo.CurPt.y; SetPrimType (&DisplayArray[NodeElementPtr->PrimIndex], STAMP_PRIM); if (scan == MINERAL_SCAN) { COUNT EType; EType = pSolarSysState->SysInfo.PlanetInfo.CurType; NodeElementPtr->turn_wait = (BYTE)EType; NodeElementPtr->mass_points = HIBYTE ( pSolarSysState->SysInfo.PlanetInfo.CurDensity); NodeElementPtr->current.image.frame = SetAbsFrameIndex ( MiscDataFrame, (NUM_SCANDOT_TRANSITIONS << 1) + ElementCategory (EType) * 5); NodeElementPtr->next.image.frame = SetRelFrameIndex ( NodeElementPtr->current.image.frame, LOBYTE ( pSolarSysState->SysInfo.PlanetInfo.CurDensity) + 1); DisplayArray[NodeElementPtr->PrimIndex].Object.Stamp.frame = IncFrameIndex (NodeElementPtr->next.image.frame); } else { extern void object_animation (PELEMENT ElementPtr); NodeElementPtr->current.image.frame = f; NodeElementPtr->next.image.frame = SetRelFrameIndex ( f, NUM_SCANDOT_TRANSITIONS - 1); NodeElementPtr->turn_wait = MAKE_BYTE (4, 4); NodeElementPtr->preprocess_func = object_animation; if (scan == ENERGY_SCAN) { if (pSolarSysState->SysInfo.PlanetInfo.CurType == 1) NodeElementPtr->mass_points = 0; else if (pSolarSysState->SysInfo.PlanetInfo.CurType == 2) NodeElementPtr->mass_points = 1; else NodeElementPtr->mass_points = MAX_SCROUNGED; DisplayArray[NodeElementPtr->PrimIndex].Object.Stamp.frame = pSolarSysState->PlanetSideFrame[1]; } else { COUNT i, which_node; which_node = pSolarSysState->SysInfo.PlanetInfo.CurType; if (CreatureData[which_node].Attributes & SPEED_MASK) { i = (COUNT)TFB_Random (); NodeElementPtr->current.location.x = (LOBYTE (i) % (MAP_WIDTH - (8 << 1))) + 8; NodeElementPtr->current.location.y = (HIBYTE (i) % (MAP_HEIGHT - (8 << 1))) + 8; } if (pSolarSysState->PlanetSideFrame[0] == 0) pSolarSysState->PlanetSideFrame[0] = CaptureDrawable (LoadGraphic ( CANNISTER_MASK_PMAP_ANIM)); for (i = 0; i < MAX_LIFE_VARIATION && life_init_tab[i] != (BYTE)(which_node + 1); ++i) { if (life_init_tab[i] != 0) continue; life_init_tab[i] = (BYTE)which_node + 1; pSolarSysState->PlanetSideFrame[i + 3] = CaptureDrawable (LoadGraphic ( MAKE_RESOURCE ( GET_PACKAGE (LIFE00_MASK_PMAP_ANIM) + which_node, GFXRES, GET_INSTANCE (LIFE00_MASK_PMAP_ANIM) + which_node))); break; } NodeElementPtr->mass_points = (BYTE)which_node; NodeElementPtr->hit_points = HINIBBLE ( CreatureData[which_node].ValueAndHitPoints); DisplayArray[NodeElementPtr->PrimIndex]. Object.Stamp.frame = SetAbsFrameIndex ( pSolarSysState->PlanetSideFrame[i + 3], (COUNT)TFB_Random ()); } } NodeElementPtr->next.location.x = NodeElementPtr->current.location.x << MAG_SHIFT; NodeElementPtr->next.location.y = NodeElementPtr->current.location.y << MAG_SHIFT; UnlockElement (hNodeElement); PutElement (hNodeElement); } } } uqm-0.6.2/sc2/src/sc2code/planets/oval.c0000600000175000017500000001701410543202077016365 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "units.h" #include "libs/gfxlib.h" #include "graphics/context.h" #include "graphics/drawable.h" #define NUM_QUADS 4 void DrawOval (PRECT pRect, BYTE num_off_pixels) { #define FIRST_QUAD (1 << 0) #define SECOND_QUAD (1 << 1) #define THIRD_QUAD (1 << 2) #define FOURTH_QUAD (1 << 3) COUNT off; COORD x, y; SIZE A, B; long Asquared, TwoAsquared, Bsquared, TwoBsquared; long d, dx, dy; BYTE quad_visible; LINE corners; POINT mp; PRIMITIVE prim[NUM_QUADS]; COUNT StartPrim; RECT ClipRect; BRESENHAM_LINE ClipLine; ClipRect.corner.x = ClipRect.corner.y = 0; corners.first.x = pRect->corner.x - ClipRect.corner.x; corners.first.y = pRect->corner.y - ClipRect.corner.y; corners.second.x = corners.first.x + pRect->extent.width - 1; corners.second.y = corners.first.y + pRect->extent.height - 1; if (corners.second.x <= corners.first.x || corners.second.y <= corners.first.y) { if (corners.second.x < corners.first.x) corners.second.x = corners.first.x; if (corners.second.y < corners.first.y) corners.second.y = corners.first.y; DrawLine (&corners); return; } ClipRect.extent.width = SIS_SCREEN_WIDTH; ClipRect.extent.height = SIS_SCREEN_HEIGHT; quad_visible = 0; mp.x = (corners.first.x + corners.second.x) >> 1; mp.y = (corners.first.y + corners.second.y) >> 1; ClipRect.corner.x = ClipRect.corner.y = 0; if (corners.first.y >= 0 && corners.first.y < ClipRect.extent.height && corners.second.x >= 0 && corners.second.x < ClipRect.extent.width) quad_visible |= FIRST_QUAD; else { ClipLine.first.x = mp.x; ClipLine.first.y = corners.first.y; ClipLine.second.x = corners.second.x; ClipLine.second.y = mp.y; if (_clip_line (&ClipRect, &ClipLine)) quad_visible |= FIRST_QUAD; } if (corners.first.y >= 0 && corners.first.y < ClipRect.extent.height && corners.first.x >= 0 && corners.first.x < ClipRect.extent.width) quad_visible |= SECOND_QUAD; else { ClipLine.first.x = mp.x; ClipLine.first.y = corners.first.y; ClipLine.second.x = corners.first.x; ClipLine.second.y = mp.y; if (_clip_line (&ClipRect, &ClipLine)) quad_visible |= SECOND_QUAD; } if (corners.second.y >= 0 && corners.second.y < ClipRect.extent.height && corners.first.x >= 0 && corners.first.x < ClipRect.extent.width) quad_visible |= THIRD_QUAD; else { ClipLine.first.x = mp.x; ClipLine.first.y = corners.second.y; ClipLine.second.x = corners.first.x; ClipLine.second.y = mp.y; if (_clip_line (&ClipRect, &ClipLine)) quad_visible |= THIRD_QUAD; } if (corners.second.y >= 0 && corners.second.y < ClipRect.extent.height && corners.second.x >= 0 && corners.second.x < ClipRect.extent.width) quad_visible |= FOURTH_QUAD; else { ClipLine.first.x = mp.x; ClipLine.first.y = corners.second.y; ClipLine.second.x = corners.second.x; ClipLine.second.y = mp.y; if (_clip_line (&ClipRect, &ClipLine)) quad_visible |= FOURTH_QUAD; } if (!quad_visible) return; StartPrim = END_OF_LIST; for (x = 0; x < NUM_QUADS; ++x) { if (quad_visible & (1 << x)) { SetPrimNextLink (&prim[x], StartPrim); SetPrimType (&prim[x], POINT_PRIM); SetPrimColor (&prim[x], _get_context_fg_color ()); StartPrim = x; } } A = pRect->extent.width >> 1; B = pRect->extent.height >> 1; x = 0; y = B; Asquared = ((long)A * A) << 1; Bsquared = ((long)B * B) << 1; do { Asquared >>= 1; Bsquared >>= 1; TwoAsquared = Asquared << 1; dy = TwoAsquared * B; } while (dy / B != TwoAsquared); TwoBsquared = Bsquared << 1; dx = 0; d = Bsquared - (dy >> 1) + (Asquared >> 2); off = 0; A += pRect->corner.x; B += pRect->corner.y; while (dx < dy) { if (off-- == 0) { prim[0].Object.Point.x = prim[3].Object.Point.x = A + x; prim[0].Object.Point.y = prim[1].Object.Point.y = B - y; prim[1].Object.Point.x = prim[2].Object.Point.x = A - x; prim[2].Object.Point.y = prim[3].Object.Point.y = B + y; DrawBatch (prim, StartPrim, 0); off = num_off_pixels; } if (d > 0) { --y; dy -= TwoAsquared; d -= dy; } ++x; dx += TwoBsquared; d += Bsquared + dx; } d += ((((Asquared - Bsquared) * 3) >> 1) - (dx + dy)) >> 1; while (y >= 0) { if (off-- == 0) { prim[0].Object.Point.x = prim[3].Object.Point.x = A + x; prim[0].Object.Point.y = prim[1].Object.Point.y = B - y; prim[1].Object.Point.x = prim[2].Object.Point.x = A - x; prim[2].Object.Point.y = prim[3].Object.Point.y = B + y; DrawBatch (prim, StartPrim, 0); off = num_off_pixels; } if (d < 0) { ++x; dx += TwoBsquared; d += dx; } --y; dy -= TwoAsquared; d += Asquared - dy; } } void DrawFilledOval (PRECT pRect) { COORD x, y; SIZE A, B; long Asquared, TwoAsquared, Bsquared, TwoBsquared; long d, dx, dy; LINE corners; PRIMITIVE prim[NUM_QUADS >> 1]; COUNT StartPrim; corners.first.x = pRect->corner.x; corners.first.y = pRect->corner.y; corners.second.x = corners.first.x + pRect->extent.width - 1; corners.second.y = corners.first.y + pRect->extent.height - 1; if (corners.second.x <= corners.first.x || corners.second.y <= corners.first.y) { if (corners.second.x < corners.first.x) corners.second.x = corners.first.x; if (corners.second.y < corners.first.y) corners.second.y = corners.first.y; DrawLine (&corners); return; } StartPrim = END_OF_LIST; for (x = 0; x < (NUM_QUADS >> 1); ++x) { SetPrimNextLink (&prim[x], StartPrim); SetPrimType (&prim[x], RECTFILL_PRIM); SetPrimColor (&prim[x], _get_context_fg_color ()); prim[x].Object.Rect.extent.height = 1; StartPrim = x; } A = pRect->extent.width >> 1; B = pRect->extent.height >> 1; x = 0; y = B; Asquared = ((long)A * A) << 1; Bsquared = ((long)B * B) << 1; do { Asquared >>= 1; Bsquared >>= 1; TwoAsquared = Asquared << 1; dy = TwoAsquared * B; } while (dy / B != TwoAsquared); TwoBsquared = Bsquared << 1; dx = 0; d = Bsquared - (dy >> 1) + (Asquared >> 2); A += pRect->corner.x; B += pRect->corner.y; while (dx < dy) { if (d > 0) { prim[0].Object.Rect.corner.x = prim[1].Object.Rect.corner.x = A - x; prim[0].Object.Rect.extent.width = prim[1].Object.Rect.extent.width = (x << 1) + 1; prim[0].Object.Rect.corner.y = B - y; prim[1].Object.Rect.corner.y = B + y; DrawBatch (prim, StartPrim, 0); --y; dy -= TwoAsquared; d -= dy; } ++x; dx += TwoBsquared; d += Bsquared + dx; } d += ((((Asquared - Bsquared) * 3) >> 1) - (dx + dy)) >> 1; while (y >= 0) { prim[0].Object.Rect.corner.x = prim[1].Object.Rect.corner.x = A - x; prim[0].Object.Rect.extent.width = prim[1].Object.Rect.extent.width = (x << 1) + 1; prim[0].Object.Rect.corner.y = B - y; prim[1].Object.Rect.corner.y = B + y; DrawBatch (prim, StartPrim, 0); if (d < 0) { ++x; dx += TwoBsquared; d += dx; } --y; dy -= TwoAsquared; d += Asquared - dy; } } uqm-0.6.2/sc2/src/sc2code/planets/genyeh.c0000600000175000017500000000753010543202100016670 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "nameref.h" #include "resinst.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateYehat (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i, which_node; DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 1; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 106L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { if (ActivateStarShip (YEHAT_SHIP, SPHERE_TRACKING)) { NotifyOthers (YEHAT_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (YEHAT_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); InitCommunication (YEHAT_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } else { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (RUINS_STRTAB) ); } } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/gencol.c0000600000175000017500000000564510543202077016702 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "globdata.h" #include "state.h" #include "planets/genall.h" void GenerateColony (BYTE control) { switch (control) { case INIT_NPCS: { HSTARSHIP hStarShip; GLOBAL (BattleGroupRef) = GET_GAME_STATE_32 (COLONY_GRPOFFS0); if (GLOBAL (BattleGroupRef) == 0) { CloneShipFragment (URQUAN_SHIP, &GLOBAL (npc_built_ship_q), 0); GLOBAL (BattleGroupRef) = PutGroupInfo (GROUPS_ADD_NEW, 1); SET_GAME_STATE_32 (COLONY_GRPOFFS0, GLOBAL (BattleGroupRef)); } GenerateRandomIP (INIT_NPCS); if (GLOBAL (BattleGroupRef) && (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)))) { SHIP_FRAGMENTPTR FragPtr; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); SET_GROUP_MISSION (FragPtr, IN_ORBIT); SET_GROUP_LOC (FragPtr, 0 + 1); /* orbitting colony */ SET_GROUP_DEST (FragPtr, 0 + 1); /* orbitting colony */ FragPtr->ShipInfo.loc.x = FragPtr->ShipInfo.loc.y = 0; FragPtr->ShipInfo.group_counter = 0; UnlockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); } break; } case GENERATE_PLANETS: { COUNT angle; PPLANET_DESC pMinPlanet; pMinPlanet = &pSolarSysState->PlanetDesc[0]; FillOrbits (pSolarSysState, (BYTE)~0, pMinPlanet, FALSE); pMinPlanet->radius = EARTH_RADIUS * 115L / 100; angle = ARCTAN (pMinPlanet->location.x, pMinPlanet->location.y); pMinPlanet->location.x = COSINE (angle, pMinPlanet->radius); pMinPlanet->location.y = SINE (angle, pMinPlanet->radius); pMinPlanet->data_index = WATER_WORLD | PLANET_SHIELDED; break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { DoPlanetaryAnalysis ( &pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc ); pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = EARTH_ATMOSPHERE * 98 / 100; pSolarSysState->SysInfo.PlanetInfo.Weather = 0; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 28; LoadPlanet (NULL); break; } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/roster.c0000600000175000017500000002447710543202100016740 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "colors.h" #include "controls.h" #include "races.h" #include "shipcont.h" #include "setup.h" #include "sounds.h" #include "libs/gfxlib.h" #include "libs/tasklib.h" static int flash_ship_task (void *data) { DWORD TimeIn; COLOR c; Task task = (Task) data; c = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x24); TimeIn = GetTimeCounter (); while (!Task_ReadState (task, TASK_EXIT)) { STAMP s; SHIP_FRAGMENTPTR StarShipPtr; COLOR OldColor; CONTEXT OldContext; LockMutex (GraphicsLock); s.origin = pMenuState->first_item; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), (HSTARSHIP)pMenuState->CurFrame); s.frame = StarShipPtr->ShipInfo.icons; UnlockStarShip (&GLOBAL (built_ship_q), (HSTARSHIP)pMenuState->CurFrame); OldContext = SetContext (StatusContext); if (c >= BUILD_COLOR (MAKE_RGB15 (0x1F, 0x19, 0x19), 0x24)) c = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x00, 0x00), 0x24); else c += BUILD_COLOR (MAKE_RGB15 (0x00, 0x02, 0x02), 0x00); OldColor = SetContextForeGroundColor (c); DrawFilledStamp (&s); SetContextForeGroundColor (OldColor); SetContext (OldContext); UnlockMutex (GraphicsLock); SleepThreadUntil (TimeIn + ONE_SECOND / 15); TimeIn = GetTimeCounter (); } FinishTask (task); return 0; } static HSTARSHIP MatchSupportShip (PMENU_STATE pMS) { PPOINT pship_pos; HSTARSHIP hStarShip, hNextShip; for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), pship_pos = (PPOINT)pMS->flash_frame0; hStarShip; hStarShip = hNextShip, ++pship_pos) { SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), hStarShip); if (pship_pos->x == pMS->first_item.x && pship_pos->y == pMS->first_item.y) { UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); return hStarShip; } hNextShip = _GetSuccLink (StarShipPtr); UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); } return 0; } static BOOLEAN DeltaSupportCrew (SIZE crew_delta) { BOOLEAN ret = FALSE; UNICODE buf[40]; HSTARSHIP hTemplate; SHIP_FRAGMENTPTR StarShipPtr, TemplatePtr; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), (HSTARSHIP)pMenuState->CurFrame); hTemplate = GetStarShipFromIndex (&GLOBAL (avail_race_q), GET_RACE_ID (StarShipPtr)); TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hTemplate); StarShipPtr->ShipInfo.crew_level += crew_delta; if (StarShipPtr->ShipInfo.crew_level == 0) StarShipPtr->ShipInfo.crew_level = 1; else if (StarShipPtr->ShipInfo.crew_level > TemplatePtr->RaceDescPtr->ship_info.crew_level && crew_delta > 0) StarShipPtr->ShipInfo.crew_level -= crew_delta; else { if (StarShipPtr->ShipInfo.crew_level >= TemplatePtr->RaceDescPtr->ship_info.crew_level) sprintf (buf, "%u", StarShipPtr->ShipInfo.crew_level); else sprintf (buf, "%u/%u", StarShipPtr->ShipInfo.crew_level, TemplatePtr->RaceDescPtr->ship_info.crew_level); DrawStatusMessage (buf); DeltaSISGauges (-crew_delta, 0, 0); if (crew_delta) { RECT r; r.corner.x = 2; r.corner.y = 130; r.extent.width = STATUS_MESSAGE_WIDTH; r.extent.height = STATUS_MESSAGE_HEIGHT; SetContext (StatusContext); SetFlashRect (&r, (FRAME)0); } ret = TRUE; } UnlockStarShip (&GLOBAL (avail_race_q), hTemplate); UnlockStarShip (&GLOBAL (built_ship_q), (HSTARSHIP)pMenuState->CurFrame); return ret; } #define SHIP_TOGGLE ((BYTE)(1 << 7)) static void RosterCleanup (PMENU_STATE pMS) { if (pMS->flash_task) { UnlockMutex (GraphicsLock); ConcludeTask (pMS->flash_task); LockMutex (GraphicsLock); pMS->flash_task = 0; } if (pMS->CurFrame) { STAMP s; SHIP_FRAGMENTPTR StarShipPtr; SetContext (StatusContext); s.origin = pMS->first_item; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), (HSTARSHIP)pMS->CurFrame); s.frame = StarShipPtr->ShipInfo.icons; UnlockStarShip (&GLOBAL (built_ship_q), (HSTARSHIP)pMS->CurFrame); if (!(pMS->CurState & SHIP_TOGGLE)) DrawStamp (&s); else { SetContextForeGroundColor (WHITE_COLOR); DrawFilledStamp (&s); } } } static BOOLEAN DoModifyRoster (PMENU_STATE pMS) { BYTE NewState; SBYTE sx, sy; RECT r; STAMP s; SHIP_FRAGMENTPTR StarShipPtr; BOOLEAN select, cancel, up, down, horiz; if (GLOBAL (CurrentActivity) & CHECK_ABORT) { LockMutex (GraphicsLock); RosterCleanup (pMS); UnlockMutex (GraphicsLock); pMS->CurFrame = 0; return FALSE; } select = PulsedInputState.menu[KEY_MENU_SELECT]; cancel = PulsedInputState.menu[KEY_MENU_CANCEL]; up = PulsedInputState.menu[KEY_MENU_UP]; down = PulsedInputState.menu[KEY_MENU_DOWN]; horiz = PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_RIGHT]; if (pMS->Initialized && (pMS->CurState & SHIP_TOGGLE)) { SetMenuSounds (MENU_SOUND_UP | MENU_SOUND_DOWN, MENU_SOUND_SELECT | MENU_SOUND_CANCEL); } else { SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); } if (!pMS->Initialized) { pMS->InputFunc = DoModifyRoster; pMS->Initialized = TRUE; pMS->CurState = NewState = 0; LockMutex (GraphicsLock); SetContext (StatusContext); goto SelectSupport; } else if (cancel && !(pMS->CurState & SHIP_TOGGLE)) { LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); RosterCleanup (pMS); pMS->CurFrame = 0; DrawStatusMessage (NULL_PTR); UnlockMutex (GraphicsLock); return FALSE; } else if (select || cancel) { LockMutex (GraphicsLock); pMS->CurState ^= SHIP_TOGGLE; if (!(pMS->CurState & SHIP_TOGGLE)) SetFlashRect (NULL_PTR, (FRAME)0); else { RosterCleanup (pMS); r.corner.x = 2; r.corner.y = 130; r.extent.width = STATUS_MESSAGE_WIDTH; r.extent.height = STATUS_MESSAGE_HEIGHT; SetContext (StatusContext); SetFlashRect (&r, (FRAME)0); } UnlockMutex (GraphicsLock); } else if (pMS->CurState & SHIP_TOGGLE) { SIZE delta = 0; BOOLEAN failed = FALSE; if (up) { sy = -1; if (GLOBAL_SIS (CrewEnlisted)) delta = 1; else failed = TRUE; } else if (down) { sy = 1; if (GLOBAL_SIS (CrewEnlisted) < GetCPodCapacity (NULL_PTR)) delta = -1; else failed = TRUE; } if (delta != 0) { LockMutex (GraphicsLock); failed = !DeltaSupportCrew (delta); UnlockMutex (GraphicsLock); } if (failed) { // not enough room or crew PlayMenuSound (MENU_SOUND_FAILURE); } } else { PPOINT pship_pos; NewState = pMS->CurState; sx = (SBYTE)((pMS->delta_item + 1) >> 1); if (horiz) { pship_pos = (PPOINT)pMS->flash_frame1; if (NewState == (BYTE)(sx - 1)) NewState = (BYTE)(pMS->delta_item - 1); else if (NewState >= (BYTE)sx) { NewState -= sx; if (pship_pos[NewState].y < pship_pos[pMS->CurState].y) ++NewState; } else { NewState += sx; if (NewState != (BYTE)sx && pship_pos[NewState].y > pship_pos[pMS->CurState].y) --NewState; } } else if (down) { sy = 1; if (++NewState == (BYTE)pMS->delta_item) NewState = (BYTE)(sx - 1); else if (NewState == (BYTE)sx) NewState = 0; } else if (up) { sy = -1; if (NewState == 0) NewState += sx - 1; else if (NewState == (BYTE)sx) NewState = (BYTE)(pMS->delta_item - 1); else --NewState; } if (NewState != pMS->CurState) { LockMutex (GraphicsLock); SetContext (StatusContext); s.origin = pMS->first_item; StarShipPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (built_ship_q), (HSTARSHIP)pMS->CurFrame ); s.frame = StarShipPtr->ShipInfo.icons; UnlockStarShip ( &GLOBAL (built_ship_q), (HSTARSHIP)pMS->CurFrame ); DrawStamp (&s); SelectSupport: pship_pos = (PPOINT)pMS->flash_frame1; pMS->first_item = pship_pos[NewState]; pMS->CurFrame = (FRAME)MatchSupportShip (pMS); DeltaSupportCrew (0); UnlockMutex (GraphicsLock); pMS->CurState = NewState; } if (pMS->flash_task == 0) pMS->flash_task = AssignTask (flash_ship_task, 2048, "flash roster menu"); } return TRUE; } BOOLEAN Roster (void) { COUNT num_support_ships; num_support_ships = CountLinks (&GLOBAL (built_ship_q)); if (num_support_ships) { SIZE i, j, k, l; POINT modified_ship_pos[MAX_COMBAT_SHIPS]; POINT ship_pos[MAX_COMBAT_SHIPS] = { SUPPORT_SHIP_PTS }; MENU_STATE MenuState; PMENU_STATE pOldMenuState; pOldMenuState = pMenuState; pMenuState = &MenuState; j = 0; k = (num_support_ships + 1) >> 1; for (i = 0; (int)i < (int)num_support_ships; i += 2) { modified_ship_pos[j++] = ship_pos[i]; modified_ship_pos[k++] = ship_pos[i + 1]; } k = (num_support_ships + 1) >> 1; for (i = 0; i < k; ++i) { for (j = k - 1; j > i; --j) { if (modified_ship_pos[i].y > modified_ship_pos[j].y) { POINT temp; temp = modified_ship_pos[i]; modified_ship_pos[i] = modified_ship_pos[j]; modified_ship_pos[j] = temp; } } } l = k; k = num_support_ships >> 1; for (i = 0; i < k; ++i) { for (j = k - 1; j > i; --j) { if (modified_ship_pos[i + l].y > modified_ship_pos[j + l].y) { POINT temp; temp = modified_ship_pos[i + l]; modified_ship_pos[i + l] = modified_ship_pos[j + l]; modified_ship_pos[j + l] = temp; } } } MenuState.InputFunc = DoModifyRoster; MenuState.Initialized = FALSE; MenuState.CurState = 0; MenuState.flash_task = 0; MenuState.delta_item = (SIZE)num_support_ships; MenuState.flash_frame0 = (FRAME)ship_pos; MenuState.flash_frame1 = (FRAME)modified_ship_pos; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); DoInput ((PVOID)&MenuState, TRUE); pMenuState = pOldMenuState; return TRUE; } return FALSE; } uqm-0.6.2/sc2/src/sc2code/planets/planets.h0000600000175000017500000001473610543202100017072 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _PLANETS_H #define _PLANETS_H #include "menustat.h" #include "units.h" #define END_INTERPLANETARY START_INTERPLANETARY enum { SCAN = 0, STARMAP, EQUIP_DEVICE, CARGO, ROSTER, GAME_MENU, NAVIGATION }; enum { MINERAL_SCAN = 0, ENERGY_SCAN, BIOLOGICAL_SCAN, NUM_SCAN_TYPES, EXIT_SCAN = NUM_SCAN_TYPES, AUTO_SCAN, DISPATCH_SHUTTLE }; #define MAP_WIDTH SIS_SCREEN_WIDTH #define MAP_HEIGHT (75 - SAFE_Y) enum { GENERATE_PLANETS = 0, GENERATE_MOONS, GENERATE_ORBITAL, INIT_NPCS, REINIT_NPCS, UNINIT_NPCS, GENERATE_MINERAL, GENERATE_ENERGY, GENERATE_LIFE, GENERATE_NAME }; enum { BIOLOGICAL_DISASTER = 0, EARTHQUAKE_DISASTER, LIGHTNING_DISASTER, LAVASPOT_DISASTER, /* additional lander sounds */ LANDER_INJURED, LANDER_SHOOTS, LANDER_HITS, LIFEFORM_CANNED, LANDER_PICKUP, LANDER_FULL, LANDER_DEPARTS, LANDER_RETURNS, LANDER_DESTROYED }; #define MAX_SCROUNGED 50 /* max lander can hold */ #define SCALE_RADIUS(r) ((r) << 6) #define UNSCALE_RADIUS(r) ((r) >> 6) #define MAX_ZOOM_RADIUS SCALE_RADIUS(128) #define MIN_ZOOM_RADIUS (MAX_ZOOM_RADIUS>>3) #define EARTH_RADIUS SCALE_RADIUS(8) #define MIN_PLANET_RADIUS SCALE_RADIUS (4) #define MAX_PLANET_RADIUS SCALE_RADIUS (124) #define DISPLAY_FACTOR ((SIS_SCREEN_WIDTH >> 1) - 8) #define NUM_SCANDOT_TRANSITIONS 4 #define MIN_MOON_RADIUS 35 #define MOON_DELTA 20 #define PLANET_SHIELDED (1 << 7) typedef struct planet_desc { DWORD rand_seed; BYTE data_index; BYTE NumPlanets; SIZE radius; POINT location; COLOR temp_color; COUNT NextIndex; STAMP image; struct planet_desc *pPrevDesc; } PLANET_DESC; typedef PLANET_DESC *PPLANET_DESC; typedef struct { POINT star_pt; BYTE Type, Index; BYTE Prefix, Postfix; } STAR_DESC; typedef STAR_DESC *PSTAR_DESC; #define STAR_DESCPTR PSTAR_DESC #define MAX_SUNS 1 #define MAX_PLANETS 16 #define MAX_MOONS 4 #include "elemdata.h" #include "plandata.h" #include "sundata.h" typedef void (*PLAN_GEN_FUNC) (BYTE control); typedef struct planet_orbit { FRAME TopoZoomFrame; // 4x scaled topo image for planet-side PBYTE lpTopoData; // normal topo data; expressed in elevation levels // data is signed for planets other than gas giants // transformed to light variance map for 3d planet FRAME PlanetFrameArray; // rotating 3d planet frames (current and next) FRAME ObjectFrame; // any extra planetary object (shield, atmo, rings) // automatically drawn if present FRAME TintFrame; // tinted topo images for current scan type (dynamic) DWORD *lpTopoMap; // RGBA version of topo image; for 3d planet DWORD *ScratchArray; // temp RGBA data for whatever transforms (nuked often) FRAME WorkFrame; // any extra frame workspace (for dynamic objects) } PLANET_ORBIT; // See doc/devel/generate for information on how this structure is // filled. typedef struct solarsys_state { MENU_STATE MenuState; COUNT WaitIntersect; PLANET_DESC SunDesc[MAX_SUNS]; PLANET_DESC PlanetDesc[MAX_PLANETS]; // Description of the planets in the system. // Only defined after a call to GenFunc with GENERATE_PLANETS // as its argument, and overwritten by subsequent calls. PLANET_DESC MoonDesc[MAX_MOONS]; // Description of the moons orbiting the planet pointed to // by pBaseDesc. // Only defined after a call to GenFunc with GENERATE_MOONS // as its argument, and overwritten by subsequent calls. PPLANET_DESC pBaseDesc; PPLANET_DESC pOrbitalDesc; SIZE FirstPlanetIndex, LastPlanetIndex; // The planets get sorted on their image.origin.y value. // PlanetDesc[FirstPlanetIndex] is the planet with the lowest // image.origin.y, and PlanetDesc[LastPlanetIndex] has the // highest image.origin.y. // PlanetDesc[PlanetDesc[i].NextIndex] is the next planet // after PlanetDesc[i] in the ordering. BYTE turn_counter, turn_wait; BYTE thrust_counter, max_ship_speed; STRING XlatRef; STRINGPTR XlatPtr; COLORMAP OrbitalCMap; SYSTEM_INFO SysInfo; COUNT CurNode; PLAN_GEN_FUNC GenFunc; // Function to call to fill in various parts of this structure. // See doc/devel/generate. FRAME PlanetSideFrame[6]; UWORD Tint_rgb; UBYTE PauseRotate; FRAME TopoFrame; PLANET_ORBIT Orbit; } SOLARSYS_STATE; typedef SOLARSYS_STATE *PSOLARSYS_STATE; extern PSOLARSYS_STATE pSolarSysState; extern MUSIC_REF SpaceMusic; extern void LoadPlanet (FRAME SurfDefFrame); extern void DrawPlanet (int x, int y, int dy, unsigned int rgb); extern void FreePlanet (void); extern void LoadStdLanderFont (PLANET_INFO *info); extern void FreeLanderFont (PLANET_INFO *info); extern void ExploreSolarSys (void); extern void DrawStarBackGround (BOOLEAN ForPlanet); extern void XFormIPLoc (PPOINT pIn, PPOINT pOut, BOOLEAN ToDisplay); extern void GenerateRandomIP (BYTE control); extern PLAN_GEN_FUNC GenerateIP (BYTE Index); extern void DrawSystem (SIZE radius, BOOLEAN IsInnerSystem); extern void DrawOval (PRECT pRect, BYTE num_off_pixels); extern void DrawFilledOval (PRECT pRect); extern void DoMissions (void); extern void FillOrbits (PSOLARSYS_STATE system, BYTE NumPlanets, PPLANET_DESC pBaseDesc, BOOLEAN TypesDefined); extern void ScanSystem (void); extern void ChangeSolarSys (void); extern BOOLEAN DoFlagshipCommands (PMENU_STATE pMS); extern void ZoomSystem (void); extern void LoadSolarSys (void); extern void InitLander (BYTE LanderFlags); extern BOOLEAN ValidateOrbits (void); extern void IP_reset (void); extern void IP_frame (void); extern PRECT RotatePlanet (int x, int dx, int dy, COUNT scale_amt, UBYTE zoom_from, PRECT r); extern void SetPlanetTilt (int da); extern void DrawScannedObjects (BOOLEAN Reversed); extern void GeneratePlanetMask (PPLANET_DESC pPlanetDesc, FRAME SurfDefFrame); extern void DeltaTopography (COUNT num_iterations, PSBYTE DepthArray, PRECT pRect, SIZE depth_delta); #endif /* _PLANETS_H */ uqm-0.6.2/sc2/src/sc2code/planets/orbits.c0000600000175000017500000004525010543202077016731 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "encount.h" #include "planets/planets.h" #include "libs/compiler.h" #include "libs/mathlib.h" #include "libs/log.h" //#define DEBUG_ORBITS enum { PLANET_NEVER = 0, PLANET_RARE = 15, PLANET_FEW = 63, PLANET_COMMON = 127, PLANET_ALWAYS = 255 }; static BYTE BlueDistribution (BYTE which_world) { BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = { PLANET_ALWAYS, /* OOLITE_WORLD */ PLANET_ALWAYS, /* YTTRIC_WORLD */ PLANET_ALWAYS, /* QUASI_DEGENERATE_WORLD */ PLANET_ALWAYS, /* LANTHANIDE_WORLD */ PLANET_ALWAYS, /* TREASURE_WORLD */ PLANET_ALWAYS, /* UREA_WORLD */ PLANET_ALWAYS, /* METAL_WORLD */ PLANET_ALWAYS, /* RADIOACTIVE_WORLD */ PLANET_ALWAYS, /* OPALESCENT_WORLD */ PLANET_ALWAYS, /* CYANIC_WORLD */ PLANET_ALWAYS, /* ACID_WORLD */ PLANET_ALWAYS, /* ALKALI_WORLD */ PLANET_ALWAYS, /* HALIDE_WORLD */ PLANET_ALWAYS, /* GREEN_WORLD */ PLANET_ALWAYS, /* COPPER_WORLD */ PLANET_ALWAYS, /* CARBIDE_WORLD */ PLANET_ALWAYS, /* ULTRAMARINE_WORLD */ PLANET_ALWAYS, /* NOBLE_WORLD */ PLANET_ALWAYS, /* AZURE_WORLD */ PLANET_NEVER, /* CHONDRITE_WORLD */ PLANET_NEVER, /* PURPLE_WORLD */ PLANET_NEVER, /* SUPER_DENSE_WORLD */ PLANET_NEVER, /* PELLUCID_WORLD */ PLANET_NEVER, /* DUST_WORLD */ PLANET_NEVER, /* CRIMSON_WORLD */ PLANET_NEVER, /* CIMMERIAN_WORLD */ PLANET_NEVER, /* INFRARED_WORLD */ PLANET_ALWAYS, /* SELENIC_WORLD */ PLANET_ALWAYS, /* AURIC_WORLD */ PLANET_ALWAYS, /* FLUORESCENT_WORLD */ PLANET_ALWAYS, /* ULTRAVIOLET_WORLD */ PLANET_ALWAYS, /* PLUTONIC_WORLD */ PLANET_NEVER, /* RAINBOW_WORLD */ PLANET_NEVER, /* CRACKED_WORLD */ PLANET_ALWAYS, /* SAPPHIRE_WORLD */ PLANET_ALWAYS, /* ORGANIC_WORLD */ PLANET_ALWAYS, /* XENOLITHIC_WORLD */ PLANET_ALWAYS, /* REDUX_WORLD */ PLANET_ALWAYS, /* PRIMORDIAL_WORLD */ PLANET_NEVER, /* EMERALD_WORLD */ PLANET_ALWAYS, /* CHLORINE_WORLD */ PLANET_ALWAYS, /* MAGNETIC_WORLD */ PLANET_ALWAYS, /* WATER_WORLD */ PLANET_ALWAYS, /* TELLURIC_WORLD */ PLANET_NEVER, /* HYDROCARBON_WORLD */ PLANET_NEVER, /* IODINE_WORLD */ PLANET_NEVER, /* VINYLOGOUS_WORLD */ PLANET_NEVER, /* RUBY_WORLD */ PLANET_NEVER, /* MAGMA_WORLD */ PLANET_NEVER, /* MAROON_WORLD */ PLANET_ALWAYS, /* BLU_GAS_GIANT */ PLANET_ALWAYS, /* CYA_GAS_GIANT */ PLANET_ALWAYS, /* GRN_GAS_GIANT */ PLANET_ALWAYS, /* GRY_GAS_GIANT */ PLANET_ALWAYS, /* ORA_GAS_GIANT */ PLANET_ALWAYS, /* PUR_GAS_GIANT */ PLANET_ALWAYS, /* RED_GAS_GIANT */ PLANET_ALWAYS, /* VIO_GAS_GIANT */ PLANET_ALWAYS, /* YEL_GAS_GIANT */ }; return (PlanetDistribution[which_world]); } static BYTE GreenDistribution (BYTE which_world) { BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = { PLANET_NEVER, /* OOLITE_WORLD */ PLANET_NEVER, /* YTTRIC_WORLD */ PLANET_ALWAYS, /* QUASI_DEGENERATE_WORLD */ PLANET_ALWAYS, /* LANTHANIDE_WORLD */ PLANET_ALWAYS, /* TREASURE_WORLD */ PLANET_ALWAYS, /* UREA_WORLD */ PLANET_ALWAYS, /* METAL_WORLD */ PLANET_ALWAYS, /* RADIOACTIVE_WORLD */ PLANET_ALWAYS, /* OPALESCENT_WORLD */ PLANET_ALWAYS, /* CYANIC_WORLD */ PLANET_ALWAYS, /* ACID_WORLD */ PLANET_ALWAYS, /* ALKALI_WORLD */ PLANET_ALWAYS, /* HALIDE_WORLD */ PLANET_ALWAYS, /* GREEN_WORLD */ PLANET_ALWAYS, /* COPPER_WORLD */ PLANET_ALWAYS, /* CARBIDE_WORLD */ PLANET_ALWAYS, /* ULTRAMARINE_WORLD */ PLANET_ALWAYS, /* NOBLE_WORLD */ PLANET_ALWAYS, /* AZURE_WORLD */ PLANET_ALWAYS, /* CHONDRITE_WORLD */ PLANET_ALWAYS, /* PURPLE_WORLD */ PLANET_ALWAYS, /* SUPER_DENSE_WORLD */ PLANET_ALWAYS, /* PELLUCID_WORLD */ PLANET_NEVER, /* DUST_WORLD */ PLANET_NEVER, /* CRIMSON_WORLD */ PLANET_NEVER, /* CIMMERIAN_WORLD */ PLANET_NEVER, /* INFRARED_WORLD */ PLANET_ALWAYS, /* SELENIC_WORLD */ PLANET_ALWAYS, /* AURIC_WORLD */ PLANET_ALWAYS, /* FLUORESCENT_WORLD */ PLANET_ALWAYS, /* ULTRAVIOLET_WORLD */ PLANET_ALWAYS, /* PLUTONIC_WORLD */ PLANET_NEVER, /* RAINBOW_WORLD */ PLANET_NEVER, /* CRACKED_WORLD */ PLANET_NEVER, /* SAPPHIRE_WORLD */ PLANET_ALWAYS, /* ORGANIC_WORLD */ PLANET_ALWAYS, /* XENOLITHIC_WORLD */ PLANET_ALWAYS, /* REDUX_WORLD */ PLANET_ALWAYS, /* PRIMORDIAL_WORLD */ PLANET_ALWAYS, /* EMERALD_WORLD */ PLANET_ALWAYS, /* CHLORINE_WORLD */ PLANET_ALWAYS, /* MAGNETIC_WORLD */ PLANET_ALWAYS, /* WATER_WORLD */ PLANET_ALWAYS, /* TELLURIC_WORLD */ PLANET_ALWAYS, /* HYDROCARBON_WORLD */ PLANET_ALWAYS, /* IODINE_WORLD */ PLANET_NEVER, /* VINYLOGOUS_WORLD */ PLANET_NEVER, /* RUBY_WORLD */ PLANET_NEVER, /* MAGMA_WORLD */ PLANET_NEVER, /* MAROON_WORLD */ PLANET_ALWAYS, /* BLU_GAS_GIANT */ PLANET_ALWAYS, /* CYA_GAS_GIANT */ PLANET_ALWAYS, /* GRN_GAS_GIANT */ PLANET_ALWAYS, /* GRY_GAS_GIANT */ PLANET_ALWAYS, /* ORA_GAS_GIANT */ PLANET_ALWAYS, /* PUR_GAS_GIANT */ PLANET_ALWAYS, /* RED_GAS_GIANT */ PLANET_ALWAYS, /* VIO_GAS_GIANT */ PLANET_ALWAYS, /* YEL_GAS_GIANT */ }; return (PlanetDistribution[which_world]); } static BYTE OrangeDistribution (BYTE which_world) { BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = { PLANET_NEVER, /* OOLITE_WORLD */ PLANET_NEVER, /* YTTRIC_WORLD */ PLANET_NEVER, /* QUASI_DEGENERATE_WORLD */ PLANET_NEVER, /* LANTHANIDE_WORLD */ PLANET_NEVER, /* TREASURE_WORLD */ PLANET_ALWAYS, /* UREA_WORLD */ PLANET_NEVER, /* METAL_WORLD */ PLANET_ALWAYS, /* RADIOACTIVE_WORLD */ PLANET_NEVER, /* OPALESCENT_WORLD */ PLANET_NEVER, /* CYANIC_WORLD */ PLANET_ALWAYS, /* ACID_WORLD */ PLANET_ALWAYS, /* ALKALI_WORLD */ PLANET_ALWAYS, /* HALIDE_WORLD */ PLANET_ALWAYS, /* GREEN_WORLD */ PLANET_ALWAYS, /* COPPER_WORLD */ PLANET_ALWAYS, /* CARBIDE_WORLD */ PLANET_ALWAYS, /* ULTRAMARINE_WORLD */ PLANET_ALWAYS, /* NOBLE_WORLD */ PLANET_ALWAYS, /* AZURE_WORLD */ PLANET_ALWAYS, /* CHONDRITE_WORLD */ PLANET_ALWAYS, /* PURPLE_WORLD */ PLANET_ALWAYS, /* SUPER_DENSE_WORLD */ PLANET_ALWAYS, /* PELLUCID_WORLD */ PLANET_ALWAYS, /* DUST_WORLD */ PLANET_ALWAYS, /* CRIMSON_WORLD */ PLANET_ALWAYS, /* CIMMERIAN_WORLD */ PLANET_ALWAYS, /* INFRARED_WORLD */ PLANET_ALWAYS, /* SELENIC_WORLD */ PLANET_NEVER, /* AURIC_WORLD */ PLANET_NEVER, /* FLUORESCENT_WORLD */ PLANET_NEVER, /* ULTRAVIOLET_WORLD */ PLANET_NEVER, /* PLUTONIC_WORLD */ PLANET_NEVER, /* RAINBOW_WORLD */ PLANET_NEVER, /* CRACKED_WORLD */ PLANET_NEVER, /* SAPPHIRE_WORLD */ PLANET_NEVER, /* ORGANIC_WORLD */ PLANET_NEVER, /* XENOLITHIC_WORLD */ PLANET_NEVER, /* REDUX_WORLD */ PLANET_NEVER, /* PRIMORDIAL_WORLD */ PLANET_NEVER, /* EMERALD_WORLD */ PLANET_ALWAYS, /* CHLORINE_WORLD */ PLANET_ALWAYS, /* MAGNETIC_WORLD */ PLANET_ALWAYS, /* WATER_WORLD */ PLANET_ALWAYS, /* TELLURIC_WORLD */ PLANET_ALWAYS, /* HYDROCARBON_WORLD */ PLANET_ALWAYS, /* IODINE_WORLD */ PLANET_ALWAYS, /* VINYLOGOUS_WORLD */ PLANET_NEVER, /* RUBY_WORLD */ PLANET_ALWAYS, /* MAGMA_WORLD */ PLANET_ALWAYS, /* MAROON_WORLD */ PLANET_ALWAYS, /* BLU_GAS_GIANT */ PLANET_ALWAYS, /* CYA_GAS_GIANT */ PLANET_ALWAYS, /* GRN_GAS_GIANT */ PLANET_ALWAYS, /* GRY_GAS_GIANT */ PLANET_ALWAYS, /* ORA_GAS_GIANT */ PLANET_ALWAYS, /* PUR_GAS_GIANT */ PLANET_ALWAYS, /* RED_GAS_GIANT */ PLANET_ALWAYS, /* VIO_GAS_GIANT */ PLANET_ALWAYS, /* YEL_GAS_GIANT */ }; return (PlanetDistribution[which_world]); } static BYTE RedDistribution (BYTE which_world) { BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = { PLANET_NEVER, /* OOLITE_WORLD */ PLANET_NEVER, /* YTTRIC_WORLD */ PLANET_NEVER, /* QUASI_DEGENERATE_WORLD */ PLANET_NEVER, /* LANTHANIDE_WORLD */ PLANET_NEVER, /* TREASURE_WORLD */ PLANET_ALWAYS, /* UREA_WORLD */ PLANET_ALWAYS, /* METAL_WORLD */ PLANET_NEVER, /* RADIOACTIVE_WORLD */ PLANET_NEVER, /* OPALESCENT_WORLD */ PLANET_NEVER, /* CYANIC_WORLD */ PLANET_NEVER, /* ACID_WORLD */ PLANET_NEVER, /* ALKALI_WORLD */ PLANET_NEVER, /* HALIDE_WORLD */ PLANET_NEVER, /* GREEN_WORLD */ PLANET_NEVER, /* COPPER_WORLD */ PLANET_NEVER, /* CARBIDE_WORLD */ PLANET_ALWAYS, /* ULTRAMARINE_WORLD */ PLANET_ALWAYS, /* NOBLE_WORLD */ PLANET_ALWAYS, /* AZURE_WORLD */ PLANET_ALWAYS, /* CHONDRITE_WORLD */ PLANET_ALWAYS, /* PURPLE_WORLD */ PLANET_ALWAYS, /* SUPER_DENSE_WORLD */ PLANET_ALWAYS, /* PELLUCID_WORLD */ PLANET_ALWAYS, /* DUST_WORLD */ PLANET_ALWAYS, /* CRIMSON_WORLD */ PLANET_ALWAYS, /* CIMMERIAN_WORLD */ PLANET_ALWAYS, /* INFRARED_WORLD */ PLANET_ALWAYS, /* SELENIC_WORLD */ PLANET_NEVER, /* AURIC_WORLD */ PLANET_NEVER, /* FLUORESCENT_WORLD */ PLANET_NEVER, /* ULTRAVIOLET_WORLD */ PLANET_NEVER, /* PLUTONIC_WORLD */ PLANET_NEVER, /* RAINBOW_WORLD */ PLANET_NEVER, /* CRACKED_WORLD */ PLANET_NEVER, /* SAPPHIRE_WORLD */ PLANET_NEVER, /* ORGANIC_WORLD */ PLANET_NEVER, /* XENOLITHIC_WORLD */ PLANET_NEVER, /* REDUX_WORLD */ PLANET_NEVER, /* PRIMORDIAL_WORLD */ PLANET_NEVER, /* EMERALD_WORLD */ PLANET_NEVER, /* CHLORINE_WORLD */ PLANET_ALWAYS, /* MAGNETIC_WORLD */ PLANET_ALWAYS, /* WATER_WORLD */ PLANET_ALWAYS, /* TELLURIC_WORLD */ PLANET_ALWAYS, /* HYDROCARBON_WORLD */ PLANET_ALWAYS, /* IODINE_WORLD */ PLANET_ALWAYS, /* VINYLOGOUS_WORLD */ PLANET_ALWAYS, /* RUBY_WORLD */ PLANET_ALWAYS, /* MAGMA_WORLD */ PLANET_ALWAYS, /* MAROON_WORLD */ PLANET_ALWAYS, /* BLU_GAS_GIANT */ PLANET_ALWAYS, /* CYA_GAS_GIANT */ PLANET_ALWAYS, /* GRN_GAS_GIANT */ PLANET_ALWAYS, /* GRY_GAS_GIANT */ PLANET_ALWAYS, /* ORA_GAS_GIANT */ PLANET_ALWAYS, /* PUR_GAS_GIANT */ PLANET_ALWAYS, /* RED_GAS_GIANT */ PLANET_ALWAYS, /* VIO_GAS_GIANT */ PLANET_ALWAYS, /* YEL_GAS_GIANT */ }; return (PlanetDistribution[which_world]); } static BYTE WhiteDistribution (BYTE which_world) { BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = { PLANET_ALWAYS, /* OOLITE_WORLD */ PLANET_ALWAYS, /* YTTRIC_WORLD */ PLANET_ALWAYS, /* QUASI_DEGENERATE_WORLD */ PLANET_ALWAYS, /* LANTHANIDE_WORLD */ PLANET_ALWAYS, /* TREASURE_WORLD */ PLANET_ALWAYS, /* UREA_WORLD */ PLANET_ALWAYS, /* METAL_WORLD */ PLANET_ALWAYS, /* RADIOACTIVE_WORLD */ PLANET_ALWAYS, /* OPALESCENT_WORLD */ PLANET_ALWAYS, /* CYANIC_WORLD */ PLANET_ALWAYS, /* ACID_WORLD */ PLANET_ALWAYS, /* ALKALI_WORLD */ PLANET_ALWAYS, /* HALIDE_WORLD */ PLANET_NEVER, /* GREEN_WORLD */ PLANET_NEVER, /* COPPER_WORLD */ PLANET_NEVER, /* CARBIDE_WORLD */ PLANET_NEVER, /* ULTRAMARINE_WORLD */ PLANET_NEVER, /* NOBLE_WORLD */ PLANET_NEVER, /* AZURE_WORLD */ PLANET_NEVER, /* CHONDRITE_WORLD */ PLANET_NEVER, /* PURPLE_WORLD */ PLANET_NEVER, /* SUPER_DENSE_WORLD */ PLANET_NEVER, /* PELLUCID_WORLD */ PLANET_NEVER, /* DUST_WORLD */ PLANET_NEVER, /* CRIMSON_WORLD */ PLANET_NEVER, /* CIMMERIAN_WORLD */ PLANET_NEVER, /* INFRARED_WORLD */ PLANET_ALWAYS, /* SELENIC_WORLD */ PLANET_ALWAYS, /* AURIC_WORLD */ PLANET_ALWAYS, /* FLUORESCENT_WORLD */ PLANET_ALWAYS, /* ULTRAVIOLET_WORLD */ PLANET_ALWAYS, /* PLUTONIC_WORLD */ PLANET_NEVER, /* RAINBOW_WORLD */ PLANET_NEVER, /* CRACKED_WORLD */ PLANET_ALWAYS, /* SAPPHIRE_WORLD */ PLANET_ALWAYS, /* ORGANIC_WORLD */ PLANET_ALWAYS, /* XENOLITHIC_WORLD */ PLANET_ALWAYS, /* REDUX_WORLD */ PLANET_ALWAYS, /* PRIMORDIAL_WORLD */ PLANET_ALWAYS, /* EMERALD_WORLD */ PLANET_NEVER, /* CHLORINE_WORLD */ PLANET_NEVER, /* MAGNETIC_WORLD */ PLANET_NEVER, /* WATER_WORLD */ PLANET_NEVER, /* TELLURIC_WORLD */ PLANET_NEVER, /* HYDROCARBON_WORLD */ PLANET_NEVER, /* IODINE_WORLD */ PLANET_ALWAYS, /* VINYLOGOUS_WORLD */ PLANET_ALWAYS, /* RUBY_WORLD */ PLANET_NEVER, /* MAGMA_WORLD */ PLANET_NEVER, /* MAROON_WORLD */ PLANET_ALWAYS, /* BLU_GAS_GIANT */ PLANET_ALWAYS, /* CYA_GAS_GIANT */ PLANET_ALWAYS, /* GRN_GAS_GIANT */ PLANET_ALWAYS, /* GRY_GAS_GIANT */ PLANET_ALWAYS, /* ORA_GAS_GIANT */ PLANET_ALWAYS, /* PUR_GAS_GIANT */ PLANET_ALWAYS, /* RED_GAS_GIANT */ PLANET_ALWAYS, /* VIO_GAS_GIANT */ PLANET_ALWAYS, /* YEL_GAS_GIANT */ }; return (PlanetDistribution[which_world]); } static BYTE YellowDistribution (BYTE which_world) { BYTE PlanetDistribution[NUMBER_OF_PLANET_TYPES] = { PLANET_NEVER, /* OOLITE_WORLD */ PLANET_NEVER, /* YTTRIC_WORLD */ PLANET_NEVER, /* QUASI_DEGENERATE_WORLD */ PLANET_NEVER, /* LANTHANIDE_WORLD */ PLANET_ALWAYS, /* TREASURE_WORLD */ PLANET_ALWAYS, /* UREA_WORLD */ PLANET_ALWAYS, /* METAL_WORLD */ PLANET_ALWAYS, /* RADIOACTIVE_WORLD */ PLANET_ALWAYS, /* OPALESCENT_WORLD */ PLANET_ALWAYS, /* CYANIC_WORLD */ PLANET_ALWAYS, /* ACID_WORLD */ PLANET_ALWAYS, /* ALKALI_WORLD */ PLANET_ALWAYS, /* HALIDE_WORLD */ PLANET_ALWAYS, /* GREEN_WORLD */ PLANET_ALWAYS, /* COPPER_WORLD */ PLANET_ALWAYS, /* CARBIDE_WORLD */ PLANET_ALWAYS, /* ULTRAMARINE_WORLD */ PLANET_ALWAYS, /* NOBLE_WORLD */ PLANET_ALWAYS, /* AZURE_WORLD */ PLANET_ALWAYS, /* CHONDRITE_WORLD */ PLANET_ALWAYS, /* PURPLE_WORLD */ PLANET_ALWAYS, /* SUPER_DENSE_WORLD */ PLANET_ALWAYS, /* PELLUCID_WORLD */ PLANET_ALWAYS, /* DUST_WORLD */ PLANET_ALWAYS, /* CRIMSON_WORLD */ PLANET_ALWAYS, /* CIMMERIAN_WORLD */ PLANET_ALWAYS, /* INFRARED_WORLD */ PLANET_ALWAYS, /* SELENIC_WORLD */ PLANET_ALWAYS, /* AURIC_WORLD */ PLANET_NEVER, /* FLUORESCENT_WORLD */ PLANET_NEVER, /* ULTRAVIOLET_WORLD */ PLANET_NEVER, /* PLUTONIC_WORLD */ PLANET_NEVER, /* RAINBOW_WORLD */ PLANET_NEVER, /* CRACKED_WORLD */ PLANET_NEVER, /* SAPPHIRE_WORLD */ PLANET_ALWAYS, /* ORGANIC_WORLD */ PLANET_ALWAYS, /* XENOLITHIC_WORLD */ PLANET_ALWAYS, /* REDUX_WORLD */ PLANET_ALWAYS, /* PRIMORDIAL_WORLD */ PLANET_NEVER, /* EMERALD_WORLD */ PLANET_ALWAYS, /* CHLORINE_WORLD */ PLANET_ALWAYS, /* MAGNETIC_WORLD */ PLANET_ALWAYS, /* WATER_WORLD */ PLANET_ALWAYS, /* TELLURIC_WORLD */ PLANET_ALWAYS, /* HYDROCARBON_WORLD */ PLANET_ALWAYS, /* IODINE_WORLD */ PLANET_ALWAYS, /* VINYLOGOUS_WORLD */ PLANET_NEVER, /* RUBY_WORLD */ PLANET_ALWAYS, /* MAGMA_WORLD */ PLANET_ALWAYS, /* MAROON_WORLD */ PLANET_ALWAYS, /* BLU_GAS_GIANT */ PLANET_ALWAYS, /* CYA_GAS_GIANT */ PLANET_ALWAYS, /* GRN_GAS_GIANT */ PLANET_ALWAYS, /* GRY_GAS_GIANT */ PLANET_ALWAYS, /* ORA_GAS_GIANT */ PLANET_ALWAYS, /* PUR_GAS_GIANT */ PLANET_ALWAYS, /* RED_GAS_GIANT */ PLANET_ALWAYS, /* VIO_GAS_GIANT */ PLANET_ALWAYS, /* YEL_GAS_GIANT */ }; return (PlanetDistribution[which_world]); } #define DWARF_ROCK_DIST MIN_PLANET_RADIUS #define DWARF_GASG_DIST SCALE_RADIUS (12) #define GIANT_ROCK_DIST SCALE_RADIUS (8) #define GIANT_GASG_DIST SCALE_RADIUS (13) #define SUPERGIANT_ROCK_DIST SCALE_RADIUS (16) #define SUPERGIANT_GASG_DIST SCALE_RADIUS (33) void FillOrbits (PSOLARSYS_STATE system, BYTE NumPlanets, PPLANET_DESC pBaseDesc, BOOLEAN TypesDefined) { /* Generate Planets in orbit around star */ BYTE StarColor, PlanetCount, MaxPlanet; BOOLEAN GeneratingMoons; COUNT StarSize; PPLANET_DESC pPD; struct { COUNT MinRockyDist, MinGasGDist; } Suns[] = { {DWARF_ROCK_DIST, DWARF_GASG_DIST}, {GIANT_ROCK_DIST, GIANT_GASG_DIST}, {SUPERGIANT_ROCK_DIST, SUPERGIANT_GASG_DIST}, }; #ifdef DEBUG_ORBITS UNICODE buf[256]; char stype[] = {'D', 'G', 'S'}; char scolor[] = {'B', 'G', 'O', 'R', 'W', 'Y'}; #endif /* DEBUG_ORBITS */ pPD = pBaseDesc; StarSize = system->SunDesc[0].data_index; StarColor = STAR_COLOR (CurStarDescPtr->Type); if (NumPlanets == (BYTE)~0) { #define MAX_GENERATED_PLANETS 10 while ((NumPlanets = (BYTE)(LOWORD (TFB_Random()) % MAX_GENERATED_PLANETS)) == 0) ; system->SunDesc[0].NumPlanets = NumPlanets; } #ifdef DEBUG_ORBITS GetClusterName (CurStarDescPtr, buf); log_add (log_Debug, "cluster name = %s color = %c type = %c", buf, scolor[STAR_COLOR (CurStarDescPtr->Type)], stype[STAR_TYPE (CurStarDescPtr->Type)]); #endif /* DEBUG_ORBITS */ GeneratingMoons = (BOOLEAN) (pBaseDesc == system->MoonDesc); if (GeneratingMoons) MaxPlanet = FIRST_LARGE_ROCKY_WORLD; else MaxPlanet = NUMBER_OF_PLANET_TYPES; PlanetCount = NumPlanets; while (NumPlanets--) { BYTE chance; DWORD rand_val; COUNT min_radius, angle; SIZE delta_r; PPLANET_DESC pLocPD; do { rand_val = TFB_Random (); if (TypesDefined) rand_val = 0; else pPD->data_index = (BYTE)(HIBYTE (LOWORD (rand_val)) % MaxPlanet); chance = PLANET_NEVER; switch (StarColor) { case BLUE_BODY: chance = BlueDistribution (pPD->data_index); break; case GREEN_BODY: chance = GreenDistribution (pPD->data_index); break; case ORANGE_BODY: chance = OrangeDistribution (pPD->data_index); break; case RED_BODY: chance = RedDistribution (pPD->data_index); break; case WHITE_BODY: chance = WhiteDistribution (pPD->data_index); break; case YELLOW_BODY: chance = YellowDistribution (pPD->data_index); break; } } while (LOBYTE (LOWORD (rand_val)) >= chance); if (pPD->data_index < FIRST_GAS_GIANT) min_radius = Suns[StarSize].MinRockyDist; else min_radius = Suns[StarSize].MinGasGDist; RelocatePlanet: rand_val = TFB_Random (); if (GeneratingMoons) { pPD->radius = MIN_MOON_RADIUS + ((LOWORD (rand_val) % MAX_MOONS) * MOON_DELTA); for (pLocPD = pPD - 1; pLocPD >= pBaseDesc; --pLocPD) { if (pPD->radius == pLocPD->radius) goto RelocatePlanet; } pPD->NumPlanets = 0; } else { pPD->radius = (LOWORD (rand_val) % (MAX_PLANET_RADIUS - min_radius)) + min_radius; for (pLocPD = pPD - 1; pLocPD >= pBaseDesc; --pLocPD) { delta_r = UNSCALE_RADIUS (pLocPD->radius) / 5 - UNSCALE_RADIUS (pPD->radius) / 5; if (delta_r < 0) delta_r = -delta_r; if (delta_r <= 1) goto RelocatePlanet; } } rand_val = TFB_Random (); angle = NORMALIZE_ANGLE (LOWORD (rand_val)); pPD->location.x = COSINE (angle, pPD->radius); pPD->location.y = SINE (angle, pPD->radius); pPD->rand_seed = MAKE_DWORD (pPD->location.x, pPD->location.y); ++pPD; } { BYTE i; for (i = 0; i < PlanetCount; ++i) { BYTE j; for (j = (BYTE)(PlanetCount - 1); j > i; --j) { if (pBaseDesc[i].radius > pBaseDesc[j].radius) { PLANET_DESC temp; temp = pBaseDesc[i]; pBaseDesc[i] = pBaseDesc[j]; pBaseDesc[j] = temp; } } } } } uqm-0.6.2/sc2/src/sc2code/planets/gensol.c0000600000175000017500000004761110543202100016704 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "gamestr.h" #include "globdata.h" #include "lander.h" #include "lifeform.h" #include "nameref.h" #include "races.h" #include "resinst.h" #include "state.h" #include "encount.h" #include "planets/genall.h" #include "libs/mathlib.h" static int init_probe (void) { HSTARSHIP hStarShip; if (!GET_GAME_STATE (PROBE_MESSAGE_DELIVERED) && GetGroupInfo (GLOBAL (BattleGroupRef), GROUP_INIT_IP) && (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)))) { SHIP_FRAGMENTPTR FragPtr; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); SET_GROUP_MISSION (FragPtr, IN_ORBIT); SET_GROUP_LOC (FragPtr, 2 + 1); /* orbitting earth */ SET_GROUP_DEST (FragPtr, 2 + 1); /* orbitting earth */ FragPtr->ShipInfo.loc.x = FragPtr->ShipInfo.loc.y = 0; FragPtr->ShipInfo.group_counter = 0; UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); return 1; } else return 0; } static void generate_energy_nodes (void) { /* Pluto */ if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[8]) { if (!GET_GAME_STATE (FOUND_PLUTO_SPATHI)) { pSolarSysState->SysInfo.PlanetInfo.CurPt.x = 20; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = MAP_HEIGHT - 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; pSolarSysState->SysInfo.PlanetInfo.CurType = 2; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { SET_GAME_STATE (FOUND_PLUTO_SPATHI, 1); pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << 0); ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; } else if (pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; return; } } /* Earth Moon */ else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[2] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[1] && !GET_GAME_STATE (MOONBASE_DESTROYED)) { pSolarSysState->SysInfo.PlanetInfo.CurPt.x = MAP_WIDTH * 3 / 4; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = MAP_HEIGHT * 1 / 4; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; pSolarSysState->SysInfo.PlanetInfo.CurType = 0; if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; else { pSolarSysState->CurNode = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { SET_GAME_STATE (MOONBASE_DESTROYED, 1); SET_GAME_STATE (MOONBASE_ON_SHIP, 1); } } return; } pSolarSysState->CurNode = 0; } static void generate_tractors (void) { if (pSolarSysState->pOrbitalDesc->pPrevDesc != &pSolarSysState->PlanetDesc[2] || pSolarSysState->pOrbitalDesc != &pSolarSysState->MoonDesc[1]) pSolarSysState->CurNode = 0; else /* Earth Moon */ { COUNT i, which_node; DWORD old_rand, rand_val; old_rand = TFB_SeedRandom (pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = NUM_CREATURE_TYPES + 1; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] & (1L << i))) break; ++which_node; } while (++i < 10); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); } } static void generate_orbital (void) { COUNT i; DWORD rand_val; /* Starbase */ if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[2] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) { PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); EncounterGroup = 0; GLOBAL (CurrentActivity) |= START_ENCOUNTER; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, (BYTE)~0); return; } rand_val = DoPlanetaryAnalysis (&pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc); if (rand_val) { pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; i = (COUNT)~0; rand_val = GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); } if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->SunDesc[0]) { i = pSolarSysState->pOrbitalDesc - pSolarSysState->PlanetDesc; switch (i) { case 0: /* MERCURY */ pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 0; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 98; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 38; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 3; pSolarSysState->SysInfo.PlanetInfo.Weather = 0; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 2; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 59 * 240; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 165; break; case 1: /* VENUS */ pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 90 * EARTH_ATMOSPHERE; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 95; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 95; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 177; pSolarSysState->SysInfo.PlanetInfo.Weather = 7; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 243 * 240; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 457; break; case 2: /* EARTH */ pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = EARTH_ATMOSPHERE; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 100; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 100; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 23; pSolarSysState->SysInfo.PlanetInfo.Weather = 1; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 240; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 22; break; case 3: /* MARS */ // XXX: Mars atmo should actually be 1/2 in current units pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 1; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 72; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 53; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 24; pSolarSysState->SysInfo.PlanetInfo.Weather = 1; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 246; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -53; break; case 4: /* JUPITER */ pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = GAS_GIANT_ATMOSPHERE; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 24; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 1120; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 3; pSolarSysState->SysInfo.PlanetInfo.Weather = 7; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 98; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -143; pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 520L / 100; break; case 5: /* SATURN */ pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = GAS_GIANT_ATMOSPHERE; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 13; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 945; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 27; pSolarSysState->SysInfo.PlanetInfo.Weather = 7; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 102; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -197; pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 952L / 100; break; case 6: /* URANUS */ pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = GAS_GIANT_ATMOSPHERE; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 21; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 411; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 98; pSolarSysState->SysInfo.PlanetInfo.Weather = 7; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 172; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -217; pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 1916L / 100; break; case 7: /* NEPTUNE */ pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = GAS_GIANT_ATMOSPHERE; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 28; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 396; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 30; pSolarSysState->SysInfo.PlanetInfo.Weather = 7; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 182; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -229; pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 2999L / 100; break; case 8: /* PLUTO */ if (!GET_GAME_STATE (FOUND_PLUTO_SPATHI)) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (SPAPLUTO_MASK_PMAP_ANIM)); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (SPAPLUTO_STRTAB)); } pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 0; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 33; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 18; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 119; pSolarSysState->SysInfo.PlanetInfo.Weather = 0; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 1533; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -235; pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 3937L / 100; break; } pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity = CalcGravity (pSolarSysState->SysInfo.PlanetInfo.PlanetDensity, pSolarSysState->SysInfo.PlanetInfo.PlanetRadius); LoadPlanet (i == 2 ? CaptureDrawable (LoadGraphic (EARTH_MASK_ANIM)) : NULL); } else { i = pSolarSysState->pOrbitalDesc->pPrevDesc - pSolarSysState->PlanetDesc; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 0; pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 0; pSolarSysState->SysInfo.PlanetInfo.Weather = 0; switch (i) { case 2: /* moons of EARTH */ pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; if (!GET_GAME_STATE (MOONBASE_DESTROYED)) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (MOONBASE_MASK_PMAP_ANIM)); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (MOONBASE_STRTAB)); } pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 60; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 25; pSolarSysState->SysInfo.PlanetInfo.AxialTilt = 0; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 240 * 29; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -18; break; case 4: /* moons of JUPITER */ pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 520L / 100; switch (pSolarSysState->pOrbitalDesc - pSolarSysState->MoonDesc) { case 0: /* Io */ pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 69; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 25; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 3; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 390; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -163; break; case 1: /* Europa */ pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 54; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 25; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 840; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -161; break; case 2: /* Ganymede */ pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 35; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 41; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 1728; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -164; break; case 3: /* Callisto */ pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 35; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 38; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 4008; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -167; break; } break; case 5: /* moon of SATURN: Titan */ pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 952L / 100; pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 160; pSolarSysState->SysInfo.PlanetInfo.Weather = 2; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 34; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 40; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 3816; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -178; break; case 7: /* moon of NEPTUNE: Triton */ pSolarSysState->SysInfo.PlanetInfo.PlanetToSunDist = EARTH_RADIUS * 2999L / 100; pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = 10; pSolarSysState->SysInfo.PlanetInfo.Weather = 1; pSolarSysState->SysInfo.PlanetInfo.PlanetDensity = 95; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 27; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.RotationPeriod = 4300; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = -216; break; } pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity = CalcGravity (pSolarSysState->SysInfo.PlanetInfo.PlanetDensity, pSolarSysState->SysInfo.PlanetInfo.PlanetRadius); LoadPlanet (NULL); } } void GenerateSOL (BYTE control) { COUNT i; DWORD rand_val; PPLANET_DESC pCurDesc; switch (control) { case INIT_NPCS: GLOBAL (BattleGroupRef) = GET_GAME_STATE_32 (URQUAN_PROBE_GRPOFFS0); if (GLOBAL (BattleGroupRef) == 0) { CloneShipFragment (URQUAN_PROBE_SHIP, &GLOBAL (npc_built_ship_q), 0); GLOBAL (BattleGroupRef) = PutGroupInfo (GROUPS_ADD_NEW, 1); SET_GAME_STATE_32 (URQUAN_PROBE_GRPOFFS0, GLOBAL (BattleGroupRef)); } if (!init_probe ()) GenerateRandomIP (INIT_NPCS); break; case REINIT_NPCS: if (GET_GAME_STATE (CHMMR_BOMB_STATE) != 3) GenerateRandomIP (REINIT_NPCS); else { GLOBAL (BattleGroupRef) = 0; ReinitQueue (&GLOBAL (npc_built_ship_q)); } break; case GENERATE_ENERGY: generate_energy_nodes (); break; case GENERATE_LIFE: generate_tractors (); break; case GENERATE_ORBITAL: generate_orbital (); break; case GENERATE_NAME: i = pSolarSysState->pBaseDesc - pSolarSysState->PlanetDesc; utf8StringCopy (GLOBAL_SIS (PlanetName), sizeof (GLOBAL_SIS (PlanetName)), GAME_STRING (PLANET_NUMBER_BASE + i)); SET_GAME_STATE (BATTLE_PLANET, pSolarSysState->PlanetDesc[i].data_index); break; case GENERATE_MOONS: { GenerateRandomIP (GENERATE_MOONS); i = pSolarSysState->pBaseDesc - pSolarSysState->PlanetDesc; switch (i) { case 2: /* moons of EARTH */ { COUNT angle; /* Starbase: */ pSolarSysState->MoonDesc[0].data_index = (BYTE)~0; pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS; angle = HALF_CIRCLE + QUADRANT; pSolarSysState->MoonDesc[0].location.x = COSINE (angle, pSolarSysState->MoonDesc[0].radius); pSolarSysState->MoonDesc[0].location.y = SINE (angle, pSolarSysState->MoonDesc[0].radius); /* Luna: */ pSolarSysState->MoonDesc[1].data_index = SELENIC_WORLD; pSolarSysState->MoonDesc[1].radius = MIN_MOON_RADIUS + (MAX_MOONS - 1) * MOON_DELTA; rand_val = TFB_Random (); angle = NORMALIZE_ANGLE (LOWORD (rand_val)); pSolarSysState->MoonDesc[1].location.x = COSINE (angle, pSolarSysState->MoonDesc[1].radius); pSolarSysState->MoonDesc[1].location.y = SINE (angle, pSolarSysState->MoonDesc[1].radius); break; } case 4: /* moons of JUPITER */ pSolarSysState->MoonDesc[0].data_index = RADIOACTIVE_WORLD; /* Io */ pSolarSysState->MoonDesc[1].data_index = HALIDE_WORLD; /* Europa */ pSolarSysState->MoonDesc[2].data_index = CYANIC_WORLD; /* Ganymede */ pSolarSysState->MoonDesc[3].data_index = PELLUCID_WORLD; /* Callisto */ break; case 5: /* moons of SATURN */ pSolarSysState->MoonDesc[0].data_index = ALKALI_WORLD; /* Titan */ break; case 7: /* moons of NEPTUNE */ pSolarSysState->MoonDesc[0].data_index = VINYLOGOUS_WORLD; /* Triton */ break; } break; } case GENERATE_PLANETS: { #define SOL_SEED 334241042L TFB_SeedRandom (SOL_SEED); pSolarSysState->SunDesc[0].NumPlanets = 9; for (i = 0, pCurDesc = pSolarSysState->PlanetDesc; i < 9; ++i, ++pCurDesc) { COUNT angle; UWORD word_val; pCurDesc->rand_seed = rand_val = TFB_Random (); word_val = LOWORD (rand_val); angle = NORMALIZE_ANGLE ((COUNT)HIBYTE (word_val)); switch (i) { case 0: /* MERCURY */ pCurDesc->data_index = METAL_WORLD; pCurDesc->radius = EARTH_RADIUS * 39L / 100; pCurDesc->NumPlanets = 0; break; case 1: /* VENUS */ pCurDesc->data_index = PRIMORDIAL_WORLD; pCurDesc->radius = EARTH_RADIUS * 72L / 100; pCurDesc->NumPlanets = 0; angle = NORMALIZE_ANGLE (FULL_CIRCLE - angle); break; case 2: /* EARTH */ pCurDesc->data_index = WATER_WORLD | PLANET_SHIELDED; pCurDesc->radius = EARTH_RADIUS; pCurDesc->NumPlanets = 2; break; case 3: /* MARS */ pCurDesc->data_index = DUST_WORLD; pCurDesc->radius = EARTH_RADIUS * 152L / 100; pCurDesc->NumPlanets = 0; break; case 4: /* JUPITER */ pCurDesc->data_index = RED_GAS_GIANT; pCurDesc->radius = EARTH_RADIUS * 500L /* 520L */ / 100; pCurDesc->NumPlanets = 4; break; case 5: /* SATURN */ pCurDesc->data_index = ORA_GAS_GIANT; pCurDesc->radius = EARTH_RADIUS * 750L /* 952L */ / 100; pCurDesc->NumPlanets = 1; break; case 6: /* URANUS */ pCurDesc->data_index = GRN_GAS_GIANT; pCurDesc->radius = EARTH_RADIUS * 1000L /* 1916L */ / 100; pCurDesc->NumPlanets = 0; break; case 7: /* NEPTUNE */ pCurDesc->data_index = BLU_GAS_GIANT; pCurDesc->radius = EARTH_RADIUS * 1250L /* 2999L */ / 100; pCurDesc->NumPlanets = 1; break; case 8: /* PLUTO */ pCurDesc->data_index = PELLUCID_WORLD; pCurDesc->radius = EARTH_RADIUS * 1550L /* 3937L */ / 100; pCurDesc->NumPlanets = 0; angle = FULL_CIRCLE - OCTANT; break; } pCurDesc->location.x = COSINE (angle, pCurDesc->radius); pCurDesc->location.y = SINE (angle, pCurDesc->radius); } break; } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/sundata.h0000600000175000017500000000340610543202100017053 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SUNDATA_H #define _SUNDATA_H #include "planets/plandata.h" #include "libs/compiler.h" /*------------------------------ Global Data ------------------------------ */ #define NUMBER_OF_SUN_SIZES (SUPER_GIANT_STAR - DWARF_STAR + 1) #define DWARF_ENERGY 1 #define GIANT_ENERGY 5 #define SUPERGIANT_ENERGY 20 typedef struct { BYTE StarSize; BYTE StarIntensity; UWORD StarEnergy; PLANET_INFO PlanetInfo; } SYSTEM_INFO; typedef SYSTEM_INFO *PSYSTEM_INFO; #define SYSTEM_INFOPTR PSYSTEM_INFO extern DWORD GenerateMineralDeposits (SYSTEM_INFOPTR SysInfoPtr, PCOUNT pwhich_deposit); extern DWORD GenerateLifeForms (SYSTEM_INFOPTR SysInfoPtr, PCOUNT pwhich_life); #define DWARF_ELEMENT_DENSITY 1 #define GIANT_ELEMENT_DENSITY 3 #define SUPERGIANT_ELEMENT_DENSITY 8 #define MAX_ELEMENT_DENSITY ((MAX_ELEMENT_UNITS * SUPERGIANT_ELEMENT_DENSITY) << 1) extern DWORD DoPlanetaryAnalysis (SYSTEM_INFOPTR SysInfoPtr, PPLANET_DESC pPlanetDesc); extern SYSTEM_INFO CurSysInfo; #endif /* _SUNDATA_H */ uqm-0.6.2/sc2/src/sc2code/planets/genmyc.c0000600000175000017500000001541110543202100016670 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "nameref.h" #include "resinst.h" #include "setup.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateMycon (BYTE control) { switch (control) { case GENERATE_LIFE: pSolarSysState->CurNode = 0; break; case GENERATE_ENERGY: if (CurStarDescPtr->Index != MYCON_DEFINED && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; pSolarSysState->SysInfo.PlanetInfo.CurType = 0; if (CurStarDescPtr->Index == SUN_DEVICE_DEFINED) { if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; else { pSolarSysState->CurNode = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { SET_GAME_STATE (SUN_DEVICE, 1); SET_GAME_STATE (SUN_DEVICE_ON_SHIP, 1); SET_GAME_STATE (MYCON_VISITS, 0); } } } else { if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; else { pSolarSysState->CurNode = 0; if ((pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->SysInfo.PlanetInfo.DiscoveryString) { switch (CurStarDescPtr->Index) { case EGG_CASE0_DEFINED: SET_GAME_STATE (EGG_CASE0_ON_SHIP, 1); break; case EGG_CASE1_DEFINED: SET_GAME_STATE (EGG_CASE1_ON_SHIP, 1); break; case EGG_CASE2_DEFINED: SET_GAME_STATE (EGG_CASE2_ON_SHIP, 1); break; } } } } TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = CRACKED_WORLD; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 80L / 100; if (pSolarSysState->PlanetDesc[0].NumPlanets > 2) pSolarSysState->PlanetDesc[0].NumPlanets = 2; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { if ((CurStarDescPtr->Index == MYCON_DEFINED || CurStarDescPtr->Index == SUN_DEVICE_DEFINED) && ActivateStarShip (MYCON_SHIP, SPHERE_TRACKING)) { if (CurStarDescPtr->Index == MYCON_DEFINED || !GET_GAME_STATE (SUN_DEVICE_UNGUARDED)) { NotifyOthers (MYCON_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); if (CurStarDescPtr->Index == MYCON_DEFINED || !GET_GAME_STATE (MYCON_FELL_FOR_AMBUSH)) CloneShipFragment (MYCON_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); else { COUNT i; for (i = 0; i < 5; ++i) CloneShipFragment (MYCON_SHIP, &GLOBAL (npc_built_ship_q), 0); } pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; if (CurStarDescPtr->Index == MYCON_DEFINED) { SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); } else { SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); } InitCommunication (MYCON_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) break; { BOOLEAN MyconSurvivors; MyconSurvivors = GetHeadLink ( &GLOBAL (npc_built_ship_q) ) != 0; GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); if (MyconSurvivors) break; SET_GAME_STATE (SUN_DEVICE_UNGUARDED, 1); LockMutex (GraphicsLock); RepairSISBorder (); UnlockMutex (GraphicsLock); } } } switch (CurStarDescPtr->Index) { case SUN_DEVICE_DEFINED: if (!GET_GAME_STATE (SUN_DEVICE)) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (SUN_DEVICE_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (SUN_DEVICE_STRTAB) ); } break; case EGG_CASE0_DEFINED: case EGG_CASE1_DEFINED: case EGG_CASE2_DEFINED: if (GET_GAME_STATE (KNOW_ABOUT_SHATTERED) == 0) { SET_GAME_STATE (KNOW_ABOUT_SHATTERED, 1); } if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0))) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (EGG_CASE_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (EGG_CASE_STRTAB) ); } break; } } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/genspa.c0000600000175000017500000001746610543202100016677 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "lifeform.h" #include "nameref.h" #include "resinst.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateSpathi (BYTE control) { COUNT i, angle; DWORD rand_val; switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0] && !GET_GAME_STATE (UMGAH_BROADCASTERS)) { DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; pSolarSysState->SysInfo.PlanetInfo.CurType = 0; if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; else { pSolarSysState->CurNode = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { SET_GAME_STATE (UMGAH_BROADCASTERS, 1); SET_GAME_STATE (UMGAH_BROADCASTERS_ON_SHIP, 1); } } TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_MOONS: GenerateRandomIP (GENERATE_MOONS); if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[0]) { #ifdef NOTYET utf8StringCopy (GLOBAL_SIS (PlanetName), sizeof (GLOBAL_SIS (PlanetName)), "Spathiwa"); #endif /* NOTYET */ pSolarSysState->MoonDesc[0].data_index = PELLUCID_WORLD; pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS + MOON_DELTA; angle = NORMALIZE_ANGLE (LOWORD (TFB_Random ())); pSolarSysState->MoonDesc[0].location.x = COSINE (angle, pSolarSysState->MoonDesc[0].radius); pSolarSysState->MoonDesc[0].location.y = SINE (angle, pSolarSysState->MoonDesc[0].radius); } break; case GENERATE_PLANETS: { PPLANET_DESC pMinPlanet; pMinPlanet = &pSolarSysState->PlanetDesc[0]; FillOrbits (pSolarSysState, pSolarSysState->SunDesc[0].NumPlanets = 1, pMinPlanet, FALSE); pMinPlanet->radius = EARTH_RADIUS * 1150L / 100; angle = ARCTAN (pMinPlanet->location.x, pMinPlanet->location.y); pMinPlanet->location.x = COSINE (angle, pMinPlanet->radius); pMinPlanet->location.y = SINE (angle, pMinPlanet->radius); pMinPlanet->data_index = WATER_WORLD; if (GET_GAME_STATE (SPATHI_SHIELDED_SELVES)) pMinPlanet->data_index |= PLANET_SHIELDED; pMinPlanet->NumPlanets = 1; break; } case GENERATE_LIFE: /* visiting Spathiwa */ if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0] && !GET_GAME_STATE (SPATHI_SHIELDED_SELVES)) { COUNT which_node; DWORD old_rand; old_rand = TFB_SeedRandom (pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = NUM_CREATURE_TYPES; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] & (1L << i))) break; ++which_node; } while (++i < 32); pSolarSysState->CurNode = which_node; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN]) { SET_GAME_STATE (SPATHI_CREATURES_EXAMINED, 1); if (pSolarSysState->SysInfo. PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] == 0xFFFFFFFF) SET_GAME_STATE (SPATHI_CREATURES_ELIMINATED, 1); } TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) { if (!GET_GAME_STATE (SPATHI_SHIELDED_SELVES) && ActivateStarShip (SPATHI_SHIP, SPHERE_TRACKING)) { NotifyOthers (SPATHI_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (SPATHI_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); GLOBAL (CurrentActivity) |= START_INTERPLANETARY; InitCommunication (SPATHI_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } rand_val = DoPlanetaryAnalysis ( &pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc ); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; i = (COUNT)~0; rand_val = GenerateLifeForms (&pSolarSysState->SysInfo, &i); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; i = (COUNT)~0; GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] = rand_val; pSolarSysState->SysInfo.PlanetInfo.Weather = 0; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 28; if (!GET_GAME_STATE (UMGAH_BROADCASTERS)) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (UMGAH_BCS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (UMGAH_BCS_STRTAB) ); } LoadPlanet (NULL); break; } else if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { /* visiting Spathiwa */ rand_val = DoPlanetaryAnalysis ( &pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc ); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; i = (COUNT)~0; rand_val = GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; pSolarSysState->SysInfo.PlanetInfo.PlanetRadius = 120; pSolarSysState->SysInfo.PlanetInfo.SurfaceGravity = CalcGravity (pSolarSysState->SysInfo.PlanetInfo.PlanetDensity, pSolarSysState->SysInfo.PlanetInfo.PlanetRadius); pSolarSysState->SysInfo.PlanetInfo.Weather = 0; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 31; LoadPlanet (NULL); break; } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/calc.c0000600000175000017500000002702310543202077016327 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ----------------------------- INCLUDES ---------------------------- */ #include "encount.h" #include "libs/mathlib.h" #include "libs/log.h" /* -------------------------------- DATA -------------------------------- */ /* -------------------------------- CODE -------------------------------- */ //#define DEBUG_PLANET_CALC #define CalcMass(b) CalcFromBase (b, b) #define CalcRadius(b) CalcFromBase (b, ((b) >> 1) + 1) #define LOW_TEMP 0 #define MED_TEMP 500 #define HIGH_TEMP 1500 #define LOW_TEMP_BONUS 10 #define MED_TEMP_BONUS 25 #define HIGH_TEMP_BONUS 50 #define MAX_TECTONICS 255 #ifdef OLD #define CalcTectonics(b,t) (CalcFromBase(b, 3 << 5) \ + (UWORD)((t) < LOW_TEMP ? 0 : \ ((t) < MED_TEMP ? LOW_TEMP_BONUS : \ ((t) < HIGH_TEMP ? MED_TEMP_BONUS : \ HIGH_TEMP_BONUS)))) #else /* OLD */ #define CalcTectonics(b,t) CalcFromBase(b, 3 << 5) #endif /* OLD */ enum { RED_SUN_INTENSITY = 0, ORANGE_SUN_INTENSITY, YELLOW_SUN_INTENSITY, GREEN_SUN_INTENSITY, BLUE_SUN_INTENSITY, WHITE_SUN_INTENSITY }; static void CalcSysInfo (SYSTEM_INFOPTR SysInfoPtr) { SysInfoPtr->StarSize = pSolarSysState->SunDesc[0].data_index; switch (STAR_COLOR (CurStarDescPtr->Type)) { case BLUE_BODY: SysInfoPtr->StarIntensity = BLUE_SUN_INTENSITY; break; case GREEN_BODY: SysInfoPtr->StarIntensity = GREEN_SUN_INTENSITY; break; case ORANGE_BODY: SysInfoPtr->StarIntensity = ORANGE_SUN_INTENSITY; break; case RED_BODY: SysInfoPtr->StarIntensity = RED_SUN_INTENSITY; break; case WHITE_BODY: SysInfoPtr->StarIntensity = WHITE_SUN_INTENSITY; break; case YELLOW_BODY: SysInfoPtr->StarIntensity = YELLOW_SUN_INTENSITY; break; } switch (STAR_TYPE (CurStarDescPtr->Type)) { case DWARF_STAR: SysInfoPtr->StarEnergy = (SysInfoPtr->StarIntensity + 1) * DWARF_ENERGY; break; case GIANT_STAR: SysInfoPtr->StarEnergy = (SysInfoPtr->StarIntensity + 1) * GIANT_ENERGY; break; case SUPER_GIANT_STAR: SysInfoPtr->StarEnergy = (SysInfoPtr->StarIntensity + 1) * SUPERGIANT_ENERGY; break; } } static UWORD GeneratePlanetComposition (PLANET_INFOPTR PlanetInfoPtr, SIZE SurfaceTemp, SIZE radius) { if (PLANSIZE (PlanetInfoPtr->PlanDataPtr->Type) == GAS_GIANT) { PlanetInfoPtr->Weather = 7 << 5; return (GAS_GIANT_ATMOSPHERE); } else { BYTE range; UWORD atmo; PlanetInfoPtr->Weather = 0; atmo = 0; if ((range = HINIBBLE (PlanetInfoPtr->PlanDataPtr->AtmoAndDensity)) <= HEAVY) { if (SurfaceTemp < COLD_THRESHOLD) --range; else if (SurfaceTemp > HOT_THRESHOLD) ++range; if (range <= HEAVY + 1) { switch (range) { case LIGHT: atmo = THIN_ATMOSPHERE; PlanetInfoPtr->Weather = 1 << 5; break; case MEDIUM: atmo = NORMAL_ATMOSPHERE; PlanetInfoPtr->Weather = 2 << 5; break; case HEAVY: atmo = THICK_ATMOSPHERE; PlanetInfoPtr->Weather = 4 << 5; break; default: atmo = SUPER_THICK_ATMOSPHERE; PlanetInfoPtr->Weather = 6 << 5; break; } radius /= EARTH_RADIUS; if (radius < 2) PlanetInfoPtr->Weather += 1 << 5; else if (radius > 10) PlanetInfoPtr->Weather -= 1 << 5; atmo = CalcFromBase (atmo, (atmo >> 1) + 1); } } return (atmo); } } // This function is called both when the solar system is generated, // and when planetary orbit is entered. // In the former case, the if() block will not be executed, // which means that the temperature calculated in that case will be // slightly lower. The result is that the orbits may not always // have the colour you'd expect based on the true temperature. // (eg. Beta Corvi I). I don't know what the idea behind this is, // but the if statement must be there for a reason. -- SvdB static SIZE CalcTemp (SYSTEM_INFOPTR SysInfoPtr, SIZE radius) { #define GENERIC_ALBEDO 33 /* In %, 0=black, 100 is reflective */ #define ADJUST_FOR_KELVIN 273 #define PLANET_TEMP_CONSTANT 277L DWORD alb; SIZE centigrade, bonus; alb = 100 - GENERIC_ALBEDO; alb = square_root (square_root (alb * 100 * 10000)) * PLANET_TEMP_CONSTANT * SysInfoPtr->StarEnergy / ((YELLOW_SUN_INTENSITY + 1) * DWARF_ENERGY); centigrade = (SIZE)(alb / square_root (radius * 10000L / EARTH_RADIUS)) - ADJUST_FOR_KELVIN; bonus = 0; if (SysInfoPtr == &pSolarSysState->SysInfo && HINIBBLE (SysInfoPtr->PlanetInfo.PlanDataPtr->AtmoAndDensity) <= HEAVY) { #define COLD_BONUS 20 #define HOT_BONUS 200 if (centigrade >= HOT_THRESHOLD) bonus = HOT_BONUS; else if (centigrade >= COLD_THRESHOLD) bonus = COLD_BONUS; bonus <<= HINIBBLE (SysInfoPtr->PlanetInfo.PlanDataPtr->AtmoAndDensity); bonus = CalcFromBase (bonus, (bonus >> 1) + 1); } return (centigrade + bonus); } static COUNT CalcRotation (PLANET_INFOPTR PlanetInfoPtr) { if (PLANSIZE (PlanetInfoPtr->PlanDataPtr->Type) == GAS_GIANT) return ((COUNT)CalcFromBase (80, 80)); else if (((BYTE)TFB_Random () % 10) == 0) return ((COUNT)CalcFromBase ((UWORD)50 * 240, (UWORD)200 * 240)); else return ((COUNT)CalcFromBase (150, 150)); } static SIZE CalcTilt (void) { /* Calculate Axial Tilt */ SIZE tilt; BYTE i; #define NUM_TOSSES 10 #define TILT_RANGE 180 tilt = -(TILT_RANGE / 2); i = NUM_TOSSES; do /* Using added Randomom values to give bell curve */ { tilt += (UWORD)TFB_Random () % ((TILT_RANGE / NUM_TOSSES) + 1); } while (--i); return (tilt); } // NB. Returns the RNG to the state it found it in. DWORD DoPlanetaryAnalysis (SYSTEM_INFOPTR SysInfoPtr, PPLANET_DESC pPlanetDesc) { DWORD old_seed; /* Earth Starbase */ if (pPlanetDesc->data_index == (BYTE)~0) return (0); old_seed = TFB_SeedRandom (pPlanetDesc->rand_seed); CalcSysInfo (SysInfoPtr); #ifdef DEBUG_PLANET_CALC { BYTE ColorClass[6][8] = { "Red", "Orange", "Yellow", "Green", "Blue", "White", }; BYTE SizeName[3][12] = { "Dwarf", "Giant", "Supergiant", }; log_add (log_Debug, "%s %s", ColorClass[SysInfoPtr->StarIntensity], SizeName[SysInfoPtr->StarSize]); log_add (log_Debug, "Stellar Energy: %d (sol = 3)", SysInfoPtr->StarEnergy); } #endif /* DEBUG_PLANET_CALC */ { SIZE radius; SysInfoPtr->PlanetInfo.PlanDataPtr = &PlanData[pPlanetDesc->data_index & ~PLANET_SHIELDED]; if (pPlanetDesc->pPrevDesc == pSolarSysState->SunDesc) radius = pPlanetDesc->radius; else radius = pPlanetDesc->pPrevDesc->radius; SysInfoPtr->PlanetInfo.PlanetToSunDist = radius; SysInfoPtr->PlanetInfo.SurfaceTemperature = CalcTemp (SysInfoPtr, radius); switch (LONIBBLE (SysInfoPtr->PlanetInfo.PlanDataPtr->AtmoAndDensity)) { case GAS_DENSITY: SysInfoPtr->PlanetInfo.PlanetDensity = 20; break; case LIGHT_DENSITY: SysInfoPtr->PlanetInfo.PlanetDensity = 33; break; case LOW_DENSITY: SysInfoPtr->PlanetInfo.PlanetDensity = 60; break; case NORMAL_DENSITY: SysInfoPtr->PlanetInfo.PlanetDensity = 100; break; case HIGH_DENSITY: SysInfoPtr->PlanetInfo.PlanetDensity = 150; break; case SUPER_DENSITY: SysInfoPtr->PlanetInfo.PlanetDensity = 200; break; } SysInfoPtr->PlanetInfo.PlanetDensity += (SysInfoPtr->PlanetInfo.PlanetDensity / 20) - ((COUNT)TFB_Random () % (SysInfoPtr->PlanetInfo.PlanetDensity / 10)); switch (PLANSIZE (SysInfoPtr->PlanetInfo.PlanDataPtr->Type)) { case SMALL_ROCKY_WORLD: #define SMALL_RADIUS 25 SysInfoPtr->PlanetInfo.PlanetRadius = CalcRadius (SMALL_RADIUS); break; case LARGE_ROCKY_WORLD: #define LARGE_RADIUS 75 SysInfoPtr->PlanetInfo.PlanetRadius = CalcRadius (LARGE_RADIUS); break; case GAS_GIANT: #define MIN_GAS_RADIUS 300 #define MAX_GAS_RADIUS 1500 SysInfoPtr->PlanetInfo.PlanetRadius = CalcFromBase (MIN_GAS_RADIUS, MAX_GAS_RADIUS - MIN_GAS_RADIUS); break; } SysInfoPtr->PlanetInfo.RotationPeriod = CalcRotation (&SysInfoPtr->PlanetInfo); SysInfoPtr->PlanetInfo.SurfaceGravity = CalcGravity (SysInfoPtr->PlanetInfo.PlanetDensity, SysInfoPtr->PlanetInfo.PlanetRadius); SysInfoPtr->PlanetInfo.AxialTilt = CalcTilt (); if ((SysInfoPtr->PlanetInfo.Tectonics = CalcTectonics (SysInfoPtr->PlanetInfo.PlanDataPtr->BaseTectonics, SysInfoPtr->PlanetInfo.SurfaceTemperature)) > MAX_TECTONICS) SysInfoPtr->PlanetInfo.Tectonics = MAX_TECTONICS; SysInfoPtr->PlanetInfo.AtmoDensity = GeneratePlanetComposition (&SysInfoPtr->PlanetInfo, SysInfoPtr->PlanetInfo.SurfaceTemperature, radius); SysInfoPtr->PlanetInfo.Tectonics >>= 5; SysInfoPtr->PlanetInfo.Weather >>= 5; #ifdef DEBUG_PLANET_CALC radius = (SIZE)((DWORD)UNSCALE_RADIUS (radius) * 100 / UNSCALE_RADIUS (EARTH_RADIUS)); log_add (log_Debug, "\tOrbital Distance : %d.%02d AU", radius / 100, radius % 100); //log_add (log_Debug, "\tPlanetary Mass : %d.%02d Earth masses", // SysInfoPtr->PlanetInfo.PlanetMass / 100, // SysInfoPtr->PlanetInfo.PlanetMass % 100); log_add (log_Debug, "\tPlanetary Radius : %d.%02d Earth radii", SysInfoPtr->PlanetInfo.PlanetRadius / 100, SysInfoPtr->PlanetInfo.PlanetRadius % 100); log_add (log_Debug, "\tSurface Gravity: %d.%02d gravities", SysInfoPtr->PlanetInfo.SurfaceGravity / 100, SysInfoPtr->PlanetInfo.SurfaceGravity % 100); log_add (log_Debug, "\tSurface Temperature: %d degrees C", SysInfoPtr->PlanetInfo.SurfaceTemperature ); log_add (log_Debug, "\tAxial Tilt : %d degrees", abs (SysInfoPtr->PlanetInfo.AxialTilt)); log_add (log_Debug, "\tTectonics : Class %u", SysInfoPtr->PlanetInfo.Tectonics + 1); log_add (log_Debug, "\tAtmospheric Density: %u.%02u", SysInfoPtr->PlanetInfo.AtmoDensity / EARTH_ATMOSPHERE, (SysInfoPtr->PlanetInfo.AtmoDensity * 100 / EARTH_ATMOSPHERE) % 100); if (SysInfoPtr->PlanetInfo.AtmoDensity == 0) { log_add (log_Debug, "\tAtmosphere: (Vacuum)"); } else if (SysInfoPtr->PlanetInfo.AtmoDensity < THIN_ATMOSPHERE) { log_add (log_Debug, "\tAtmosphere: (Thin)"); } else if (SysInfoPtr->PlanetInfo.AtmoDensity < NORMAL_ATMOSPHERE) { log_add (log_Debug, "\tAtmosphere: (Normal)"); } else if (SysInfoPtr->PlanetInfo.AtmoDensity < THICK_ATMOSPHERE) { log_add (log_Debug, "\tAtmosphere: (Thick)"); } else if (SysInfoPtr->PlanetInfo.AtmoDensity < SUPER_THICK_ATMOSPHERE) { log_add (log_Debug, "\tAtmosphere: (Super thick)"); } else { log_add (log_Debug, "\tAtmosphere: (Gas Giant)"); } log_add (log_Debug, "\tWeather : Class %u", SysInfoPtr->PlanetInfo.Weather + 1); if (SysInfoPtr->PlanetInfo.RotationPeriod >= 480) { log_add (log_Debug, "\tLength of day : %d.%d Earth days", SysInfoPtr->PlanetInfo.RotationPeriod / 240, SysInfoPtr->PlanetInfo.RotationPeriod % 240); } else { log_add (log_Debug, "\tLength of day : %d.%d Earth hours", SysInfoPtr->PlanetInfo.RotationPeriod / 10, SysInfoPtr->PlanetInfo.RotationPeriod % 10); } #endif /* DEBUG_PLANET_CALC */ } return (TFB_SeedRandom (old_seed)); } uqm-0.6.2/sc2/src/sc2code/planets/lander.c0000600000175000017500000016340310543202100016660 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "controls.h" #include "colors.h" #include "encount.h" #include "gamestr.h" #include "lander.h" #include "lifeform.h" #include "scan.h" #include "nameref.h" #include "resinst.h" #include "setup.h" #include "sounds.h" #include "element.h" #include "libs/graphics/gfx_common.h" #include "libs/mathlib.h" //define SPIN_ON_LAUNCH to let the planet spin while // the lander animation is playing #define SPIN_ON_LAUNCH // PLANET_SIDE_RATE governs how fast the lander, // bio and planet effects will be // We're using the 3DO speed, which is 35 FPS // The PC speed was 30 FPS. // Remember that all values need to evenly divide // ONE_SECOND. #define PLANET_SIDE_RATE (ONE_SECOND / 35) FRAME LanderFrame[8]; static SOUND LanderSounds; MUSIC_REF LanderMusic; #define NUM_ORBIT_THEMES 5 static MUSIC_REF OrbitMusic[NUM_ORBIT_THEMES]; const LIFEFORM_DESC CreatureData[] = { {SPEED_MOTIONLESS | DANGER_HARMLESS, MAKE_BYTE (1, 1)}, // Roto-Dendron {SPEED_MOTIONLESS | DANGER_HARMLESS, MAKE_BYTE (6, 1)}, // Macrocillia {SPEED_MOTIONLESS | DANGER_WEAK, MAKE_BYTE (3, 1)}, // Splort Wort {SPEED_MOTIONLESS | DANGER_NORMAL, MAKE_BYTE (5, 3)}, // Whackin' Bush {SPEED_MOTIONLESS | DANGER_HARMLESS, MAKE_BYTE (2, 10)}, // Slot Machine Tree {BEHAVIOR_UNPREDICTABLE | SPEED_SLOW | DANGER_HARMLESS, MAKE_BYTE (1, 2)}, // Neon Worm {BEHAVIOR_FLEE | AWARENESS_MEDIUM | SPEED_SLOW | DANGER_HARMLESS, MAKE_BYTE (8, 5)}, // Stiletto Urchin {BEHAVIOR_HUNT | AWARENESS_LOW | SPEED_SLOW | DANGER_WEAK, MAKE_BYTE (2, 2)}, // Deluxe Blob {BEHAVIOR_UNPREDICTABLE | SPEED_SLOW | DANGER_NORMAL, MAKE_BYTE (3, 8)}, // Glowing Medusa {BEHAVIOR_HUNT | AWARENESS_MEDIUM | SPEED_SLOW | DANGER_MONSTROUS, MAKE_BYTE (10, 15)}, // Carousel Beast {BEHAVIOR_HUNT | AWARENESS_MEDIUM | SPEED_MEDIUM | DANGER_WEAK, MAKE_BYTE (3, 3)}, // Mysterious Bees {BEHAVIOR_FLEE | AWARENESS_MEDIUM | SPEED_MEDIUM | DANGER_HARMLESS, MAKE_BYTE (2, 1)}, // Hopping Blobby {BEHAVIOR_UNPREDICTABLE | SPEED_MEDIUM | DANGER_WEAK, MAKE_BYTE (2, 2)}, // Blood Monkey {BEHAVIOR_HUNT | AWARENESS_HIGH | SPEED_MEDIUM | DANGER_NORMAL, MAKE_BYTE (4, 6)}, // Yompin Yiminy {BEHAVIOR_UNPREDICTABLE | SPEED_MEDIUM | DANGER_MONSTROUS, MAKE_BYTE (9, 12)}, // Amorphous Trandicula {BEHAVIOR_HUNT | AWARENESS_HIGH | SPEED_FAST | DANGER_WEAK, MAKE_BYTE (3, 1)}, // Crazy Weasel {BEHAVIOR_FLEE | AWARENESS_HIGH | SPEED_FAST | DANGER_HARMLESS, MAKE_BYTE (1, 1)}, // Merry Whumpet {BEHAVIOR_HUNT | AWARENESS_LOW | SPEED_FAST | DANGER_NORMAL, MAKE_BYTE (7, 8)}, // Fungal Squid {BEHAVIOR_FLEE | AWARENESS_HIGH | SPEED_FAST | DANGER_WEAK, MAKE_BYTE (15, 2)}, // Penguin Cyclops {BEHAVIOR_FLEE | AWARENESS_LOW | SPEED_FAST | DANGER_WEAK, MAKE_BYTE (1, 1)}, // Chicken {BEHAVIOR_UNPREDICTABLE | SPEED_SLOW | DANGER_WEAK, MAKE_BYTE (6, 2)}, // Bubble Vine {BEHAVIOR_FLEE | AWARENESS_HIGH | SPEED_SLOW | DANGER_WEAK, MAKE_BYTE (4, 2)}, // Bug-Eyed Bait {SPEED_MOTIONLESS | DANGER_WEAK, MAKE_BYTE (8, 5)}, // Goo Burger {SPEED_MOTIONLESS | DANGER_MONSTROUS, MAKE_BYTE (1, 1)}, // Evil One {BEHAVIOR_UNPREDICTABLE | SPEED_SLOW | DANGER_HARMLESS, MAKE_BYTE (0, 1)}, // Brainbox Bulldozers {BEHAVIOR_HUNT | AWARENESS_HIGH | SPEED_FAST | DANGER_MONSTROUS, MAKE_BYTE (15, 15)}, // Zex's Beauty }; #define FLASH_WIDTH 9 #define FLASH_HEIGHT 9 extern PRIM_LINKS DisplayLinks; #define DAMAGE_CYCLE 6 #define EXPLOSION_LIFE 10 #define SHIELD_BIT (1 << 7) #define DEATH_EXPLOSION 0 #define SURFACE_X SIS_ORG_X #define SURFACE_Y SIS_ORG_Y #define SURFACE_WIDTH SIS_SCREEN_WIDTH #define SURFACE_HEIGHT (SIS_SCREEN_HEIGHT - MAP_HEIGHT - 5) #define REPAIR_LANDER (1 << 7) #define REPAIR_TRANSITION (1 << 6) #define KILL_CREW (1 << 5) #define ADD_AT_END (1 << 4) #define REPAIR_COUNT (0xf) #define LANDER_SPEED_DENOM 10 static BYTE lander_flags; static COLOR DamageColorCycle (COLOR c, COUNT i) { static const COLOR damage_tab[DAMAGE_CYCLE + 1] = { WHITE_COLOR, BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7E), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7C), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E), }; if (i) c = damage_tab[i]; else if (c == WHITE_COLOR) c = damage_tab[6]; else if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x0A), 0x0E)) c = damage_tab[5]; else if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1C, 0x00), 0x78)) c = damage_tab[4]; else if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x15, 0x00), 0x7A)) c = damage_tab[3]; else if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0E, 0x00), 0x7C)) c = damage_tab[2]; else if (c == BUILD_COLOR (MAKE_RGB15 (0x1F, 0x07, 0x00), 0x7E)) c = damage_tab[1]; else c = damage_tab[0]; return (c); } #define MAGNIFICATION (1 << MAG_SHIFT) static BOOLEAN RepairTopography (ELEMENTPTR ElementPtr) { //BOOLEAN CursorIntersect; SIZE delta; RECT r; STAMP s; s.origin = ElementPtr->current.location; GetFrameRect (ElementPtr->next.image.frame, &r); r.corner.x += ElementPtr->current.location.x; r.corner.y += ElementPtr->current.location.y; delta = (ElementPtr->next.location.x >> MAG_SHIFT) - r.corner.x; if (delta >= 0) r.extent.width += delta; else { r.corner.x += delta; r.extent.width -= delta; } if ((ElementPtr->current.location.x += delta) < 0) ElementPtr->current.location.x += MAP_WIDTH; else if (ElementPtr->current.location.x >= MAP_WIDTH) ElementPtr->current.location.x -= MAP_WIDTH; delta = (ElementPtr->next.location.y >> MAG_SHIFT) - r.corner.y; if (delta >= 0) r.extent.height += delta; else { r.corner.y += delta; r.extent.height -= delta; } ElementPtr->current.location.y += delta; return (FALSE); } static HELEMENT AddGroundDisaster (COUNT which_disaster); void object_animation (PELEMENT ElementPtr) { COUNT frame_index, angle; PPRIMITIVE pPrim; pPrim = &DisplayArray[ElementPtr->PrimIndex]; if (GetPrimType (pPrim) == STAMPFILL_PRIM && !((ElementPtr->state_flags & FINITE_LIFE) && ElementPtr->mass_points == EARTHQUAKE_DISASTER)) { COLOR c; c = DamageColorCycle (GetPrimColor (pPrim), 0); if (c == WHITE_COLOR) { SetPrimType (pPrim, STAMP_PRIM); if (ElementPtr->hit_points == 0) { ZeroVelocityComponents (&ElementPtr->velocity); pPrim->Object.Stamp.frame = SetAbsFrameIndex (pPrim->Object.Stamp.frame, 0); PlaySound (SetAbsSoundIndex (LanderSounds, LIFEFORM_CANNED), NotPositional (), NULL, GAME_SOUND_PRIORITY); } } SetPrimColor (pPrim, c); } frame_index = GetFrameIndex (pPrim->Object.Stamp.frame) + 1; if (LONIBBLE (ElementPtr->turn_wait)) --ElementPtr->turn_wait; else { ElementPtr->turn_wait += HINIBBLE (ElementPtr->turn_wait); pPrim->Object.Stamp.frame = IncFrameIndex (pPrim->Object.Stamp.frame); if (ElementPtr->state_flags & FINITE_LIFE) { if (ElementPtr->mass_points == DEATH_EXPLOSION) { if (++pMenuState->CurState >= EXPLOSION_LIFE) pPrim->Object.Stamp.frame = DecFrameIndex (pPrim->Object.Stamp.frame); } else if (ElementPtr->mass_points == EARTHQUAKE_DISASTER) { SIZE s; if (frame_index >= 13) s = 0; else s = (14 - frame_index) >> 1; SetPrimColor (pPrim, BUILD_COLOR (0x8000 | MAKE_RGB15 (0x1F, 0x1F, 0x1F), s)); if (frame_index == 13) PlaySound (SetAbsSoundIndex (LanderSounds, EARTHQUAKE_DISASTER), NotPositional (), NULL, GAME_SOUND_PRIORITY); } if (ElementPtr->mass_points == LAVASPOT_DISASTER && frame_index == 5 && (BYTE)TFB_Random () < 256 * 90 / 100) { HELEMENT hLavaElement; hLavaElement = AddGroundDisaster (LAVASPOT_DISASTER); if (hLavaElement) { ELEMENTPTR LavaElementPtr; angle = FACING_TO_ANGLE (ElementPtr->hit_points); LockElement (hLavaElement, &LavaElementPtr); LavaElementPtr->next.location = ElementPtr->next.location; LavaElementPtr->next.location.x += COSINE (angle, 4); LavaElementPtr->next.location.y += SINE (angle, 4); if (LavaElementPtr->next.location.y < 0) LavaElementPtr->next.location.y = 0; else if (LavaElementPtr->next.location.y >= (MAP_HEIGHT << MAG_SHIFT)) LavaElementPtr->next.location.y = (MAP_HEIGHT << MAG_SHIFT) - 1; if (LavaElementPtr->next.location.x < 0) LavaElementPtr->next.location.x += MAP_WIDTH << MAG_SHIFT; else LavaElementPtr->next.location.x %= MAP_WIDTH << MAG_SHIFT; LavaElementPtr->hit_points = NORMALIZE_FACING ( ElementPtr->hit_points + ((COUNT)TFB_Random () % 3) - 1 ); UnlockElement (hLavaElement); } } } else if (!(frame_index & 3) && ElementPtr->hit_points) { BYTE index; COUNT speed; index = ElementPtr->mass_points & ~CREATURE_AWARE; speed = CreatureData[index].Attributes & SPEED_MASK; if (speed) { SIZE dx, dy; COUNT old_angle; dx = pSolarSysState->MenuState.first_item.x - ElementPtr->next.location.x; if (dx < 0 && dx < -(MAP_WIDTH << (MAG_SHIFT - 1))) dx += MAP_WIDTH << MAG_SHIFT; else if (dx > (MAP_WIDTH << (MAG_SHIFT - 1))) dx -= MAP_WIDTH << MAG_SHIFT; dy = pSolarSysState->MenuState.first_item.y - ElementPtr->next.location.y; angle = ARCTAN (dx, dy); if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; if (dx >= SURFACE_WIDTH || dy >= SURFACE_WIDTH || dx * dx + dy * dy >= SURFACE_WIDTH * SURFACE_WIDTH) ElementPtr->mass_points &= ~CREATURE_AWARE; else if (!(ElementPtr->mass_points & CREATURE_AWARE)) { BYTE DetectPercent; DetectPercent = (((BYTE)(CreatureData[index].Attributes & AWARENESS_MASK) >> AWARENESS_SHIFT) + 1) * (30 / 6); // XXX: Shouldn't this be dependant on // PLANET_SIDE_RATE somehow? And why is it // written as '30 / 6' instead of 5? Does the 30 // specify the (PC) framerate? That doesn't make // sense; I would expect it to be in the // denominator. And even then, it wouldn't give // the same results with different frame rates, // as repeating 'random(x / 30)' 30 times doesn't // generally have the same result as repeating // 'random(x / 35)' 25 times. - SvdB if (((BYTE)TFB_Random () % 100) < DetectPercent) { ElementPtr->thrust_wait = 0; ElementPtr->mass_points |= CREATURE_AWARE; } } if (ElementPtr->next.location.y == 0 || ElementPtr->next.location.y == (MAP_HEIGHT << MAG_SHIFT) - 1) ElementPtr->thrust_wait = 0; old_angle = GetVelocityTravelAngle (&ElementPtr->velocity); if (ElementPtr->thrust_wait) { --ElementPtr->thrust_wait; angle = old_angle; } else if (!(ElementPtr->mass_points & CREATURE_AWARE) || (CreatureData[index].Attributes & BEHAVIOR_MASK) == BEHAVIOR_UNPREDICTABLE) { COUNT rand_val; rand_val = (COUNT)TFB_Random (); angle = NORMALIZE_ANGLE (LOBYTE (rand_val)); ElementPtr->thrust_wait = (HIBYTE (rand_val) >> 2) + 10; } else if ((CreatureData[index].Attributes & BEHAVIOR_MASK) == BEHAVIOR_FLEE) { if (ElementPtr->next.location.y == 0 || ElementPtr->next.location.y == (MAP_HEIGHT << MAG_SHIFT) - 1) { if (angle & (HALF_CIRCLE - 1)) angle = HALF_CIRCLE - angle; else if (old_angle == QUADRANT || old_angle == (FULL_CIRCLE - QUADRANT)) angle = old_angle; else angle = (((COUNT)TFB_Random () & 1) * HALF_CIRCLE) - QUADRANT; ElementPtr->thrust_wait = 5; } angle = NORMALIZE_ANGLE (angle + HALF_CIRCLE); } switch (speed) { case SPEED_SLOW: speed = WORLD_TO_VELOCITY (2 * 1) >> 2; break; case SPEED_MEDIUM: speed = WORLD_TO_VELOCITY (2 * 1) >> 1; break; case SPEED_FAST: speed = WORLD_TO_VELOCITY (2 * 1) * 9 / 10; break; } SetVelocityComponents (&ElementPtr->velocity, COSINE (angle, speed), SINE (angle, speed)); } } } if ((ElementPtr->state_flags & FINITE_LIFE) && ElementPtr->mass_points == DEATH_EXPLOSION && GetSuccLink (DisplayLinks) != ElementPtr->PrimIndex) lander_flags |= ADD_AT_END; } #define NUM_CREW_COLS 6 #define NUM_CREW_ROWS 2 static void DeltaLanderCrew (SIZE crew_delta, COUNT which_disaster) { STAMP s; CONTEXT OldContext; if (crew_delta > 0) { crew_delta = HIBYTE (pMenuState->delta_item); pMenuState->delta_item += MAKE_WORD (0, 1); s.frame = SetAbsFrameIndex (LanderFrame[0], 55); } else /* if (crew_delta < 0) */ { BYTE ShieldFlags; ShieldFlags = GET_GAME_STATE (LANDER_SHIELDS); ShieldFlags &= 1 << which_disaster; crew_delta = HIBYTE (pMenuState->delta_item); if (crew_delta < 1) return; if (ShieldFlags && (BYTE)TFB_Random () < 256 * 95 / 100) pMenuState->delta_item = SHIELD_BIT; else { ShieldFlags = 0; if (--crew_delta == 0) pMenuState->CurState = 0; pMenuState->delta_item = 0; } pMenuState->delta_item |= MAKE_WORD (DAMAGE_CYCLE, crew_delta); if (ShieldFlags) return; s.frame = SetAbsFrameIndex (LanderFrame[0], 56); PlaySound (SetAbsSoundIndex (LanderSounds, LANDER_INJURED), NotPositional (), NULL, GAME_SOUND_PRIORITY); } s.origin.x = 11 + (6 * (crew_delta % NUM_CREW_COLS)); s.origin.y = 35 - (6 * (crew_delta / NUM_CREW_COLS)); OldContext = SetContext (RadarContext); DrawStamp (&s); SetContext (OldContext); } static void FillLanderHold (PPLANETSIDE_DESC pPSD, COUNT scan, COUNT NumRetrieved) { COUNT start_count; STAMP s; CONTEXT OldContext; PlaySound (SetAbsSoundIndex (LanderSounds, LANDER_PICKUP), NotPositional (), NULL, GAME_SOUND_PRIORITY); if (scan == BIOLOGICAL_SCAN) { start_count = pPSD->BiologicalLevel; s.frame = SetAbsFrameIndex (LanderFrame[0], 41); pPSD->BiologicalLevel += NumRetrieved; } else { start_count = pPSD->ElementLevel; pPSD->ElementLevel += NumRetrieved; if (GET_GAME_STATE (IMPROVED_LANDER_CARGO)) { start_count >>= 1; NumRetrieved = (pPSD->ElementLevel >> 1) - start_count; } s.frame = SetAbsFrameIndex (LanderFrame[0], 43); } s.origin.x = 0; s.origin.y = -(int)start_count; if (!(start_count & 1)) s.frame = IncFrameIndex (s.frame); OldContext = SetContext (RadarContext); while (NumRetrieved--) { if (start_count++ & 1) s.frame = IncFrameIndex (s.frame); else s.frame = DecFrameIndex (s.frame); DrawStamp (&s); --s.origin.y; } SetContext (OldContext); } static void CheckObjectCollision (COUNT index) { INTERSECT_CONTROL LanderControl; MEM_HANDLE LanderHandle; PPRIMITIVE pPrim, pLanderPrim; PPLANETSIDE_DESC pPSD; if (index != END_OF_LIST) { pLanderPrim = &DisplayArray[index]; LanderControl.IntersectStamp = pLanderPrim->Object.Stamp; index = GetPredLink (GetPrimLinks (pLanderPrim)); } else { pLanderPrim = 0; LanderControl.IntersectStamp.origin.x = SURFACE_WIDTH >> 1; LanderControl.IntersectStamp.origin.y = SURFACE_HEIGHT >> 1; LanderControl.IntersectStamp.frame = LanderFrame[0]; index = GetSuccLink (DisplayLinks); } pPSD = (PPLANETSIDE_DESC)pMenuState->ModuleFrame; LanderControl.EndPoint = LanderControl.IntersectStamp.origin; LanderHandle = GetFrameHandle (LanderControl.IntersectStamp.frame); for (; index != END_OF_LIST; index = GetPredLink (GetPrimLinks (pPrim))) { INTERSECT_CONTROL ElementControl; HELEMENT hElement, hNextElement; pPrim = &DisplayArray[index]; ElementControl.IntersectStamp = pPrim->Object.Stamp; ElementControl.EndPoint = ElementControl.IntersectStamp.origin; if (GetFrameHandle (ElementControl.IntersectStamp.frame) == LanderHandle) { CheckObjectCollision (index); continue; } if (!DrawablesIntersect (&LanderControl, &ElementControl, MAX_TIME_VALUE)) continue; for (hElement = GetHeadElement (); hElement; hElement = hNextElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); hNextElement = GetSuccElement (ElementPtr); if (&DisplayArray[ElementPtr->PrimIndex] == pLanderPrim) { ElementPtr->state_flags |= DISAPPEARING; UnlockElement (hElement); continue; } if (&DisplayArray[ElementPtr->PrimIndex] != pPrim || !(ElementPtr->state_flags & BAD_GUY)) { UnlockElement (hElement); continue; } { COUNT scan, NumRetrieved; SIZE which_node; scan = LOBYTE (ElementPtr->life_span); if (pLanderPrim == 0) { if (HIBYTE (pMenuState->delta_item) == 0 || pPSD->InTransit) break; if (ElementPtr->state_flags & FINITE_LIFE) { /* A natural disaster */ scan = ElementPtr->mass_points; switch (scan) { case EARTHQUAKE_DISASTER: case LAVASPOT_DISASTER: if ((BYTE)TFB_Random () < (256 >> 2)) DeltaLanderCrew (-1, scan); break; } UnlockElement (hElement); continue; } else if (scan == ENERGY_SCAN) { if (ElementPtr->mass_points == 1) { DWORD TimeIn; /* Ran into Spathi on Pluto */ TimeIn = GetTimeCounter (); which_node = 8; do { DeltaLanderCrew (-1, LANDER_INJURED); SleepThreadUntil (TimeIn + ONE_SECOND / 20); TimeIn = GetTimeCounter(); } while (HIBYTE (pMenuState->delta_item) && --which_node); } if (HIBYTE (pMenuState->delta_item) && pSolarSysState->SysInfo.PlanetInfo.DiscoveryString && CurStarDescPtr->Index != ANDROSYNTH_DEFINED) { UnbatchGraphics (); DoDiscoveryReport (MenuSounds); BatchGraphics (); } if (ElementPtr->mass_points == 0) { DestroyStringTable (ReleaseStringTable ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString )); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = 0; UnlockElement (hElement); continue; } } else if (scan == BIOLOGICAL_SCAN && ElementPtr->hit_points) { BYTE danger_vals[] = { 0, 6, 13, 26 }; int creatureIndex = ElementPtr->mass_points & ~CREATURE_AWARE; int dangerLevel = (CreatureData[creatureIndex].Attributes & DANGER_MASK) >> DANGER_SHIFT; if (((COUNT)TFB_Random () & 127) < danger_vals[dangerLevel]) { PlaySound (SetAbsSoundIndex ( LanderSounds, BIOLOGICAL_DISASTER ), NotPositional (), NULL, GAME_SOUND_PRIORITY); DeltaLanderCrew (-1, BIOLOGICAL_DISASTER); } UnlockElement (hElement); continue; } NumRetrieved = ElementPtr->mass_points; } /* if a natural disaster */ else if (ElementPtr->state_flags & FINITE_LIFE) { UnlockElement (hElement); continue; } else { BYTE value; if (scan == ENERGY_SCAN) { UnlockElement (hElement); break; } else if (scan == BIOLOGICAL_SCAN && (value = LONIBBLE (CreatureData[ ElementPtr->mass_points & ~CREATURE_AWARE ].ValueAndHitPoints))) { if (ElementPtr->hit_points) { if (--ElementPtr->hit_points == 0) { ElementPtr->mass_points = value; DisplayArray[ ElementPtr->PrimIndex ].Object.Stamp.frame = pSolarSysState->PlanetSideFrame[0]; } else if (CreatureData[ ElementPtr->mass_points & ~CREATURE_AWARE ].Attributes & SPEED_MASK) { COUNT angle; angle = FACING_TO_ANGLE (GetFrameIndex ( LanderControl.IntersectStamp.frame ) - ANGLE_TO_FACING (FULL_CIRCLE)); DeltaVelocityComponents ( &ElementPtr->velocity, COSINE (angle, WORLD_TO_VELOCITY (1)), SINE (angle, WORLD_TO_VELOCITY (1)) ); ElementPtr->thrust_wait = 0; ElementPtr->mass_points |= CREATURE_AWARE; } SetPrimType (pPrim, STAMPFILL_PRIM); SetPrimColor (pPrim, WHITE_COLOR); PlaySound (SetAbsSoundIndex ( LanderSounds, LANDER_HITS), NotPositional (), NULL, GAME_SOUND_PRIORITY); } UnlockElement (hElement); break; } NumRetrieved = 0; } if (NumRetrieved) { switch (scan) { case ENERGY_SCAN: break; case MINERAL_SCAN: if (pPSD->ElementLevel < pPSD->MaxElementLevel) { if (pPSD->ElementLevel + NumRetrieved > pPSD->MaxElementLevel) NumRetrieved = (COUNT)(pPSD->MaxElementLevel - pPSD->ElementLevel); FillLanderHold (pPSD, scan, NumRetrieved); if (scan == MINERAL_SCAN) { BYTE EType; UNICODE ch, *pStr; EType = ElementPtr->turn_wait; pPSD->ElementAmounts[ ElementCategory (EType) ] += NumRetrieved; pPSD->NumFrames = NUM_TEXT_FRAMES; sprintf (pPSD->AmountBuf, "%u", NumRetrieved); pStr = GAME_STRING (EType + ELEMENTS_STRING_BASE); pPSD->MineralText[0].baseline.x = (SURFACE_WIDTH >> 1) + (ElementControl.EndPoint.x - LanderControl.EndPoint.x); pPSD->MineralText[0].baseline.y = (SURFACE_HEIGHT >> 1) + (ElementControl.EndPoint.y - LanderControl.EndPoint.y); pPSD->MineralText[0].CharCount = (COUNT)~0; pPSD->MineralText[1].pStr = pStr; while ((ch = *pStr++) && ch != ' ') ; if (ch == '\0') { pPSD->MineralText[1].CharCount = (COUNT)~0; pPSD->MineralText[2].CharCount = 0; } else /* ch == ' ' */ { // Name contains a space. Print over // two lines. pPSD->MineralText[1].CharCount = utf8StringCountN( pPSD->MineralText[1].pStr, pStr - 1); pPSD->MineralText[2].pStr = pStr; pPSD->MineralText[2].CharCount = (COUNT)~0; } } break; } PlaySound (SetAbsSoundIndex ( LanderSounds, LANDER_FULL), NotPositional (), NULL, GAME_SOUND_PRIORITY); continue; case BIOLOGICAL_SCAN: if (pPSD->BiologicalLevel < MAX_SCROUNGED) { if (pPSD->BiologicalLevel + NumRetrieved > MAX_SCROUNGED) NumRetrieved = (COUNT)( MAX_SCROUNGED - pPSD->BiologicalLevel ); FillLanderHold (pPSD, scan, NumRetrieved); break; } PlaySound (SetAbsSoundIndex ( LanderSounds, LANDER_FULL ), NotPositional (), NULL, GAME_SOUND_PRIORITY); continue; } } which_node = HIBYTE (ElementPtr->life_span) - 1; pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[scan] |= (1L << which_node); pSolarSysState->CurNode = (COUNT)~0; (*pSolarSysState->GenFunc) ((BYTE)(scan + GENERATE_MINERAL)); if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[scan] & (1L << which_node))) { if (DestroyStringTable (ReleaseStringTable ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString ))) pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = 0; } else { if (NumRetrieved && scan == ENERGY_SCAN) pPSD->InTransit = TRUE; SET_GAME_STATE (PLANETARY_CHANGE, 1); ElementPtr->state_flags |= DISAPPEARING; } UnlockElement (hElement); } } } } static void lightning_process (PELEMENT ElementPtr) { PPRIMITIVE pPrim; pPrim = &DisplayArray[ElementPtr->PrimIndex]; if (LONIBBLE (ElementPtr->turn_wait)) --ElementPtr->turn_wait; else { COUNT num_frames; num_frames = GetFrameCount (pPrim->Object.Stamp.frame) - 7; if (GetFrameIndex (pPrim->Object.Stamp.frame) >= num_frames) pPrim->Object.Stamp.frame = IncFrameIndex (pPrim->Object.Stamp.frame); else { SIZE s; s = 7 - ((SIZE)ElementPtr->crew_level - (SIZE)ElementPtr->life_span); if (s < 0) s = 0; SetPrimColor (pPrim, BUILD_COLOR (0x8000 | MAKE_RGB15 (0x1F, 0x1F, 0x1F), s)); if (ElementPtr->mass_points == LIGHTNING_DISASTER) { if (HIBYTE (pMenuState->delta_item) && (BYTE)TFB_Random () < (256 / 10) && !( (PPLANETSIDE_DESC)pMenuState->ModuleFrame )->InTransit) lander_flags |= KILL_CREW; ElementPtr->next.location = pSolarSysState->MenuState.first_item; } pPrim->Object.Stamp.frame = SetAbsFrameIndex (pPrim->Object.Stamp.frame, (COUNT)TFB_Random () % num_frames); } ElementPtr->turn_wait += HINIBBLE (ElementPtr->turn_wait); } if (GetSuccLink (DisplayLinks) != ElementPtr->PrimIndex) lander_flags |= ADD_AT_END; } static void AddLightning (void) { HELEMENT hLightningElement; hLightningElement = AllocElement (); if (hLightningElement) { DWORD rand_val; ELEMENTPTR LightningElementPtr; LockElement (hLightningElement, &LightningElementPtr); LightningElementPtr->state_flags = FINITE_LIFE | BAD_GUY; LightningElementPtr->preprocess_func = lightning_process; if ((BYTE)TFB_Random () >= (256 >> 2)) LightningElementPtr->mass_points = 0; else LightningElementPtr->mass_points = LIGHTNING_DISASTER; rand_val = TFB_Random (); LightningElementPtr->life_span = 10 + (HIWORD (rand_val) % 10) + 1; LightningElementPtr->next.location.x = ( pSolarSysState->MenuState.first_item.x + ((MAP_WIDTH << MAG_SHIFT) - ((SURFACE_WIDTH >> 1) - 6)) + (LOBYTE (rand_val) % (SURFACE_WIDTH - 12)) ) % (MAP_WIDTH << MAG_SHIFT); LightningElementPtr->next.location.y = ( pSolarSysState->MenuState.first_item.y + ((MAP_HEIGHT << MAG_SHIFT) - ((SURFACE_HEIGHT >> 1) - 6)) + (HIBYTE (rand_val) % (SURFACE_HEIGHT - 12)) ) % (MAP_HEIGHT << MAG_SHIFT); LightningElementPtr->crew_level = LightningElementPtr->life_span; SetPrimType (&DisplayArray[LightningElementPtr->PrimIndex], STAMPFILL_PRIM); SetPrimColor (&DisplayArray[LightningElementPtr->PrimIndex], WHITE_COLOR); DisplayArray[LightningElementPtr->PrimIndex].Object.Stamp.frame = LanderFrame[2]; UnlockElement (hLightningElement); PutElement (hLightningElement); PlaySound (SetAbsSoundIndex (LanderSounds, LIGHTNING_DISASTER), NotPositional (), NULL, GAME_SOUND_PRIORITY); } } static HELEMENT AddGroundDisaster (COUNT which_disaster) { HELEMENT hGroundDisasterElement; hGroundDisasterElement = AllocElement (); if (hGroundDisasterElement) { DWORD rand_val; ELEMENTPTR GroundDisasterElementPtr; PPRIMITIVE pPrim; LockElement (hGroundDisasterElement, &GroundDisasterElementPtr); pPrim = &DisplayArray[GroundDisasterElementPtr->PrimIndex]; GroundDisasterElementPtr->mass_points = which_disaster; GroundDisasterElementPtr->state_flags = FINITE_LIFE | BAD_GUY; GroundDisasterElementPtr->preprocess_func = object_animation; rand_val = TFB_Random (); GroundDisasterElementPtr->next.location.x = ( pSolarSysState->MenuState.first_item.x + ((MAP_WIDTH << MAG_SHIFT) - (SURFACE_WIDTH * 3 / 8)) + (LOWORD (rand_val) % (SURFACE_WIDTH * 3 / 4)) ) % (MAP_WIDTH << MAG_SHIFT); GroundDisasterElementPtr->next.location.y = ( pSolarSysState->MenuState.first_item.y + ((MAP_HEIGHT << MAG_SHIFT) - (SURFACE_HEIGHT * 3 / 8)) + (HIWORD (rand_val) % (SURFACE_HEIGHT * 3 / 4)) ) % (MAP_HEIGHT << MAG_SHIFT); if (which_disaster == EARTHQUAKE_DISASTER) { SetPrimType (pPrim, STAMPFILL_PRIM); pPrim->Object.Stamp.frame = LanderFrame[1]; GroundDisasterElementPtr->turn_wait = MAKE_BYTE (2, 2); } else { SetPrimType (pPrim, STAMP_PRIM); GroundDisasterElementPtr->hit_points = NORMALIZE_FACING (TFB_Random ()); pPrim->Object.Stamp.frame = LanderFrame[3]; GroundDisasterElementPtr->turn_wait = MAKE_BYTE (0, 0); } GroundDisasterElementPtr->life_span = GetFrameCount (pPrim->Object.Stamp.frame) * (LONIBBLE (GroundDisasterElementPtr->turn_wait) + 1) - 1; UnlockElement (hGroundDisasterElement); PutElement (hGroundDisasterElement); } return (hGroundDisasterElement); } static void BuildObjectList (void) { DWORD rand_val; POINT org; HELEMENT hElement, hNextElement; PPLANETSIDE_DESC pPSD; DisplayLinks = MakeLinks (END_OF_LIST, END_OF_LIST); lander_flags &= ~KILL_CREW; pPSD = (PPLANETSIDE_DESC)pMenuState->ModuleFrame; rand_val = TFB_Random (); if (LOBYTE (HIWORD (rand_val)) < pPSD->FireChance) { AddGroundDisaster (LAVASPOT_DISASTER); PlaySound (SetAbsSoundIndex (LanderSounds, LAVASPOT_DISASTER), NotPositional (), NULL, GAME_SOUND_PRIORITY); } if (HIBYTE (LOWORD (rand_val)) < pPSD->TectonicsChance) AddGroundDisaster (EARTHQUAKE_DISASTER); if (LOBYTE (LOWORD (rand_val)) < pPSD->WeatherChance) AddLightning (); org = pSolarSysState->MenuState.first_item; for (hElement = GetHeadElement (); hElement; hElement = hNextElement) { SIZE dx, dy; ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); if (ElementPtr->life_span == 0 || (ElementPtr->state_flags & DISAPPEARING)) { hNextElement = GetSuccElement (ElementPtr); UnlockElement (hElement); if (ElementPtr->state_flags & APPEARING) { ElementPtr->current.location.x |= 0x8000; ElementPtr->current.location.y |= 0x8000; } else { RemoveElement (hElement); FreeElement (hElement); } continue; } else if (ElementPtr->state_flags & FINITE_LIFE) --ElementPtr->life_span; lander_flags &= ~ADD_AT_END; if (ElementPtr->preprocess_func) (*ElementPtr->preprocess_func) (ElementPtr); GetNextVelocityComponents ( &ElementPtr->velocity, &dx, &dy, 1 ); if (dx || dy) { ElementPtr->next.location.x += dx; ElementPtr->next.location.y += dy; /* if not lander's shot */ if (ElementPtr->state_flags != (FINITE_LIFE | GOOD_GUY)) { if (ElementPtr->next.location.y < 0) ElementPtr->next.location.y = 0; else if (ElementPtr->next.location.y >= (MAP_HEIGHT << MAG_SHIFT)) ElementPtr->next.location.y = (MAP_HEIGHT << MAG_SHIFT) - 1; } if (ElementPtr->state_flags & APPEARING) ElementPtr->current.location.x |= 0x8000; if (ElementPtr->next.location.x < 0) ElementPtr->next.location.x += MAP_WIDTH << MAG_SHIFT; else ElementPtr->next.location.x %= MAP_WIDTH << MAG_SHIFT; } { PPRIMITIVE pPrim; pPrim = &DisplayArray[ElementPtr->PrimIndex]; pPrim->Object.Stamp.origin.x = ElementPtr->next.location.x - org.x + (SURFACE_WIDTH >> 1); if (pPrim->Object.Stamp.origin.x >= (MAP_WIDTH << MAG_SHIFT) - (SURFACE_WIDTH * 3 / 2)) pPrim->Object.Stamp.origin.x -= MAP_WIDTH << MAG_SHIFT; else if (pPrim->Object.Stamp.origin.x <= -((MAP_WIDTH << MAG_SHIFT) - (SURFACE_WIDTH * 3 / 2))) pPrim->Object.Stamp.origin.x += MAP_WIDTH << MAG_SHIFT; pPrim->Object.Stamp.origin.y = ElementPtr->next.location.y - org.y + (SURFACE_HEIGHT >> 1); if (lander_flags & ADD_AT_END) InsertPrim (&DisplayLinks, ElementPtr->PrimIndex, END_OF_LIST); else InsertPrim (&DisplayLinks, ElementPtr->PrimIndex, GetPredLink (DisplayLinks)); } hNextElement = GetSuccElement (ElementPtr); UnlockElement (hElement); } } static void RepairScan (void) { CONTEXT OldContext; HELEMENT hElement, hNextElement; OldContext = SetContext (ScanContext); for (hElement = GetHeadElement (); hElement; hElement = hNextElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); hNextElement = GetSuccElement (ElementPtr); if (ElementPtr->current.location.x & 0x8000) { BOOLEAN remove; ElementPtr->current.location.x &= ~0x8000; if (ElementPtr->current.location.y & 0x8000) { remove = TRUE; ElementPtr->current.location.y &= ~0x8000; } else remove = FALSE; RepairTopography (ElementPtr); if (remove) { UnlockElement (hElement); RemoveElement (hElement); FreeElement (hElement); continue; } } UnlockElement (hElement); } BatchGraphics (); #if 1 DrawPlanet (0, 0, 0, 0); #endif DrawScannedObjects (TRUE); { #define FLASH_INDEX 105 STAMP s; s.origin = pMenuState->flash_rect0.corner; s.frame = SetAbsFrameIndex (MiscDataFrame, FLASH_INDEX); DrawStamp (&s); } UnbatchGraphics (); SetContext (OldContext); } static void ScrollPlanetSide (SIZE dx, SIZE dy, SIZE CountDown) { POINT old_pt, new_pt; STAMP lander_s, shadow_s, shield_s; CONTEXT OldContext; signed char lander_pos[] = { -10, 1, 12, 22, 31, 39, 45, 50, 54, 57, 59 }; old_pt.x = pSolarSysState->MenuState.first_item.x - (SURFACE_WIDTH >> 1); old_pt.y = pSolarSysState->MenuState.first_item.y - (SURFACE_HEIGHT >> 1); new_pt.y = old_pt.y + dy; if (new_pt.y < -(SURFACE_HEIGHT >> 1)) { new_pt.y = -(SURFACE_HEIGHT >> 1); dy = new_pt.y - old_pt.y; dx = 0; ZeroVelocityComponents (&GLOBAL (velocity)); } else if (new_pt.y > (MAP_HEIGHT << MAG_SHIFT) - (SURFACE_HEIGHT >> 1)) { new_pt.y = (MAP_HEIGHT << MAG_SHIFT) - (SURFACE_HEIGHT >> 1); dy = new_pt.y - old_pt.y; dx = 0; ZeroVelocityComponents (&GLOBAL (velocity)); } new_pt.x = old_pt.x + dx; if (new_pt.x < 0) new_pt.x += MAP_WIDTH << MAG_SHIFT; else if (new_pt.x >= MAP_WIDTH << MAG_SHIFT) new_pt.x -= MAP_WIDTH << MAG_SHIFT; new_pt.x = pSolarSysState->MenuState.first_item.x + dx; if (new_pt.x < 0) new_pt.x += MAP_WIDTH << MAG_SHIFT; else if (new_pt.x >= MAP_WIDTH << MAG_SHIFT) new_pt.x -= MAP_WIDTH << MAG_SHIFT; new_pt.y = pSolarSysState->MenuState.first_item.y + dy; pSolarSysState->MenuState.first_item = new_pt; { DWORD TimeIn; SleepThreadUntil (MAKE_DWORD ( pSolarSysState->MenuState.flash_rect1.corner.x, pSolarSysState->MenuState.flash_rect1.corner.y )); // planet-side rate is set here TimeIn = GetTimeCounter () + PLANET_SIDE_RATE; pSolarSysState->MenuState.flash_rect1.corner.x = LOWORD (TimeIn); pSolarSysState->MenuState.flash_rect1.corner.y = HIWORD (TimeIn); } LockMutex (GraphicsLock); OldContext = SetContext (SpaceContext); BatchGraphics (); // Display planet area, accounting for horizontal wrapping if // near the edges. { STAMP s; ClearDrawable (); s.origin.x = -new_pt.x + (SURFACE_WIDTH >> 1); s.origin.y = -new_pt.y + (SURFACE_HEIGHT >> 1); s.frame = pSolarSysState->Orbit.TopoZoomFrame; DrawStamp (&s); s.origin.x += MAP_WIDTH << MAG_SHIFT; DrawStamp (&s); s.origin.x -= MAP_WIDTH << (MAG_SHIFT + 1); DrawStamp (&s); } BuildObjectList (); DrawBatch (DisplayArray, DisplayLinks, 0); if (pMenuState->delta_item || pMenuState->CurState < 3) { BYTE damage_index; lander_s.origin.x = SURFACE_WIDTH >> 1; lander_s.frame = LanderFrame[0]; if (CountDown < 0) lander_s.origin.y = SURFACE_HEIGHT >> 1; else lander_s.origin.y = lander_pos[CountDown]; if (CountDown >= 0) { shadow_s.origin.x = lander_s.origin.y + (SURFACE_WIDTH >> 1) - (SURFACE_HEIGHT >> 1);//2; shadow_s.origin.y = lander_s.origin.y; shadow_s.frame = lander_s.frame; SetContextForeGroundColor (BLACK_COLOR); DrawFilledStamp (&shadow_s); } if ((damage_index = LOBYTE (pMenuState->delta_item)) == 0) DrawStamp (&lander_s); else { --pMenuState->delta_item; if (!(damage_index & SHIELD_BIT)) { SetContextForeGroundColor (DamageColorCycle (0, damage_index)); DrawFilledStamp (&lander_s); } else { if ((damage_index = (BYTE)((damage_index & ~SHIELD_BIT) - 1)) == 0) pMenuState->delta_item &= ~SHIELD_BIT; else { shield_s.origin = lander_s.origin; shield_s.frame = SetEquFrameIndex ( LanderFrame[4], lander_s.frame ); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F) | 0x8000, damage_index) ); DrawFilledStamp (&shield_s); } DrawStamp (&lander_s); } } } if (CountDown < 0 && HIBYTE (pMenuState->delta_item) && GetPredLink (DisplayLinks) != END_OF_LIST) CheckObjectCollision (END_OF_LIST); { PPLANETSIDE_DESC pPSD; pPSD = (PPLANETSIDE_DESC)pMenuState->ModuleFrame; if (pPSD->NumFrames) { --pPSD->NumFrames; SetContextForeGroundColor (pPSD->ColorCycle[pPSD->NumFrames >> 1]); pPSD->MineralText[0].baseline.x -= dx; pPSD->MineralText[0].baseline.y -= dy; font_DrawText (&pPSD->MineralText[0]); pPSD->MineralText[1].baseline.x = pPSD->MineralText[0].baseline.x; pPSD->MineralText[1].baseline.y = pPSD->MineralText[0].baseline.y + 7; font_DrawText (&pPSD->MineralText[1]); pPSD->MineralText[2].baseline.x = pPSD->MineralText[1].baseline.x; pPSD->MineralText[2].baseline.y = pPSD->MineralText[1].baseline.y + 7; font_DrawText (&pPSD->MineralText[2]); } } pMenuState->flash_rect0.corner.x = new_pt.x >> MAG_SHIFT; pMenuState->flash_rect0.corner.y = new_pt.y >> MAG_SHIFT; RepairScan (); if (lander_flags & KILL_CREW) DeltaLanderCrew (-1, LIGHTNING_DISASTER); UnbatchGraphics (); SetContext (OldContext); UnlockMutex (GraphicsLock); } static void AnimateLaunch (FRAME farray, BOOLEAN ShowPlanetSide) { RECT r; STAMP s; COUNT num_frames; DWORD Time; Time = GetTimeCounter (); s.origin.x = s.origin.y = 0; s.frame = DecFrameIndex (farray); num_frames = GetFrameCount (s.frame); do { GetFrameRect (s.frame, &r); s.frame = IncFrameIndex (s.frame); RepairBackRect (&r); DrawStamp (&s); UnlockMutex (GraphicsLock); #if 0 if (ShowPlanetSide) { do { ScrollPlanetSide (0, 0, 0); } while (GetTimeCounter () < Time + (ONE_SECOND / 22)); } #else (void) ShowPlanetSide; /* Satisfying compiler (unused parameter) */ #endif SleepThreadUntil (Time + (ONE_SECOND / 22)); Time = GetTimeCounter (); LockMutex (GraphicsLock); } while (--num_frames); GetFrameRect (s.frame, &r); RepairBackRect (&r); } static void InitPlanetSide (void) { SIZE num_crew; POINT pt; STAMP s; CONTEXT OldContext; DWORD Time; LockMutex (GraphicsLock); OldContext = SetContext (RadarContext); UnlockMutex (GraphicsLock); Time = GetTimeCounter (); s.origin.x = 0; s.origin.y = 0; s.frame = SetAbsFrameIndex (LanderFrame[0], (ANGLE_TO_FACING (FULL_CIRCLE) << 1) + 1); LockMutex (GraphicsLock); DrawStamp (&s); UnlockMutex (GraphicsLock); SleepThread (ONE_SECOND / 15); Time = GetTimeCounter (); for (num_crew = 0; num_crew < (NUM_CREW_COLS * NUM_CREW_ROWS) && GLOBAL_SIS (CrewEnlisted); ++num_crew) { SleepThreadUntil (Time + ONE_SECOND / 30); Time = GetTimeCounter (); LockMutex (GraphicsLock); DeltaSISGauges (-1, 0, 0); DeltaLanderCrew (1, 0); UnlockMutex (GraphicsLock); } SleepThreadUntil (Time + (ONE_SECOND / 15)); Time = GetTimeCounter (); if (GET_GAME_STATE (IMPROVED_LANDER_SHOT)) s.frame = SetAbsFrameIndex (s.frame, 58); else s.frame = SetAbsFrameIndex (s.frame, (ANGLE_TO_FACING (FULL_CIRCLE) << 1) + 2); LockMutex (GraphicsLock); DrawStamp (&s); UnlockMutex (GraphicsLock); SleepThreadUntil (Time + (ONE_SECOND / 15)); Time = GetTimeCounter (); if (GET_GAME_STATE (IMPROVED_LANDER_SPEED)) s.frame = SetAbsFrameIndex (s.frame, 57); else { s.frame = SetAbsFrameIndex (s.frame, (ANGLE_TO_FACING (FULL_CIRCLE) << 1) + 3); LockMutex (GraphicsLock); DrawStamp (&s); UnlockMutex (GraphicsLock); SleepThreadUntil (Time + (ONE_SECOND / 15)); Time = GetTimeCounter (); s.frame = IncFrameIndex (s.frame); } LockMutex (GraphicsLock); DrawStamp (&s); UnlockMutex (GraphicsLock); if (GET_GAME_STATE (IMPROVED_LANDER_CARGO)) { SleepThreadUntil (Time + (ONE_SECOND / 15)); Time = GetTimeCounter (); s.frame = SetAbsFrameIndex (s.frame, 59); LockMutex (GraphicsLock); DrawStamp (&s); UnlockMutex (GraphicsLock); } #ifndef SPIN_ON_LAUNCH pSolarSysState->PauseRotate = 1; #endif SleepThreadUntil (Time + (ONE_SECOND / 15)); LockMutex (GraphicsLock); PlaySound (SetAbsSoundIndex (LanderSounds, LANDER_DEPARTS), NotPositional (), NULL, GAME_SOUND_PRIORITY + 1); SetContext (SpaceContext); AnimateLaunch (LanderFrame[5], FALSE); #ifdef SPIN_ON_LAUNCH pSolarSysState->PauseRotate = 1; UnlockMutex (GraphicsLock); TaskSwitch (); LockMutex (GraphicsLock); #endif // Adjust pSolarSysState->MenuState.first_item by a random jitter. #define RANDOM_MISS 64 pt = pSolarSysState->MenuState.first_item; // Jitter the X landing point. pt.x -= RANDOM_MISS - (SIZE)(LOWORD (TFB_Random ()) % (RANDOM_MISS << 1)); if (pt.x < 0) pt.x += (MAP_WIDTH << MAG_SHIFT); else if (pt.x >= (MAP_WIDTH << MAG_SHIFT)) pt.x -= (MAP_WIDTH << MAG_SHIFT); // Jitter the Y landing point. pt.y -= RANDOM_MISS - (SIZE)(LOWORD (TFB_Random ()) % (RANDOM_MISS << 1)); if (pt.y < 0) pt.y = 0; else if (pt.y >= (MAP_HEIGHT << MAG_SHIFT)) pt.y = (MAP_HEIGHT << MAG_SHIFT) - 1; // Put this back in as our original menu choice. pSolarSysState->MenuState.first_item = pt; #ifdef NEVER SetContext (ScanContext); s.origin = pMenuState->flash_rect0.corner; s.origin.x -= (FLASH_WIDTH >> 1); s.origin.y -= (FLASH_HEIGHT >> 1); s.frame = pMenuState->flash_frame0; DrawStamp (&s); #endif /* NEVER */ pMenuState->flash_rect0.corner = pt; SetContext (SpaceContext); SetContextFont (TinyFont); { RECT r; r.corner.x = SURFACE_X; r.corner.y = SURFACE_Y; r.extent.width = SURFACE_WIDTH; r.extent.height = SURFACE_HEIGHT; SetContextClipRect (&r); SetContextClipping (TRUE); SetTransitionSource (&r); BatchGraphics (); { STAMP s; // Note - This code is the same as in ScrollPlanetSize, // Display planet area, accounting for horizontal wrapping if // near the edges. ClearDrawable (); s.origin.x = -pt.x + (SURFACE_WIDTH >> 1); s.origin.y = -pt.y + (SURFACE_HEIGHT >> 1); s.frame = pSolarSysState->Orbit.TopoZoomFrame; DrawStamp (&s); s.origin.x += MAP_WIDTH << MAG_SHIFT; DrawStamp (&s); s.origin.x -= MAP_WIDTH << (MAG_SHIFT + 1); DrawStamp (&s); } ScreenTransition (3, &r); UnbatchGraphics (); LoadIntoExtraScreen (&r); } SetContext (OldContext); UnlockMutex (GraphicsLock); SET_GAME_STATE (PLANETARY_LANDING, 1); } static BOOLEAN DoPlanetSide (PMENU_STATE pMS) { #define NUM_LANDING_DELTAS 10 #define SHUTTLE_TURN_WAIT 2 #define SHUTTLE_FIRE_WAIT 15 SIZE index; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); pMS->MenuRepeatDelay = 0; if (!pMS->Initialized) { pMS->Initialized = TRUE; pMS->CurState = 0; index = FACING_TO_ANGLE (GetFrameIndex (LanderFrame[0])); if (!GET_GAME_STATE (IMPROVED_LANDER_SPEED)) SetVelocityComponents ( &GLOBAL (velocity), COSINE (index, WORLD_TO_VELOCITY (2 * 8)) / LANDER_SPEED_DENOM, SINE (index, WORLD_TO_VELOCITY (2 * 8)) / LANDER_SPEED_DENOM ); else SetVelocityComponents ( &GLOBAL (velocity), COSINE (index, WORLD_TO_VELOCITY (2 * 14)) / LANDER_SPEED_DENOM, SINE (index, WORLD_TO_VELOCITY (2 * 14)) / LANDER_SPEED_DENOM ); #ifdef FAST_FAST SetVelocityComponents ( &GLOBAL (velocity), COSINE (index, WORLD_TO_VELOCITY (48)) / LANDER_SPEED_DENOM, SINE (index, WORLD_TO_VELOCITY (48)) / LANDER_SPEED_DENOM ); #endif } else if (pMS->delta_item == 0 || (HIBYTE (pMS->delta_item) && ((CurrentInputState.key[PlayerOne][KEY_ESCAPE] || CurrentInputState.key[PlayerOne][KEY_SPECIAL]) || ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit))) { if (pMS->delta_item || pMS->CurState > EXPLOSION_LIFE + 60) return (FALSE); else { if (pMS->CurState > EXPLOSION_LIFE) ++pMS->CurState; else if (pMS->CurState == 0) { HELEMENT hExplosionElement; ++pMS->CurState; hExplosionElement = AllocElement (); if (hExplosionElement) { ELEMENTPTR ExplosionElementPtr; LockElement (hExplosionElement, &ExplosionElementPtr); ExplosionElementPtr->mass_points = DEATH_EXPLOSION; ExplosionElementPtr->state_flags = FINITE_LIFE | GOOD_GUY; ExplosionElementPtr->next.location = pSolarSysState->MenuState.first_item; ExplosionElementPtr->preprocess_func = object_animation; ExplosionElementPtr->turn_wait = MAKE_BYTE (2, 2); ExplosionElementPtr->life_span = EXPLOSION_LIFE * (LONIBBLE (ExplosionElementPtr->turn_wait) + 1); SetPrimType (&DisplayArray[ExplosionElementPtr->PrimIndex], STAMP_PRIM); DisplayArray[ExplosionElementPtr->PrimIndex].Object.Stamp.frame = SetAbsFrameIndex ( LanderFrame[0], 46 ); UnlockElement (hExplosionElement); InsertElement (hExplosionElement, GetHeadElement ()); PlaySound (SetAbsSoundIndex ( LanderSounds, LANDER_DESTROYED ), NotPositional (), NULL, GAME_SOUND_PRIORITY + 1); } } ScrollPlanetSide (0, 0, -1); } } else { SIZE dx, dy; if (HIBYTE (pMS->delta_item) == 0) dx = dy = 0; else { index = GetFrameIndex (LanderFrame[0]); if (LONIBBLE (pMS->CurState)) pMS->CurState -= MAKE_BYTE (1, 0); else if (CurrentInputState.key[PlayerOne][KEY_LEFT] || CurrentInputState.key[PlayerOne][KEY_RIGHT]) { if (CurrentInputState.key[PlayerOne][KEY_LEFT]) { dx = -1; --index; } else { dx = +1; ++index; } index = NORMALIZE_FACING (index); LanderFrame[0] = SetAbsFrameIndex (LanderFrame[0], index); dx = FACING_TO_ANGLE (index); if (!GET_GAME_STATE (IMPROVED_LANDER_SPEED)) SetVelocityComponents ( &GLOBAL (velocity), COSINE (dx, WORLD_TO_VELOCITY (2 * 8)) / LANDER_SPEED_DENOM, SINE (dx, WORLD_TO_VELOCITY (2 * 8)) / LANDER_SPEED_DENOM ); else SetVelocityComponents ( &GLOBAL (velocity), COSINE (dx, WORLD_TO_VELOCITY (2 * 14)) / LANDER_SPEED_DENOM, SINE (dx, WORLD_TO_VELOCITY (2 * 14)) / LANDER_SPEED_DENOM ); #ifdef FAST_FAST SetVelocityComponents ( &GLOBAL (velocity), COSINE (dx, WORLD_TO_VELOCITY (48)) / LANDER_SPEED_DENOM, SINE (dx, WORLD_TO_VELOCITY (48)) / LANDER_SPEED_DENOM ); #endif pMS->CurState = MAKE_BYTE ( SHUTTLE_TURN_WAIT, HINIBBLE (pMS->CurState) ); } if (!CurrentInputState.key[PlayerOne][KEY_UP]) dx = dy = 0; else GetNextVelocityComponents ( &GLOBAL (velocity), &dx, &dy, 1 ); if (HINIBBLE (pMS->CurState)) pMS->CurState -= MAKE_BYTE (0, 1); else if (CurrentInputState.key[PlayerOne][KEY_WEAPON]) { HELEMENT hWeaponElement; hWeaponElement = AllocElement (); if (hWeaponElement) { SIZE wdx, wdy; ELEMENTPTR WeaponElementPtr; LockElement (hWeaponElement, &WeaponElementPtr); WeaponElementPtr->mass_points = 1; WeaponElementPtr->life_span = 12; WeaponElementPtr->state_flags = FINITE_LIFE | GOOD_GUY; WeaponElementPtr->next.location = pSolarSysState->MenuState.first_item; WeaponElementPtr->current.location.x = WeaponElementPtr->next.location.x >> MAG_SHIFT; WeaponElementPtr->current.location.y = WeaponElementPtr->next.location.y >> MAG_SHIFT; SetPrimType (&DisplayArray[WeaponElementPtr->PrimIndex], STAMP_PRIM); DisplayArray[WeaponElementPtr->PrimIndex].Object.Stamp.frame = SetAbsFrameIndex ( LanderFrame[0], index + ANGLE_TO_FACING (FULL_CIRCLE) ); if (!CurrentInputState.key[PlayerOne][KEY_UP]) wdx = wdy = 0; else GetCurrentVelocityComponents ( &GLOBAL (velocity), &wdx, &wdy ); index = FACING_TO_ANGLE (index); SetVelocityComponents ( &WeaponElementPtr->velocity, COSINE (index, WORLD_TO_VELOCITY (2 * 3)) + wdx, SINE (index, WORLD_TO_VELOCITY (2 * 3)) + wdy ); UnlockElement (hWeaponElement); InsertElement (hWeaponElement, GetHeadElement ()); PlaySound (SetAbsSoundIndex ( LanderSounds, LANDER_SHOOTS ), NotPositional (), NULL, GAME_SOUND_PRIORITY); wdx = SHUTTLE_FIRE_WAIT; if (GET_GAME_STATE (IMPROVED_LANDER_SHOT)) wdx >>= 1; pMS->CurState = MAKE_BYTE (LONIBBLE (pMS->CurState), wdx); } } } ScrollPlanetSide (dx, dy, -1); } return (TRUE); } void FreeLanderData (void) { if (LanderFrame[0]) { COUNT i; for (i = 0; i < NUM_ORBIT_THEMES; ++i) { DestroyMusic (OrbitMusic[i]); OrbitMusic[i] = 0; } DestroySound (ReleaseSound (LanderSounds)); LanderSounds = 0; for (i = 0; i < sizeof (LanderFrame) / sizeof (LanderFrame[0]); ++i) { DestroyDrawable (ReleaseDrawable (LanderFrame[i])); LanderFrame[i] = 0; } } } void LoadLanderData (void) { if (LanderFrame[0] == 0) { LanderFrame[0] = CaptureDrawable (LoadGraphic (LANDER_MASK_PMAP_ANIM)); LanderFrame[1] = CaptureDrawable (LoadGraphic (QUAKE_MASK_PMAP_ANIM)); LanderFrame[2] = CaptureDrawable (LoadGraphic (LIGHTNING_MASK_ANIM)); LanderFrame[3] = CaptureDrawable (LoadGraphic (LAVA_MASK_PMAP_ANIM)); LanderFrame[4] = CaptureDrawable (LoadGraphic (LANDER_SHIELD_MASK_ANIM)); LanderFrame[5] = CaptureDrawable (LoadGraphic (LANDER_LAUNCH_MASK_PMAP_ANIM)); LanderFrame[6] = CaptureDrawable (LoadGraphic (LANDER_RETURN_MASK_PMAP_ANIM)); LanderSounds = CaptureSound (LoadSound (LANDER_SOUNDS)); LanderFrame[7] = CaptureDrawable (LoadGraphic (ORBIT_VIEW_ANIM)); { COUNT i; RES_TYPE rt; RES_INSTANCE ri; RES_PACKAGE rp; rt = GET_TYPE (ORBIT1_MUSIC); ri = GET_INSTANCE (ORBIT1_MUSIC); rp = GET_PACKAGE (ORBIT1_MUSIC); for (i = 0; i < NUM_ORBIT_THEMES; ++i, ++ri) OrbitMusic[i] = LoadMusic (MAKE_RESOURCE (rp, rt, ri)); } } } void SetPlanetMusic (BYTE planet_type) { LanderMusic = OrbitMusic[planet_type % NUM_ORBIT_THEMES]; } static void ReturnToOrbit (PRECT pRect) { CONTEXT OldContext; LockMutex (GraphicsLock); OldContext = SetContext (SpaceContext); SetContextClipRect (pRect); SetTransitionSource (pRect); BatchGraphics (); DrawStarBackGround (TRUE); SetContext (ScanContext); DrawPlanet (0, 0, 0, 0); DrawScannedObjects (TRUE); ScreenTransition (3, pRect); UnbatchGraphics (); LoadIntoExtraScreen (pRect); SetContext (OldContext); UnlockMutex (GraphicsLock); // SetPlanetTilt (0); } void PlanetSide (PMENU_STATE pMS) { SIZE index; DWORD TimeIn; PLANETSIDE_DESC PSD; BYTE TectonicsChanceTab[] = {0*3, 0*3, 1*3, 2*3, 4*3, 8*3, 16*3, 32*3}; BYTE WeatherChanceTab[] = {0*3, 0*3, 1*3, 2*3, 3*3, 6*3, 12*3, 24*3}; BYTE FireChanceTab[] = {0*3, 0*3, 1*3, 2*3, 4*3, 12*3, 24*3, 48*3}; memset ((PPLANETSIDE_DESC)&PSD, 0, sizeof (PSD)); PSD.InTransit = TRUE; PSD.TectonicsChance = TectonicsChanceTab[pSolarSysState->SysInfo.PlanetInfo.Tectonics]; PSD.WeatherChance = WeatherChanceTab[pSolarSysState->SysInfo.PlanetInfo.Weather]; index = pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature; if (index < 50) PSD.FireChance = FireChanceTab[0]; else if (index < 100) PSD.FireChance = FireChanceTab[1]; else if (index < 150) PSD.FireChance = FireChanceTab[2]; else if (index < 250) PSD.FireChance = FireChanceTab[3]; else if (index < 350) PSD.FireChance = FireChanceTab[4]; else if (index < 550) PSD.FireChance = FireChanceTab[5]; else if (index < 800) PSD.FireChance = FireChanceTab[6]; else PSD.FireChance = FireChanceTab[7]; PSD.ElementLevel = GetSBayCapacity (NULL_PTR) - GLOBAL_SIS (TotalElementMass); PSD.MaxElementLevel = MAX_SCROUNGED; if (GET_GAME_STATE (IMPROVED_LANDER_CARGO)) PSD.MaxElementLevel <<= 1; if (PSD.ElementLevel < PSD.MaxElementLevel) PSD.MaxElementLevel = PSD.ElementLevel; PSD.ElementLevel = 0; PSD.MineralText[0].align = ALIGN_CENTER; PSD.MineralText[0].pStr = PSD.AmountBuf; PSD.MineralText[1] = PSD.MineralText[0]; PSD.MineralText[2] = PSD.MineralText[1]; PSD.ColorCycle[0] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7F); PSD.ColorCycle[1] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7D); PSD.ColorCycle[2] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B); PSD.ColorCycle[3] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x71); for (index = 4; index < (NUM_TEXT_FRAMES >> 1) - 4; ++index) PSD.ColorCycle[index] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F); PSD.ColorCycle[(NUM_TEXT_FRAMES >> 1) - 4] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x00), 0x71); PSD.ColorCycle[(NUM_TEXT_FRAMES >> 1) - 3] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x11, 0x00), 0x7B); PSD.ColorCycle[(NUM_TEXT_FRAMES >> 1) - 2] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x00), 0x7D); PSD.ColorCycle[(NUM_TEXT_FRAMES >> 1) - 1] = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x03, 0x00), 0x7F); pMS->ModuleFrame = (FRAME)&PSD; index = NORMALIZE_FACING ((COUNT)TFB_Random ()); LanderFrame[0] = SetAbsFrameIndex ( LanderFrame[0], index ); pMS->delta_item = 0; pSolarSysState->MenuState.Initialized += 4; InitPlanetSide (); TimeIn = GetTimeCounter (); pSolarSysState->MenuState.flash_rect1.corner.x = LOWORD (TimeIn); pSolarSysState->MenuState.flash_rect1.corner.y = HIWORD (TimeIn); for (index = 0; index <= NUM_LANDING_DELTAS; ++index) { if (index == 0) TimeIn += ONE_SECOND; else TimeIn += ONE_SECOND / 60; do { ScrollPlanetSide (0, 0, index); } while (GetTimeCounter () < TimeIn); } PSD.InTransit = FALSE; TimeIn += ONE_SECOND / 30; pSolarSysState->MenuState.flash_rect1.corner.x = LOWORD (TimeIn); pSolarSysState->MenuState.flash_rect1.corner.y = HIWORD (TimeIn); pMS->Initialized = FALSE; pMS->InputFunc = DoPlanetSide; SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); DoInput ((PVOID)pMS, FALSE); if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) { SIZE crew_left; RECT r; //CONTEXT OldContext; crew_left = HIBYTE (pMS->delta_item); r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT; if (crew_left == 0) { #ifdef NEVER ScrollPlanetSide (0, 0, 0); #endif /* NEVER */ --GLOBAL_SIS (NumLanders); LockMutex (GraphicsLock); DrawLanders (); UnlockMutex (GraphicsLock); ReturnToOrbit (&r); } else { PSD.InTransit = TRUE; PlaySound (SetAbsSoundIndex (LanderSounds, LANDER_RETURNS), NotPositional (), NULL, GAME_SOUND_PRIORITY + 1); TimeIn = GetTimeCounter (); for (index = NUM_LANDING_DELTAS; index >= 0; --index) { if (index == 0) TimeIn += (ONE_SECOND >> 1); else TimeIn += ONE_SECOND / 60; do { ScrollPlanetSide (0, 0, index); } while (GetTimeCounter () < TimeIn); } ReturnToOrbit (&r); #ifdef SPIN_ON_LAUNCH // If PauseRotate is set to 2 the plaet will be displayed, but won't rotate // Until the lander animation is complete pSolarSysState->PauseRotate = 0; // Give The RotatePlanet thread a slice to draw the planet SleepThread (1); #endif LockMutex (GraphicsLock); SetContext (SpaceContext); AnimateLaunch (LanderFrame[6], TRUE); DeltaSISGauges (crew_left, 0, 0); if (PSD.ElementLevel) { for (index = 0; index < NUM_ELEMENT_CATEGORIES; ++index) { GLOBAL_SIS (ElementAmounts[index]) += PSD.ElementAmounts[index]; GLOBAL_SIS (TotalElementMass) += PSD.ElementAmounts[index]; } DrawStorageBays (FALSE); } UnlockMutex (GraphicsLock); GLOBAL_SIS (TotalBioMass) += PSD.BiologicalLevel; } } pMS->ModuleFrame = 0; { HELEMENT hElement, hNextElement; for (hElement = GetHeadElement (); hElement; hElement = hNextElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); hNextElement = _GetSuccLink (ElementPtr); if (ElementPtr->state_flags & FINITE_LIFE) { UnlockElement (hElement); RemoveElement (hElement); FreeElement (hElement); continue; } UnlockElement (hElement); } } ZeroVelocityComponents (&GLOBAL (velocity)); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); pSolarSysState->MenuState.Initialized -= 4; pSolarSysState->PauseRotate = 0; } void InitLander (BYTE LanderFlags) { RECT r; LockMutex (GraphicsLock); SetContext (RadarContext); BatchGraphics (); r.corner.x = 0; r.corner.y = 0; r.extent.width = RADAR_WIDTH; r.extent.height = RADAR_HEIGHT; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); if (GLOBAL_SIS (NumLanders) || LanderFlags) { BYTE ShieldFlags, capacity_shift; COUNT free_space; STAMP s; s.origin.x = 0; /* set up powered-down lander */ s.origin.y = 0; s.frame = SetAbsFrameIndex (LanderFrame[0], ANGLE_TO_FACING (FULL_CIRCLE) << 1); DrawStamp (&s); if (LanderFlags == 0) { ShieldFlags = GET_GAME_STATE (LANDER_SHIELDS); capacity_shift = GET_GAME_STATE (IMPROVED_LANDER_CARGO); } else { ShieldFlags = (unsigned char)(LanderFlags & ((1 << EARTHQUAKE_DISASTER) | (1 << BIOLOGICAL_DISASTER) | (1 << LIGHTNING_DISASTER) | (1 << LAVASPOT_DISASTER))); s.frame = IncFrameIndex (s.frame); DrawStamp (&s); if (LanderFlags & (1 << (4 + 0))) s.frame = SetAbsFrameIndex (s.frame, 57); else { s.frame = SetAbsFrameIndex (s.frame, (ANGLE_TO_FACING (FULL_CIRCLE) << 1) + 3); DrawStamp (&s); s.frame = IncFrameIndex (s.frame); } DrawStamp (&s); if (!(LanderFlags & (1 << (4 + 1)))) capacity_shift = 0; else { capacity_shift = 1; s.frame = SetAbsFrameIndex (s.frame, 59); DrawStamp (&s); } if (LanderFlags & (1 << (4 + 2))) s.frame = SetAbsFrameIndex (s.frame, 58); else s.frame = SetAbsFrameIndex (s.frame, (ANGLE_TO_FACING (FULL_CIRCLE) << 1) + 2); DrawStamp (&s); } if ((int)(free_space = GetSBayCapacity (NULL_PTR) - GLOBAL_SIS (TotalElementMass)) < (int)(MAX_SCROUNGED << capacity_shift)) { r.corner.x = 1; r.extent.width = 4; r.extent.height = MAX_SCROUNGED - (free_space >> capacity_shift) + 1; SetContextForeGroundColor (BLACK_COLOR); DrawFilledRectangle (&r); } s.frame = SetAbsFrameIndex (s.frame, 37); if (ShieldFlags & (1 << EARTHQUAKE_DISASTER)) DrawStamp (&s); s.frame = IncFrameIndex (s.frame); if (ShieldFlags & (1 << BIOLOGICAL_DISASTER)) DrawStamp (&s); s.frame = IncFrameIndex (s.frame); if (ShieldFlags & (1 << LIGHTNING_DISASTER)) DrawStamp (&s); s.frame = IncFrameIndex (s.frame); if (ShieldFlags & (1 << LAVASPOT_DISASTER)) DrawStamp (&s); } UnbatchGraphics (); UnlockMutex (GraphicsLock); } uqm-0.6.2/sc2/src/sc2code/planets/solarsys.c0000600000175000017500000013703510543202100017274 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "colors.h" #include "controls.h" #include "encount.h" #include "gamestr.h" #include "globdata.h" #include "init.h" #include "nameref.h" #include "resinst.h" #include "settings.h" #include "lander.h" #include "load.h" #include "setup.h" #include "sounds.h" #include "state.h" #include "uqmdebug.h" #include "libs/graphics/gfx_common.h" #include "libs/mathlib.h" #include "libs/inplib.h" #include "libs/log.h" //#define DEBUG_SOLARSYS PSOLARSYS_STATE pSolarSysState; FRAME SISIPFrame, SunFrame, OrbitalFrame, SpaceJunkFrame; COLORMAP OrbitalCMap; COLORMAP SunCMap; MUSIC_REF SpaceMusic; SIZE EncounterRace; BYTE EncounterGroup; // last encountered group info #define DRAW_STARS (1 << 0) #define DRAW_PLANETS (1 << 1) #define DRAW_ORBITS (1 << 2) #define DRAW_HYPER_COORDS (1 << 3) #define UNBATCH_SYS (1 << 4) #define DRAW_REFRESH (1 << 5) #define REPAIR_SCAN (1 << 6) #define GRAB_BKGND (1 << 7) static SIZE old_radius; BYTE draw_sys_flags = DRAW_STARS | DRAW_PLANETS | DRAW_ORBITS | DRAW_HYPER_COORDS | GRAB_BKGND; // NB. This function modifies the RNG state. static void GeneratePlanets (PSOLARSYS_STATE system) { COUNT i; PPLANET_DESC planet; for (i = system->SunDesc[0].NumPlanets, planet = &system->PlanetDesc[0]; i; --i, ++planet) { DWORD rand_val; BYTE byte_val; BYTE num_moons; BYTE type; rand_val = TFB_Random (); byte_val = LOBYTE (rand_val); num_moons = 0; type = PlanData[planet->data_index & ~PLANET_SHIELDED].Type; switch (PLANSIZE (type)) { case LARGE_ROCKY_WORLD: if (byte_val < 0x00FF * 25 / 100) { if (byte_val < 0x00FF * 5 / 100) ++num_moons; ++num_moons; } break; case GAS_GIANT: if (byte_val < 0x00FF * 90 / 100) { if (byte_val < 0x00FF * 75 / 100) { if (byte_val < 0x00FF * 50 / 100) { if (byte_val < 0x00FF * 25 / 100) ++num_moons; ++num_moons; } ++num_moons; } ++num_moons; } break; } planet->NumPlanets = num_moons; } } static void GenerateMoons (void) { COUNT i, facing; PPLANET_DESC pMoonDesc; PPLANET_DESC pCurDesc; DWORD old_seed; GLOBAL (ip_location.x) = (SIZE)((long)(GLOBAL (ShipStamp.origin.x) - (SIS_SCREEN_WIDTH >> 1)) * MAX_ZOOM_RADIUS / (DISPLAY_FACTOR >> 1)); GLOBAL (ip_location.y) = (SIZE)((long)(GLOBAL (ShipStamp.origin.y) - (SIS_SCREEN_HEIGHT >> 1)) * MAX_ZOOM_RADIUS / (DISPLAY_FACTOR >> 1)); pCurDesc = pSolarSysState->pBaseDesc; old_seed = TFB_SeedRandom (pCurDesc->rand_seed); (*pSolarSysState->GenFunc) (GENERATE_NAME); (*pSolarSysState->GenFunc) (GENERATE_MOONS); facing = NORMALIZE_FACING (ANGLE_TO_FACING ( ARCTAN (pCurDesc->location.x, pCurDesc->location.y))); for (i = 0, pMoonDesc = &pSolarSysState->MoonDesc[0]; i < MAX_MOONS; ++i, ++pMoonDesc) { pMoonDesc->pPrevDesc = pCurDesc; if (pSolarSysState->MenuState.Initialized > 1 || i >= pCurDesc->NumPlanets) ; else { BYTE data_index; pMoonDesc->temp_color = pCurDesc->temp_color; data_index = pMoonDesc->data_index; if (data_index == (BYTE)~0) { /* Starbase */ pMoonDesc->image.frame = SetAbsFrameIndex (SpaceJunkFrame, 16); } else if (data_index == (BYTE)(~0 - 1)) { /* Sa-Matra */ pMoonDesc->image.frame = SetAbsFrameIndex (SpaceJunkFrame, 19); } } } pSolarSysState->pBaseDesc = pSolarSysState->MoonDesc; TFB_SeedRandom (old_seed); } void FreeIPData (void) { DestroyDrawable (ReleaseDrawable (SISIPFrame)); SISIPFrame = 0; DestroyDrawable (ReleaseDrawable (SunFrame)); SunFrame = 0; DestroyColorMap (ReleaseColorMap (SunCMap)); SunCMap = 0; DestroyColorMap (ReleaseColorMap (OrbitalCMap)); OrbitalCMap = 0; DestroyDrawable (ReleaseDrawable (OrbitalFrame)); OrbitalFrame = 0; DestroyDrawable (ReleaseDrawable (SpaceJunkFrame)); SpaceJunkFrame = 0; DestroyMusic (SpaceMusic); SpaceMusic = 0; } void LoadIPData (void) { if (SpaceJunkFrame == 0) { SpaceJunkFrame = CaptureDrawable ( LoadGraphic (IPBKGND_MASK_PMAP_ANIM)); SISIPFrame = CaptureDrawable (LoadGraphic (SISIP_MASK_PMAP_ANIM)); OrbitalCMap = CaptureColorMap (LoadColorMap (ORBPLAN_COLOR_MAP)); OrbitalFrame = CaptureDrawable ( LoadGraphic (ORBPLAN_MASK_PMAP_ANIM)); SunCMap = CaptureColorMap (LoadColorMap (IPSUN_COLOR_MAP)); SunFrame = CaptureDrawable (LoadGraphic (SUN_MASK_PMAP_ANIM)); SpaceMusic = LoadMusic (IP_MUSIC); } } void LoadSolarSys (void) { COUNT i; PPLANET_DESC pCurDesc; DWORD old_seed; #define NUM_TEMP_RANGES 5 static const COLOR temp_color_array[NUM_TEMP_RANGES] = { BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x0E), 0x54), BUILD_COLOR (MAKE_RGB15 (0x00, 0x06, 0x08), 0x62), BUILD_COLOR (MAKE_RGB15 (0x00, 0x0B, 0x00), 0x6D), BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D), BUILD_COLOR (MAKE_RGB15 (0x0F, 0x08, 0x00), 0x75), }; pSolarSysState->MenuState.CurState = 0; pSolarSysState->MenuState.Initialized = HIBYTE (HIWORD (GLOBAL (ShipStamp.frame))); if (pSolarSysState->MenuState.Initialized) { GLOBAL (ShipStamp.frame) = (FRAME)MAKE_DWORD ( LOWORD (GLOBAL (ShipStamp.frame)), LOBYTE (HIWORD (GLOBAL (ShipStamp.frame)))); ++pSolarSysState->MenuState.Initialized; } else { // LoadIPData (); } old_seed = TFB_SeedRandom (MAKE_DWORD (CurStarDescPtr->star_pt.x, CurStarDescPtr->star_pt.y)); SunFrame = SetAbsFrameIndex (SunFrame, STAR_TYPE (CurStarDescPtr->Type)); pCurDesc = &pSolarSysState->SunDesc[0]; pCurDesc->pPrevDesc = 0; pCurDesc->rand_seed = TFB_Random (); pCurDesc->data_index = STAR_TYPE (CurStarDescPtr->Type); pCurDesc->location.x = 0; pCurDesc->location.y = 0; pCurDesc->image.origin = pCurDesc->location; pCurDesc->image.frame = SunFrame; (*pSolarSysState->GenFunc) (GENERATE_PLANETS); if (GET_GAME_STATE (PLANETARY_CHANGE)) { PutPlanetInfo (); SET_GAME_STATE (PLANETARY_CHANGE, 0); } for (i = 0, pCurDesc = pSolarSysState->PlanetDesc; i < MAX_PLANETS; ++i, ++pCurDesc) { pCurDesc->pPrevDesc = &pSolarSysState->SunDesc[0]; pCurDesc->image.origin = pCurDesc->location; if (pSolarSysState->MenuState.Initialized != 0 || i >= pSolarSysState->SunDesc[0].NumPlanets) pCurDesc->image.frame = 0; else { COUNT index; SYSTEM_INFO SysInfo; DoPlanetaryAnalysis (&SysInfo, pCurDesc); index = (SysInfo.PlanetInfo.SurfaceTemperature + 250) / 100; if (index >= NUM_TEMP_RANGES) index = NUM_TEMP_RANGES - 1; pCurDesc->temp_color = temp_color_array[index]; } } { SIZE sort_array[MAX_PLANETS + 1]; // When this part is done, sort_array will contain the indices to // all planets, sorted on their y position. // The sun itself, which has its data located at // pSolarSysState->PlanetDesc[-1], is included in this array. // Very ugly stuff, but it's correct. for (i = 0; i <= pSolarSysState->SunDesc[0].NumPlanets; ++i) sort_array[i] = i - 1; for (i = 0; i <= pSolarSysState->SunDesc[0].NumPlanets; ++i) { COUNT j; for (j = pSolarSysState->SunDesc[0].NumPlanets; j > i; --j) { SIZE real_i, real_j; real_i = sort_array[i]; real_j = sort_array[j]; if (pSolarSysState->PlanetDesc[real_i].image.origin.y > pSolarSysState->PlanetDesc[real_j].image.origin.y) { SIZE temp; temp = sort_array[i]; sort_array[i] = sort_array[j]; sort_array[j] = temp; } } } pSolarSysState->FirstPlanetIndex = sort_array[0]; pSolarSysState->LastPlanetIndex = sort_array[ pSolarSysState->SunDesc[0].NumPlanets ]; for (i = 0; i <= pSolarSysState->SunDesc[0].NumPlanets; ++i) pSolarSysState->PlanetDesc[sort_array[i]].NextIndex = sort_array[i + 1]; } i = LOBYTE (HIWORD (GLOBAL (ShipStamp.frame))); if (i == 0) pSolarSysState->pBaseDesc = pSolarSysState->pOrbitalDesc = pSolarSysState->PlanetDesc; else { pSolarSysState->pOrbitalDesc = 0; pSolarSysState->pBaseDesc = &pSolarSysState->PlanetDesc[i - 1]; pSolarSysState->SunDesc[0].location = GLOBAL (ip_location); GenerateMoons (); SET_GAME_STATE (PLANETARY_LANDING, 0); } { BYTE i, num_thrusters; num_thrusters = 0; for (i = 0; i < NUM_DRIVE_SLOTS; ++i) { if (GLOBAL_SIS (DriveSlots[i]) == FUSION_THRUSTER) ++num_thrusters; } pSolarSysState->max_ship_speed = (BYTE)( (num_thrusters + 5) * IP_SHIP_THRUST_INCREMENT); pSolarSysState->turn_wait = IP_SHIP_TURN_WAIT; for (i = 0; i < NUM_JET_SLOTS; ++i) { if (GLOBAL_SIS (JetSlots[i]) == TURNING_JETS) pSolarSysState->turn_wait -= IP_SHIP_TURN_DECREMENT; } } i = pSolarSysState->MenuState.Initialized; if (i) { i -= 2; if (i == 0) pSolarSysState->pOrbitalDesc = pSolarSysState->pBaseDesc->pPrevDesc; else pSolarSysState->pOrbitalDesc = &pSolarSysState->MoonDesc[i - 1]; pSolarSysState->MenuState.Initialized = 2; GLOBAL (ip_location) = pSolarSysState->SunDesc[0].location; } else { i = LOWORD (GLOBAL (ShipStamp.frame)); if (i == 0) ++i; GLOBAL (ShipStamp.frame) = SetAbsFrameIndex (SISIPFrame, i - 1); } TFB_SeedRandom (old_seed); } static void FreeSolarSys (void) { if (pSolarSysState->MenuState.flash_task) { if (pSolarSysState->MenuState.Initialized >= 3) FreePlanet (); else { if (pSolarSysState->MenuState.flash_task != (Task)(~0)) { log_add (log_Warning, "DIAGNOSTIC: FreeSolarSys cancels a " "flash_task that wasn't the placeholder for IP flight"); ConcludeTask (pSolarSysState->MenuState.flash_task); } pSolarSysState->MenuState.flash_task = 0; LockMutex (GraphicsLock); if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) SaveFlagshipState (); UnlockMutex (GraphicsLock); } } LockMutex (GraphicsLock); SetContext (SpaceContext); StopMusic (); // FreeIPData (); UnlockMutex (GraphicsLock); } static void CheckIntersect (BOOLEAN just_checking) { COUNT i; PPLANET_DESC pCurDesc; INTERSECT_CONTROL ShipIntersect, PlanetIntersect; COUNT NewWaitPlanet; BYTE PlanetOffset, MoonOffset; pCurDesc = pSolarSysState->pBaseDesc->pPrevDesc; ShipIntersect.IntersectStamp.origin = GLOBAL (ShipStamp.origin); ShipIntersect.EndPoint = ShipIntersect.IntersectStamp.origin; ShipIntersect.IntersectStamp.frame = GLOBAL (ShipStamp.frame); PlanetIntersect.IntersectStamp.origin.x = SIS_SCREEN_WIDTH >> 1; PlanetIntersect.IntersectStamp.origin.y = SIS_SCREEN_HEIGHT >> 1; PlanetIntersect.EndPoint = PlanetIntersect.IntersectStamp.origin; if (pSolarSysState->WaitIntersect != (COUNT)~0 && pSolarSysState->WaitIntersect != MAKE_WORD ( pCurDesc - pSolarSysState->PlanetDesc + 1, 1)) PlanetIntersect.IntersectStamp.frame = DecFrameIndex (stars_in_space); else PlanetIntersect.IntersectStamp.frame = pCurDesc->image.frame; NewWaitPlanet = 0; if (pCurDesc != pSolarSysState->SunDesc /* can't intersect with sun */ && DrawablesIntersect (&ShipIntersect, &PlanetIntersect, MAX_TIME_VALUE)) { PlanetOffset = pCurDesc - pSolarSysState->PlanetDesc + 1; MoonOffset = 1; #ifdef DEBUG_SOLARSYS log_add (log_Debug, "0: Planet %d, Moon %d", PlanetOffset, MoonOffset); #endif /* DEBUG_SOLARSYS */ NewWaitPlanet = MAKE_WORD (PlanetOffset, MoonOffset); if (pSolarSysState->WaitIntersect != (COUNT)~0 && pSolarSysState->WaitIntersect != NewWaitPlanet) { ShowPlanet: pSolarSysState->WaitIntersect = NewWaitPlanet; if (!just_checking) { ZeroVelocityComponents (&GLOBAL (velocity)); ++pSolarSysState->MenuState.Initialized; pSolarSysState->pOrbitalDesc = pCurDesc; } #ifdef DEBUG_SOLARSYS log_add (log_Debug, "Star index = %d, Planet index = %d, <%d, %d>", CurStarDescPtr - star_array, pCurDesc - pSolarSysState->PlanetDesc, pSolarSysState->SunDesc[0].location.x, pSolarSysState->SunDesc[0].location.y); #endif /* DEBUG_SOLARSYS */ return; } } for (i = pCurDesc->NumPlanets, pCurDesc = pSolarSysState->pBaseDesc; i; --i, ++pCurDesc) { PlanetIntersect.IntersectStamp.origin = pCurDesc->image.origin; PlanetIntersect.EndPoint = PlanetIntersect.IntersectStamp.origin; if (pSolarSysState->pBaseDesc == pSolarSysState->MoonDesc) { PlanetOffset = pCurDesc->pPrevDesc - pSolarSysState->PlanetDesc; MoonOffset = pCurDesc - pSolarSysState->MoonDesc + 2; } else { PlanetOffset = pCurDesc - pSolarSysState->PlanetDesc; MoonOffset = 0; } ++PlanetOffset; if (pSolarSysState->WaitIntersect != (COUNT)~0 && pSolarSysState->WaitIntersect != MAKE_WORD ( PlanetOffset, MoonOffset)) PlanetIntersect.IntersectStamp.frame = DecFrameIndex (stars_in_space); else PlanetIntersect.IntersectStamp.frame = pCurDesc->image.frame; if (DrawablesIntersect (&ShipIntersect, &PlanetIntersect, MAX_TIME_VALUE)) { #ifdef DEBUG_SOLARSYS log_add (log_Debug, "1: Planet %d, Moon %d", PlanetOffset, MoonOffset); #endif /* DEBUG_SOLARSYS */ NewWaitPlanet = MAKE_WORD (PlanetOffset, MoonOffset); if (pSolarSysState->WaitIntersect == (COUNT)~0) return; else if (pSolarSysState->WaitIntersect == NewWaitPlanet) continue; else if (pSolarSysState->pBaseDesc == pSolarSysState->MoonDesc) goto ShowPlanet; else if (!just_checking) /* pBaseDesc == PlanetDesc */ { COUNT angle; RECT r; angle = FACING_TO_ANGLE ( GetFrameIndex (GLOBAL (ShipStamp.frame)) ) + HALF_CIRCLE; GLOBAL (ShipStamp.origin.x) = (SIS_SCREEN_WIDTH >> 1) + COSINE ( angle, MIN_MOON_RADIUS + ((MAX_MOONS - 1) * MOON_DELTA) + (MOON_DELTA >> 2)); GLOBAL (ShipStamp.origin.y) = (SIS_SCREEN_HEIGHT >> 1) + SINE ( angle, MIN_MOON_RADIUS + ((MAX_MOONS - 1) * MOON_DELTA) + (MOON_DELTA >> 2)); if (GLOBAL (ShipStamp.origin.y) < 0) GLOBAL (ShipStamp.origin.y) = 1; else if (GLOBAL (ShipStamp.origin.y) >= SIS_SCREEN_HEIGHT) GLOBAL (ShipStamp.origin.y) = (SIS_SCREEN_HEIGHT - 1) - 1; pSolarSysState->pBaseDesc = pCurDesc; XFormIPLoc (&pCurDesc->image.origin, &pSolarSysState->SunDesc[0].location, FALSE); ZeroVelocityComponents (&GLOBAL (velocity)); GenerateMoons (); NewWaitPlanet = 0; SetTransitionSource (NULL); BatchGraphics (); SetGraphicGrabOther (1); DrawSystem (pSolarSysState->pBaseDesc->pPrevDesc->radius, TRUE); SetGraphicGrabOther (0); r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT; ScreenTransition (3, &r); UnbatchGraphics (); LoadIntoExtraScreen (&r); } break; } } if (pSolarSysState->WaitIntersect != (COUNT)~0 || NewWaitPlanet == 0) pSolarSysState->WaitIntersect = NewWaitPlanet; } static void GetOrbitRect (PRECT pRect, COORD cx, COORD cy, SIZE radius, COUNT xnumer, COUNT ynumer, COUNT denom) { #ifdef BVT_NOT pRect->corner.x = (SIS_SCREEN_WIDTH >> 1) + (SIZE)((long)-cx * xnumer / denom); pRect->corner.y = (SIS_SCREEN_HEIGHT >> 1) + (SIZE)((long)-cy * ynumer / denom); pRect->extent.width = (SIZE)(radius * (DWORD)(xnumer << 1) / denom); #endif pRect->corner.x = (SIS_SCREEN_WIDTH >> 1) + (SIZE)((long)-cx * (long)xnumer / (long)denom); pRect->corner.y = (SIS_SCREEN_HEIGHT >> 1) + (SIZE)((long)-cy * (long)ynumer / (long)denom); pRect->extent.width = (SIZE)((long)radius * (long)(xnumer << 1) / (long)denom); pRect->extent.height = pRect->extent.width >> 1; } static void DrawOrbit (PPLANET_DESC pPlanetDesc, COUNT xnumer, COUNT ynumer0, COUNT ynumer1, COUNT denom) { COUNT index; COORD cx, cy; RECT r; if (!(draw_sys_flags & (DRAW_ORBITS | DRAW_PLANETS))) return; cx = pPlanetDesc->radius; cy = pPlanetDesc->radius; if (xnumer > (COUNT)DISPLAY_FACTOR) { cx = cx + pPlanetDesc->location.x; cy = (cy + pPlanetDesc->location.y) << 1; } GetOrbitRect (&r, cx, cy, pPlanetDesc->radius, xnumer, ynumer0, denom); if (draw_sys_flags & DRAW_ORBITS) { if (pSolarSysState->pBaseDesc) { SetContextForeGroundColor (pPlanetDesc->temp_color); DrawOval (&r, 1); } } if (!(draw_sys_flags & DRAW_PLANETS)) return; r.corner.x += (r.extent.width >> 1); r.corner.y += (r.extent.height >> 1); r.corner.x = r.corner.x + (SIZE)((long)pPlanetDesc->location.x * (long)xnumer / (long)denom); r.corner.y = r.corner.y + (SIZE)((long)pPlanetDesc->location.y * (long)ynumer1 / (long)denom); index = pPlanetDesc->data_index & ~PLANET_SHIELDED; if (index < NUMBER_OF_PLANET_TYPES) { BYTE Type; COUNT Size; Type = PlanData[index].Type; SetColorMap (GetColorMapAddress (SetAbsColorMapIndex (OrbitalCMap, PLANCOLOR (Type)))); Size = PLANSIZE (Type); if (denom == 2 || xnumer > (COUNT)DISPLAY_FACTOR) Size += 3; else if (denom <= (COUNT)(MAX_ZOOM_RADIUS >> 2)) { ++Size; if (denom == MIN_ZOOM_RADIUS) ++Size; } if (pPlanetDesc->pPrevDesc == &pSolarSysState->SunDesc[0]) pPlanetDesc->image.frame = SetAbsFrameIndex (OrbitalFrame, (Size << FACING_SHIFT) + NORMALIZE_FACING (ANGLE_TO_FACING ( ARCTAN (pPlanetDesc->location.x, pPlanetDesc->location.y) ))); else { --Size; pPlanetDesc->image.frame = SetAbsFrameIndex (OrbitalFrame, (Size << FACING_SHIFT) + NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN ( pPlanetDesc->pPrevDesc->location.x, pPlanetDesc->pPrevDesc->location.y)))); } } if (!(denom == 2 || xnumer > (COUNT)DISPLAY_FACTOR)) { pPlanetDesc->image.origin = r.corner; } else { STAMP s; if (denom == 2) pPlanetDesc->image.origin = r.corner; s.origin = r.corner; s.frame = pPlanetDesc->image.frame; DrawStamp (&s); if (index < NUMBER_OF_PLANET_TYPES && (pPlanetDesc->data_index & PLANET_SHIELDED)) { s.frame = SetAbsFrameIndex (SpaceJunkFrame, 17); DrawStamp (&s); } } } static void FindRadius (void) { SIZE delta_x, delta_y; SIZE radius; do { if ((pSolarSysState->SunDesc[0].radius >>= 1) > MIN_ZOOM_RADIUS) radius = pSolarSysState->SunDesc[0].radius >> 1; else radius = 0; GetOrbitRect (&pSolarSysState->MenuState.flash_rect0, radius, radius, radius, DISPLAY_FACTOR, DISPLAY_FACTOR >> 2, pSolarSysState->SunDesc[0].radius); XFormIPLoc (&GLOBAL (ip_location), &GLOBAL (ShipStamp.origin), TRUE); } while (radius && (delta_x = GLOBAL (ShipStamp.origin.x) - pSolarSysState->MenuState.flash_rect0.corner.x) >= 0 && (delta_y = GLOBAL (ShipStamp.origin.y) - pSolarSysState->MenuState.flash_rect0.corner.y) >= 0 && delta_x < pSolarSysState->MenuState.flash_rect0.extent.width && delta_y < pSolarSysState->MenuState.flash_rect0.extent.height); } void ZoomSystem (void) { RECT r; r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT; SetTransitionSource (&r); BatchGraphics (); if (pSolarSysState->pBaseDesc == pSolarSysState->MoonDesc) DrawSystem (pSolarSysState->pBaseDesc->pPrevDesc->radius, TRUE); else { if (pSolarSysState->MenuState.CurState == 0) FindRadius (); DrawSystem (pSolarSysState->SunDesc[0].radius, FALSE); } ScreenTransition (3, &r); UnbatchGraphics (); LoadIntoExtraScreen (&r); } static UWORD flagship_inertial_thrust (COUNT CurrentAngle) { BYTE max_speed; SIZE cur_delta_x, cur_delta_y; COUNT TravelAngle; VELOCITYPTR VelocityPtr; max_speed = pSolarSysState->max_ship_speed; VelocityPtr = &GLOBAL (velocity); GetCurrentVelocityComponents (VelocityPtr, &cur_delta_x, &cur_delta_y); TravelAngle = GetVelocityTravelAngle (VelocityPtr); if (TravelAngle == CurrentAngle && cur_delta_x == COSINE (CurrentAngle, max_speed) && cur_delta_y == SINE (CurrentAngle, max_speed)) return (SHIP_AT_MAX_SPEED); else { SIZE delta_x, delta_y; DWORD desired_speed; delta_x = cur_delta_x + COSINE (CurrentAngle, IP_SHIP_THRUST_INCREMENT); delta_y = cur_delta_y + SINE (CurrentAngle, IP_SHIP_THRUST_INCREMENT); desired_speed = (DWORD) ((long) delta_x * delta_x) + (DWORD) ((long) delta_y * delta_y); if (desired_speed <= (DWORD) ((UWORD) max_speed * max_speed)) SetVelocityComponents (VelocityPtr, delta_x, delta_y); else if (TravelAngle == CurrentAngle) { SetVelocityComponents (VelocityPtr, COSINE (CurrentAngle, max_speed), SINE (CurrentAngle, max_speed)); return (SHIP_AT_MAX_SPEED); } else { VELOCITY_DESC v; v = *VelocityPtr; DeltaVelocityComponents (&v, COSINE (CurrentAngle, IP_SHIP_THRUST_INCREMENT >> 1) - COSINE (TravelAngle, IP_SHIP_THRUST_INCREMENT), SINE (CurrentAngle, IP_SHIP_THRUST_INCREMENT >> 1) - SINE (TravelAngle, IP_SHIP_THRUST_INCREMENT)); GetCurrentVelocityComponents (&v, &cur_delta_x, &cur_delta_y); desired_speed = (DWORD) ((long) cur_delta_x * cur_delta_x) + (DWORD) ((long) cur_delta_y * cur_delta_y); if (desired_speed > (DWORD) ((UWORD) max_speed * max_speed)) { SetVelocityComponents (VelocityPtr, COSINE (CurrentAngle, max_speed), SINE (CurrentAngle, max_speed)); return (SHIP_AT_MAX_SPEED); } *VelocityPtr = v; } return 0; } } static void ProcessShipControls (void) { COUNT index; SIZE delta_x, delta_y; ClockTick (); if (CurrentInputState.key[PlayerOne][KEY_UP]) delta_y = -1; else delta_y = 0; delta_x = 0; if (CurrentInputState.key[PlayerOne][KEY_LEFT]) delta_x -= 1; if (CurrentInputState.key[PlayerOne][KEY_RIGHT]) delta_x += 1; if (delta_x || delta_y < 0) { GLOBAL (autopilot.x) = ~0; GLOBAL (autopilot.y) = ~0; } else if (GLOBAL (autopilot.x) != ~0 && GLOBAL (autopilot.y) != ~0) delta_y = -1; else delta_y = 0; index = GetFrameIndex (GLOBAL (ShipStamp.frame)); if (pSolarSysState->turn_counter) --pSolarSysState->turn_counter; else if (delta_x) { if (delta_x < 0) index = NORMALIZE_FACING (index - 1); else index = NORMALIZE_FACING (index + 1); GLOBAL (ShipStamp.frame) = SetAbsFrameIndex (GLOBAL (ShipStamp.frame), index); pSolarSysState->turn_counter = pSolarSysState->turn_wait; } if (pSolarSysState->thrust_counter) --pSolarSysState->thrust_counter; else if (delta_y < 0) { #define THRUST_WAIT 1 flagship_inertial_thrust (FACING_TO_ANGLE (index)); pSolarSysState->thrust_counter = THRUST_WAIT; } } static void UndrawShip (void) { SIZE radius, delta_x, delta_y; BOOLEAN LeavingInnerSystem; #ifdef SHOW_RADAR extern void DrawIPRadar (BOOLEAN FirstTime); DrawIPRadar (FALSE); #endif /* SHOW_RADAR */ LeavingInnerSystem = FALSE; radius = pSolarSysState->SunDesc[0].radius; if (GLOBAL (ShipStamp.origin.x) < 0 || GLOBAL (ShipStamp.origin.x) >= SIS_SCREEN_WIDTH || GLOBAL (ShipStamp.origin.y) < 0 || GLOBAL (ShipStamp.origin.y) >= SIS_SCREEN_HEIGHT) { if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) { if (radius == MAX_ZOOM_RADIUS) { GLOBAL (CurrentActivity) |= END_INTERPLANETARY; return; } } else { PPLANET_DESC pPlanetDesc; LeavingInnerSystem = TRUE; pPlanetDesc = pSolarSysState->pBaseDesc->pPrevDesc; pSolarSysState->pBaseDesc = pSolarSysState->PlanetDesc; pSolarSysState->WaitIntersect = MAKE_WORD ( pPlanetDesc - pSolarSysState->PlanetDesc + 1, 0); GLOBAL (ip_location) = pSolarSysState->SunDesc[0].location; ZeroVelocityComponents (&GLOBAL (velocity)); } radius = MAX_ZOOM_RADIUS << 1; } if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc && (radius > MAX_ZOOM_RADIUS || ((delta_x = GLOBAL (ShipStamp.origin.x) - pSolarSysState->MenuState.flash_rect0.corner.x) >= 0 && (delta_y = GLOBAL (ShipStamp.origin.y) - pSolarSysState->MenuState.flash_rect0.corner.y) >= 0 && delta_x < pSolarSysState->MenuState.flash_rect0.extent.width && delta_y < pSolarSysState->MenuState.flash_rect0.extent.height))) { old_radius = pSolarSysState->SunDesc[0].radius; pSolarSysState->SunDesc[0].radius = radius; FindRadius (); if (old_radius == (MAX_ZOOM_RADIUS << 1) || old_radius == pSolarSysState->SunDesc[0].radius || LeavingInnerSystem) { old_radius = 0; if (LeavingInnerSystem) SetGraphicGrabOther (1); DrawSystem (pSolarSysState->SunDesc[0].radius, FALSE); if (LeavingInnerSystem) { COUNT OldWI; SetGraphicGrabOther (0); OldWI = pSolarSysState->WaitIntersect; CheckIntersect (TRUE); if (pSolarSysState->WaitIntersect != OldWI) { pSolarSysState->WaitIntersect = (COUNT)~0; return; } } } else return; } if (GLOBAL (autopilot.x) == ~0 && GLOBAL (autopilot.y) == ~0) CheckIntersect (FALSE); } #if 0 static void DrawSimpleSystem (SIZE radius, BYTE flags) { draw_sys_flags &= ~flags; DrawSystem (radius, FALSE); draw_sys_flags |= flags; } #endif static void ScaleSystem (void) { #if 0 #define NUM_STEPS 8 COUNT num_steps; SIZE err, d, new_radius, step; RECT r; BOOLEAN first_time; CONTEXT OldContext; first_time = TRUE; new_radius = pSolarSysState->SunDesc[0].radius; BatchGraphics (); DrawSimpleSystem (new_radius, DRAW_PLANETS | DRAW_ORBITS | GRAB_BKGND); pSolarSysState->SunDesc[0].radius = old_radius; d = new_radius - old_radius; step = d / NUM_STEPS; if (d < 0) d = -d; num_steps = err = NUM_STEPS; OldContext = SetContext (SpaceContext); GetContextClipRect (&r); SetGraphicGrabOther (1); // to grab from hidden screen (since we haven't flipped yet) LoadIntoExtraScreen (&r); SetGraphicGrabOther (0); SetContextFGFrame (Screen); do { if ((err -= d) <= 0) { pSolarSysState->SunDesc[0].radius += step; BatchGraphics (); DrawFromExtraScreen (r.corner.x, r.corner.y); DrawSimpleSystem (pSolarSysState->SunDesc[0].radius, DRAW_ORBITS | DRAW_STARS | GRAB_BKGND | DRAW_HYPER_COORDS); RedrawQueue (FALSE); if (first_time) { first_time = FALSE; UnbatchGraphics (); // to balance out Batch before DrawSimpleSystem above } UnbatchGraphics (); err += d; } } while (--num_steps); SetContext (OldContext); pSolarSysState->SunDesc[0].radius = new_radius; DrawSystem (pSolarSysState->SunDesc[0].radius, FALSE); old_radius = 0; #else RECT r; CONTEXT OldContext; OldContext = SetContext (SpaceContext); GetContextClipRect (&r); SetTransitionSource (&r); BatchGraphics (); DrawSystem (pSolarSysState->SunDesc[0].radius, FALSE); ScreenTransition (3, &r); UnbatchGraphics (); LoadIntoExtraScreen (&r); SetContext (OldContext); old_radius = 0; #endif } /* Constants and routines for handling interplanetary play. TODO: this is NOT THREAD-SAFE; only one IP task may be active at any given time. --Michael */ #define IP_FRAME_RATE (ONE_SECOND / 30) static UWORD IP_input_state; static DWORD IP_next_time; void IP_reset (void) { if (LastActivity != CHECK_LOAD) { IP_input_state = 0; } else { IP_input_state = 2; /* CANCEL */ } IP_next_time = GetTimeCounter (); } void IP_frame (void) { CONTEXT OldContext; BOOLEAN InnerSystem; RECT r; BOOLEAN select, cancel; InnerSystem = FALSE; LockMutex (GraphicsLock); if ((pSolarSysState->MenuState.Initialized > 1 || (GLOBAL (CurrentActivity) & (START_ENCOUNTER | END_INTERPLANETARY | CHECK_ABORT | CHECK_LOAD)) || GLOBAL_SIS (CrewEnlisted) == (COUNT)~0)) { UnlockMutex (GraphicsLock); TaskSwitch (); IP_input_state = 0; IP_next_time = GetTimeCounter (); return; } cancel = ((IP_input_state) >> 1) & 1; select = (IP_input_state) & 1; OldContext = SetContext (StatusContext); if (pSolarSysState->MenuState.CurState || pSolarSysState->MenuState.Initialized == 0) { select = FALSE; cancel = FALSE; if (draw_sys_flags & DRAW_REFRESH) goto TheMess; } else { TheMess: // this is a mess: // we have to treat things slightly differently depending on the // situation (note that DRAW_REFRESH means we had gone to the // menu) InnerSystem = (BOOLEAN) (pSolarSysState->pBaseDesc != pSolarSysState->PlanetDesc); if (InnerSystem) { SetTransitionSource (NULL); BatchGraphics (); if (draw_sys_flags & DRAW_REFRESH) { InnerSystem = FALSE; DrawSystem (pSolarSysState->pBaseDesc->pPrevDesc->radius, TRUE); } } else if (draw_sys_flags & DRAW_REFRESH) { SetTransitionSource (NULL); BatchGraphics (); DrawSystem (pSolarSysState->SunDesc[0].radius, FALSE); } if (!(draw_sys_flags & DRAW_REFRESH)) ProcessShipControls (); UndrawShip (); if (pSolarSysState->MenuState.Initialized != 1) { select = FALSE; cancel = FALSE; } } if (old_radius) ScaleSystem (); BatchGraphics (); if (!(draw_sys_flags & DRAW_REFRESH)) // don't repair from Extra or draw ship if forcing repair { CONTEXT OldContext; OldContext = SetContext (SpaceContext); GetContextClipRect (&r); DrawFromExtraScreen (&r); SetContext (OldContext); // Don't redraw if entering/exiting inner system // this screws up ScreenTransition by leaving an image of the // ship in the ExtraScreen (which we use for repair) if (pSolarSysState->MenuState.CurState == 0 && (InnerSystem ^ (BOOLEAN)( pSolarSysState->pBaseDesc != pSolarSysState->PlanetDesc))) ; else RedrawQueue (FALSE); } if (InnerSystem) { if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) { // transition screen if we left inner system (if going // from outer to inner, ScreenTransition happens elsewhere) r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT; ScreenTransition (3, &r); } UnbatchGraphics (); } else if (draw_sys_flags & DRAW_REFRESH) { // must set rect for LoadInto... below r.corner.x = SIS_ORG_X; r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; r.extent.height = SIS_SCREEN_HEIGHT; ScreenTransition (3, &r); UnbatchGraphics (); } UnbatchGraphics (); if (draw_sys_flags & UNBATCH_SYS) { // means we're forcing a redraw/transition from Init- & ChangeSolarSys draw_sys_flags &= ~UNBATCH_SYS; UnbatchGraphics (); } // LoadInto Extra if we left inner system, or we forced a redraw if ((InnerSystem && pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) || (draw_sys_flags & DRAW_REFRESH)) { LoadIntoExtraScreen (&r); draw_sys_flags &= ~DRAW_REFRESH; } SetContext (OldContext); UnlockMutex (GraphicsLock); if (!cancel) { SleepThreadUntil (IP_next_time + IP_FRAME_RATE); IP_next_time = GetTimeCounter (); if (pSolarSysState->MenuState.CurState || pSolarSysState->MenuState.Initialized != 1) { cancel = FALSE; select = FALSE; } else { /* Updating the input state is handled by * DoFlagshipCommands, which is running in * parallel with us */ // UpdateInputState (); cancel = PulsedInputState.menu[KEY_MENU_CANCEL]; select = PulsedInputState.menu[KEY_MENU_SELECT]; IP_input_state = (cancel << 1) | select; } // JournalInput (InputState); } else { SuspendGameClock (); LockMutex (GraphicsLock); DrawStatusMessage (NULL_PTR); if (LastActivity == CHECK_LOAD) pSolarSysState->MenuState.CurState = (ROSTER + 1) + 1; else { UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_STARMAP, STARMAP); LockMutex (GraphicsLock); pSolarSysState->MenuState.CurState = STARMAP + 1; IP_input_state = 0; } SetFlashRect (SFR_MENU_3DO, (FRAME)0); FlushInput (); UnlockMutex (GraphicsLock); } } static void DrawInnerSystem (void) { LockMutex (GraphicsLock); DrawSISTitle (GLOBAL_SIS (PlanetName)); DrawSystem (pSolarSysState->pBaseDesc->pPrevDesc->radius, TRUE); UnlockMutex (GraphicsLock); } BOOLEAN ValidateOrbits (void) { BYTE i; BOOLEAN InnerSystem; POINT old_pts[2]; PPLANET_DESC pCurDesc; InnerSystem = (BOOLEAN)( pSolarSysState->pBaseDesc == pSolarSysState->MoonDesc); if (InnerSystem) { old_pts[0] = GLOBAL (ShipStamp.origin); old_pts[1] = GLOBAL (ip_location); GLOBAL (ip_location) = pSolarSysState->SunDesc[0].location; } pSolarSysState->SunDesc[0].radius = MAX_ZOOM_RADIUS << 1; FindRadius (); pSolarSysState->pBaseDesc = 0; for (i = pSolarSysState->SunDesc[0].NumPlanets, pCurDesc = &pSolarSysState->PlanetDesc[0]; i; --i, ++pCurDesc) { DrawOrbit (pCurDesc, DISPLAY_FACTOR, DISPLAY_FACTOR >> 2, DISPLAY_FACTOR >> 1, pSolarSysState->SunDesc[0].radius); } if (!InnerSystem) pSolarSysState->pBaseDesc = pSolarSysState->PlanetDesc; else { pSolarSysState->pBaseDesc = pSolarSysState->MoonDesc; GLOBAL (ShipStamp.origin) = old_pts[0]; GLOBAL (ip_location) = old_pts[1]; } return (InnerSystem); } void ChangeSolarSys (void) { if (pSolarSysState->MenuState.Initialized == 0) { StartGroups: ++pSolarSysState->MenuState.Initialized; if (pSolarSysState->MenuState.flash_task == 0) { DrawMenuStateStrings (PM_STARMAP, -(PM_NAVIGATE - PM_SCAN)); LockMutex (GraphicsLock); RepairSISBorder (); InitDisplayList (); DoMissions (); // if entering new system (NOT from load), // force redraw and transition in IPtask_func if ((draw_sys_flags & UNBATCH_SYS) && LastActivity != (CHECK_LOAD | CHECK_RESTART)) draw_sys_flags |= DRAW_REFRESH; CheckIntersect (TRUE); IP_reset (); pSolarSysState->MenuState.flash_task = (Task)(~0); /* pSolarSysState->MenuState.flash_task = AssignTask (IPtask_func, 6144, "interplanetary task"); */ UnlockMutex (GraphicsLock); if (!PLRPlaying ((MUSIC_REF)~0) && LastActivity != CHECK_LOAD) { PlayMusic (SpaceMusic, TRUE, 1); if (LastActivity == (CHECK_LOAD | CHECK_RESTART)) { BYTE clut_buf[] = {FadeAllToColor}; LastActivity = 0; if (draw_sys_flags & UNBATCH_SYS) { draw_sys_flags &= ~UNBATCH_SYS; UnbatchGraphics (); } LockMutex (GraphicsLock); while (pSolarSysState->SunDesc[0].radius == (MAX_ZOOM_RADIUS << 1)) { UnlockMutex (GraphicsLock); IP_frame (); LockMutex (GraphicsLock); } UnlockMutex (GraphicsLock); XFormColorMap ((COLORMAPPTR)clut_buf, ONE_SECOND / 2); } } ResumeGameClock (); SetGameClockRate (INTERPLANETARY_CLOCK_RATE); } } else { if (pSolarSysState->MenuState.flash_task) { SuspendGameClock (); FreeSolarSys (); if (pSolarSysState->pOrbitalDesc->pPrevDesc != &pSolarSysState->SunDesc[0]) GLOBAL (ShipStamp.origin) = pSolarSysState->pOrbitalDesc->image.origin; else { GLOBAL (ShipStamp.origin.x) = SIS_SCREEN_WIDTH >> 1; GLOBAL (ShipStamp.origin.y) = SIS_SCREEN_HEIGHT >> 1; } } GetPlanetInfo (); (*pSolarSysState->GenFunc) (GENERATE_ORBITAL); LastActivity &= ~(CHECK_LOAD | CHECK_RESTART); if ((GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD | START_ENCOUNTER)) || GLOBAL_SIS (CrewEnlisted) == (COUNT)~0 || GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) return; if (pSolarSysState->MenuState.flash_task == 0) { /* Note! This implies that our GenFunc was a conversation; that is, that this is a homeworld */ SetTransitionSource (NULL); LoadSolarSys (); ValidateOrbits (); DrawInnerSystem (); ScreenTransition (3, NULL); goto StartGroups; } else { DrawMenuStateStrings (PM_SCAN, SCAN); LockMutex (GraphicsLock); pSolarSysState->MenuState.CurState = SCAN + 1; SetFlashRect (SFR_MENU_3DO, (FRAME)0); FlushInput (); UnlockMutex (GraphicsLock); } } } void InitSolarSys (void) { BOOLEAN InnerSystem; BOOLEAN Reentry; LockMutex (GraphicsLock); LoadIPData (); LoadLanderData (); UnlockMutex (GraphicsLock); pSolarSysState->MenuState.InputFunc = DoFlagshipCommands; Reentry = (BOOLEAN)(GLOBAL (ShipStamp.frame) != 0); if (!Reentry) { GLOBAL (autopilot.x) = ~0; GLOBAL (autopilot.y) = ~0; GLOBAL (ShipStamp.origin.x) = SIS_SCREEN_WIDTH >> 1; GLOBAL (ShipStamp.origin.y) = SIS_SCREEN_HEIGHT >> 1; GLOBAL (ShipStamp.origin.y) += (SIS_SCREEN_HEIGHT >> 1) - 1; pSolarSysState->SunDesc[0].radius = MAX_ZOOM_RADIUS; XFormIPLoc (&GLOBAL (ShipStamp.origin), &GLOBAL (ip_location), FALSE); } LoadSolarSys (); InnerSystem = ValidateOrbits (); if (Reentry) { (*pSolarSysState->GenFunc) (REINIT_NPCS); } else { EncounterRace = -1; EncounterGroup = 0; GLOBAL (BattleGroupRef) = 0; ReinitQueue (&GLOBAL (npc_built_ship_q)); (*pSolarSysState->GenFunc) (INIT_NPCS); } if (pSolarSysState->MenuState.Initialized == 0) { LockMutex (GraphicsLock); SetTransitionSource (NULL); BatchGraphics (); draw_sys_flags |= UNBATCH_SYS; if (LastActivity & (CHECK_LOAD | CHECK_RESTART)) { if ((LastActivity & (CHECK_LOAD | CHECK_RESTART)) == LastActivity) { DrawSISFrame (); if (NextActivity) LastActivity &= ~(CHECK_LOAD | CHECK_RESTART); } else { ClearSISRect (DRAW_SIS_DISPLAY); LastActivity &= ~CHECK_LOAD; } } // Enabled graphics synchronization again, as in 3DO code originally. // This should fix the 'entering star' lockup/messed graphics problems. DrawSISMessage (NULL_PTR); SetContext (SpaceContext); SetContextFGFrame (Screen); SetContextBackGroundColor (BLACK_COLOR); UnlockMutex (GraphicsLock); if (InnerSystem) { SetGraphicGrabOther (1); // since Unbatch won't have flipped yet DrawInnerSystem (); SetGraphicGrabOther (0); if (draw_sys_flags & UNBATCH_SYS) { draw_sys_flags &= ~UNBATCH_SYS; ScreenTransition (3, 0); UnbatchGraphics (); LoadIntoExtraScreen (0); } } else { LockMutex (GraphicsLock); DrawHyperCoords (CurStarDescPtr->star_pt); /* Adjust position */ UnlockMutex (GraphicsLock); /* force a redraw */ pSolarSysState->SunDesc[0].radius = MAX_ZOOM_RADIUS << 1; } } } void UninitSolarSys (void) { FreeSolarSys (); //FreeLanderData (); //FreeIPData (); if (GLOBAL (CurrentActivity) & END_INTERPLANETARY) { GLOBAL (CurrentActivity) &= ~END_INTERPLANETARY; (*pSolarSysState->GenFunc) (UNINIT_NPCS); SET_GAME_STATE (USED_BROADCASTER, 0); } else if ((GLOBAL (CurrentActivity) & START_ENCOUNTER) && EncounterGroup) { GetGroupInfo (GLOBAL (BattleGroupRef), EncounterGroup); if (HIWORD (GLOBAL (ShipStamp.frame)) == 0) { BYTE i; DWORD best_dist; PPLANET_DESC pCurDesc; best_dist = ~0L; for (i = 0, pCurDesc = pSolarSysState->PlanetDesc; i < pSolarSysState->SunDesc[0].NumPlanets; ++i, ++pCurDesc) { SIZE dx, dy; DWORD dist; dx = GLOBAL (ShipStamp.origin.x) - pCurDesc->image.origin.x; dy = GLOBAL (ShipStamp.origin.y) - pCurDesc->image.origin.y; dist = (DWORD) ((long) dx * dx + (long) dy * dy); if (dist < best_dist) { best_dist = dist; pSolarSysState->pBaseDesc = pCurDesc; } } (*pSolarSysState->GenFunc) (GENERATE_NAME); } } } void GenerateRandomIP (BYTE control) { COUNT i; DWORD rand_val; switch (control) { case INIT_NPCS: if (!GetGroupInfo (GLOBAL (BattleGroupRef), GROUP_INIT_IP)) { GLOBAL (BattleGroupRef) = 0; BuildGroups (); } break; case REINIT_NPCS: GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); break; case UNINIT_NPCS: PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); break; case GENERATE_MINERAL: GenerateMineralDeposits (&pSolarSysState->SysInfo, &pSolarSysState->CurNode); break; case GENERATE_ENERGY: pSolarSysState->CurNode = 0; break; case GENERATE_LIFE: GenerateLifeForms (&pSolarSysState->SysInfo, &pSolarSysState->CurNode); break; case GENERATE_ORBITAL: { #ifdef DEBUG_SOLARSYS if (pSolarSysState->pOrbitalDesc->pPrevDesc == pSolarSysState->SunDesc) log_add (log_Debug, "Planet index = %d", pSolarSysState->pOrbitalDesc - pSolarSysState->PlanetDesc); else log_add (log_Debug, "Planet index = %d, Moon index = %d", pSolarSysState->pOrbitalDesc->pPrevDesc - pSolarSysState->PlanetDesc, pSolarSysState->pOrbitalDesc - pSolarSysState->MoonDesc); #endif /* DEBUG_SOLARSYS */ rand_val = DoPlanetaryAnalysis (&pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; i = (COUNT)~0; rand_val = GenerateLifeForms (&pSolarSysState->SysInfo, &i); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; i = (COUNT)~0; GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] = rand_val; LoadPlanet (NULL); break; } case GENERATE_NAME: { i = pSolarSysState->pBaseDesc - pSolarSysState->PlanetDesc; utf8StringCopy (GLOBAL_SIS (PlanetName), sizeof (GLOBAL_SIS (PlanetName)), GAME_STRING (PLANET_NUMBER_BASE + (9 + 7) + i)); SET_GAME_STATE (BATTLE_PLANET, pSolarSysState->PlanetDesc[i].data_index); break; } case GENERATE_MOONS: FillOrbits (pSolarSysState, pSolarSysState->pBaseDesc->NumPlanets, &pSolarSysState->MoonDesc[0], FALSE); break; case GENERATE_PLANETS: { FillOrbits (pSolarSysState, (BYTE)~0, &pSolarSysState->PlanetDesc[0], FALSE); GeneratePlanets (pSolarSysState); break; } } } void DrawSystem (SIZE radius, BOOLEAN IsInnerSystem) { BYTE i; PPLANET_DESC pCurDesc, pBaseDesc; BatchGraphics (); if (draw_sys_flags & DRAW_STARS) DrawStarBackGround (FALSE); if (!IsInnerSystem) { pBaseDesc = pSolarSysState->PlanetDesc; pSolarSysState->pOrbitalDesc = 0; } else { pBaseDesc = pSolarSysState->pBaseDesc; pCurDesc = pBaseDesc->pPrevDesc; pSolarSysState->pOrbitalDesc = pCurDesc; DrawOrbit (pCurDesc, DISPLAY_FACTOR << 2, DISPLAY_FACTOR, DISPLAY_FACTOR << 1, radius); } for (i = pBaseDesc->pPrevDesc->NumPlanets, pCurDesc = pBaseDesc; i; --i, ++pCurDesc) { if (IsInnerSystem) DrawOrbit (pCurDesc, 2, 1, 1, 2); else DrawOrbit (pCurDesc, DISPLAY_FACTOR, DISPLAY_FACTOR >> 2, DISPLAY_FACTOR >> 1, radius); } if (IsInnerSystem) DrawSISTitle (GLOBAL_SIS (PlanetName)); else { SIZE index; index = 0; if (radius <= (MAX_ZOOM_RADIUS >> 1)) { ++index; if (radius <= (MAX_ZOOM_RADIUS >> 2)) ++index; } pCurDesc = &pSolarSysState->SunDesc[0]; pCurDesc->image.origin.x = SIS_SCREEN_WIDTH >> 1; pCurDesc->image.origin.y = SIS_SCREEN_HEIGHT >> 1; pCurDesc->image.frame = SetRelFrameIndex (SunFrame, index); index = pSolarSysState->FirstPlanetIndex; if (draw_sys_flags & DRAW_PLANETS) { for (;;) { pCurDesc = &pSolarSysState->PlanetDesc[index]; /* Star color fix - draw the star using own cmap */ if (pCurDesc == &pSolarSysState->SunDesc[0]) { SetColorMap (GetColorMapAddress (SetAbsColorMapIndex ( SunCMap, STAR_COLOR (CurStarDescPtr->Type) ))); } else { SetColorMap (GetColorMapAddress (SetAbsColorMapIndex ( OrbitalCMap, PLANCOLOR (PlanData[ pCurDesc->data_index & ~PLANET_SHIELDED].Type) ))); } DrawStamp (&pCurDesc->image); if (index == pSolarSysState->LastPlanetIndex) break; index = pCurDesc->NextIndex; } } if (pSolarSysState->pBaseDesc == pSolarSysState->PlanetDesc) XFormIPLoc (&GLOBAL (ip_location), &GLOBAL (ShipStamp.origin), TRUE); else XFormIPLoc (&pSolarSysState->SunDesc[0].location, &GLOBAL (ShipStamp.origin), TRUE); if (draw_sys_flags & DRAW_HYPER_COORDS) DrawHyperCoords (CurStarDescPtr->star_pt); } UnbatchGraphics (); SetContext (SpaceContext); if (draw_sys_flags & GRAB_BKGND) { RECT r; GetContextClipRect (&r); LoadIntoExtraScreen (&r); } // pSolarSysState->WaitIntersect = TRUE; } void DrawStarBackGround (BOOLEAN ForPlanet) { COUNT i, j; DWORD rand_val; STAMP s; DWORD old_seed; SetContext (SpaceContext); SetContextBackGroundColor (BLACK_COLOR); ClearDrawable (); old_seed = TFB_SeedRandom ( MAKE_DWORD (CurStarDescPtr->star_pt.x, CurStarDescPtr->star_pt.y)); #define NUM_DIM_PIECES 8 s.frame = SpaceJunkFrame; for (i = 0; i < NUM_DIM_PIECES; ++i) { #define NUM_DIM_DRAWN 5 for (j = 0; j < NUM_DIM_DRAWN; ++j) { rand_val = TFB_Random (); s.origin.x = LOWORD (rand_val) % SIS_SCREEN_WIDTH; s.origin.y = HIWORD (rand_val) % SIS_SCREEN_HEIGHT; DrawStamp (&s); } s.frame = IncFrameIndex (s.frame); } #define NUM_BRT_PIECES 8 for (i = 0; i < NUM_BRT_PIECES; ++i) { #define NUM_BRT_DRAWN 30 for (j = 0; j < NUM_BRT_DRAWN; ++j) { rand_val = TFB_Random (); s.origin.x = LOWORD (rand_val) % SIS_SCREEN_WIDTH; s.origin.y = HIWORD (rand_val) % SIS_SCREEN_HEIGHT; DrawStamp (&s); } s.frame = IncFrameIndex (s.frame); } if (ForPlanet) { RECT r; // 2002-12-13 PhracturedBlue's fix to planet changing color when // using device problem /*if (pSolarSysState->MenuState.flash_task || (LastActivity & CHECK_LOAD)) RenderTopography (TRUE);*/ BatchGraphics (); SetContext (ScreenContext); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); r.corner.x = SIS_ORG_X - 1; r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT - 4; r.extent.width = SIS_SCREEN_WIDTH + 2; r.extent.height = 3; DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); r.extent.width = 1; r.extent.height = MAP_HEIGHT + 1; r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT; r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH - 1; DrawFilledRectangle (&r); r.corner.x = SIS_ORG_X + SIS_SCREEN_WIDTH; DrawFilledRectangle (&r); r.extent.width = SIS_SCREEN_WIDTH + 1; r.extent.height = 1; r.corner.x = SIS_ORG_X; r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT - 5; DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19)); r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT - 1; r.extent.width = MAP_WIDTH + 2; r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH - 1; DrawFilledRectangle (&r); r.extent.width = 1; r.extent.height = MAP_HEIGHT + 1; r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT; r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH - 1; DrawFilledRectangle (&r); UnbatchGraphics (); } TFB_SeedRandom (old_seed); } void XFormIPLoc (PPOINT pIn, PPOINT pOut, BOOLEAN ToDisplay) { if (ToDisplay) { pOut->x = (SIS_SCREEN_WIDTH >> 1) + (SIZE)((long)pIn->x * (DISPLAY_FACTOR >> 1) // / (long)pSolarSysState->SunDesc[0].radius); / pSolarSysState->SunDesc[0].radius); pOut->y = (SIS_SCREEN_HEIGHT >> 1) + (SIZE)((long)pIn->y * (DISPLAY_FACTOR >> 1) // / (long)pSolarSysState->SunDesc[0].radius); / pSolarSysState->SunDesc[0].radius); } else { pOut->x = (SIZE)((long)(pIn->x - (SIS_SCREEN_WIDTH >> 1)) // * (long)pSolarSysState->SunDesc[0].radius * pSolarSysState->SunDesc[0].radius / (DISPLAY_FACTOR >> 1)); pOut->y = (SIZE)((long)(pIn->y - (SIS_SCREEN_HEIGHT >> 1)) // * (long)pSolarSysState->SunDesc[0].radius * pSolarSysState->SunDesc[0].radius / (DISPLAY_FACTOR >> 1)); } } void ExploreSolarSys (void) { SOLARSYS_STATE SolarSysState; if (CurStarDescPtr == 0) { POINT universe; universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); CurStarDescPtr = FindStar (0, &universe, 1, 1); /* // The following code used to be there, but the test is // pointless. Maybe we should panic here? if ((CurStarDescPtr = FindStar (0, &universe, 1, 1)) == 0) ; */ } GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (CurStarDescPtr->star_pt.x); GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (CurStarDescPtr->star_pt.y); pSolarSysState = &SolarSysState; memset (pSolarSysState, 0, sizeof (*pSolarSysState)); SolarSysState.GenFunc = GenerateIP (CurStarDescPtr->Index); InitSolarSys (); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); DoInput ((PVOID)&SolarSysState.MenuState, FALSE); UninitSolarSys (); pSolarSysState = 0; } uqm-0.6.2/sc2/src/sc2code/planets/gensup.c0000600000175000017500000001106010543202100016703 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "lander.h" #include "nameref.h" #include "resinst.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateSupox (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i, which_node; DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; if (!GET_GAME_STATE (ULTRON_CONDITION)) pSolarSysState->SysInfo.PlanetInfo.CurType = 0; else pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i)) { pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << i); if (!GET_GAME_STATE (ULTRON_CONDITION)) { ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; SET_GAME_STATE (ULTRON_CONDITION, 1); } } if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 2; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 152L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { if (ActivateStarShip (SUPOX_SHIP, SPHERE_TRACKING)) { NotifyOthers (SUPOX_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (SUPOX_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); InitCommunication (SUPOX_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } else { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (RUINS_STRTAB) ); if (!GET_GAME_STATE (ULTRON_CONDITION)) pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetAbsStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 1 ); } } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/lifeform.h0000600000175000017500000000345510543202100017223 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _LIFEFORM_H #define _LIFEFORM_H #include "libs/compiler.h" #define BEHAVIOR_HUNT (0 << 0) #define BEHAVIOR_FLEE (1 << 0) #define BEHAVIOR_UNPREDICTABLE (2 << 0) #define BEHAVIOR_MASK 0x03 #define BEHAVIOR_SHIFT 0 #define AWARENESS_LOW (0 << 2) #define AWARENESS_MEDIUM (1 << 2) #define AWARENESS_HIGH (2 << 2) #define AWARENESS_MASK 0x0C #define AWARENESS_SHIFT (BEHAVIOR_SHIFT + 2) #define SPEED_MOTIONLESS (0 << 4) #define SPEED_SLOW (1 << 4) #define SPEED_MEDIUM (2 << 4) #define SPEED_FAST (3 << 4) #define SPEED_MASK 0x30 #define SPEED_SHIFT (AWARENESS_SHIFT + 2) #define DANGER_HARMLESS (0 << 6) #define DANGER_WEAK (1 << 6) #define DANGER_NORMAL (2 << 6) #define DANGER_MONSTROUS (3 << 6) #define DANGER_MASK 0xC0 #define DANGER_SHIFT (SPEED_SHIFT + 2) #define NUM_CREATURE_TYPES 23 #define NUM_SPECIAL_CREATURE_TYPES 3 #define MAX_LIFE_VARIATION 3 #define CREATURE_AWARE (BYTE)(1 << 7) typedef struct { BYTE Attributes, ValueAndHitPoints; } LIFEFORM_DESC; extern const LIFEFORM_DESC CreatureData[]; #endif /* _LIFEFORM_H */ uqm-0.6.2/sc2/src/sc2code/planets/devices.c0000600000175000017500000004075110543202100017035 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "gamestr.h" #include "controls.h" #include "settings.h" #include "shipcont.h" #include "load.h" #include "setup.h" #include "state.h" #include "sounds.h" #include "util.h" #include "strlib.h" // If DEBUG_DEVICES is defined, the device list shown in the game will // include the pictures of all devices defined, regardless of which // devices the player actually possesses. //#define DEBUG_DEVICES static void DrawDevices (PMENU_STATE pMS, BYTE OldDevice, BYTE NewDevice) { #define MAX_VIS_DEVICES 5 COORD y, cy; TEXT t; RECT r; PBYTE pDeviceMap; LockMutex (GraphicsLock); SetContext (StatusContext); SetContextFont (TinyFont); y = 41; t.baseline.x = 40; t.align = ALIGN_CENTER; t.CharCount = 3; pDeviceMap = (PBYTE)pMS->CurFrame; if (OldDevice > NUM_DEVICES || (NewDevice < NUM_DEVICES && (NewDevice < (BYTE)pMS->first_item.y || NewDevice >= (BYTE)(pMS->first_item.y + MAX_VIS_DEVICES)))) { STAMP s; r.corner.x = 2; r.extent.width = FIELD_WIDTH + 1; if (!(pMS->Initialized & 1)) { ++r.corner.x; r.extent.width -= 2; r.corner.y = 33; r.extent.height = 89; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); DrawFilledRectangle (&r); } else { TEXT ct; r.corner.y = 20; r.extent.height = 109; DrawStarConBox (&r, 1, BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F), TRUE, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); SetContextFont (StarConFont); ct.baseline.x = (STATUS_WIDTH >> 1) - 1; ct.baseline.y = 27; ct.align = ALIGN_CENTER; ct.pStr = GAME_STRING (DEVICE_STRING_BASE); ct.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)); font_DrawText (&ct); SetContextFont (TinyFont); } if (NewDevice < (BYTE)pMS->first_item.y) pMS->first_item.y = NewDevice; else if (NewDevice >= (BYTE)(pMS->first_item.y + MAX_VIS_DEVICES)) pMS->first_item.y = NewDevice - (MAX_VIS_DEVICES - 1); s.origin.x = 4; s.origin.y = 34; cy = y; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); for (OldDevice = (BYTE)pMS->first_item.y; OldDevice < (BYTE)(pMS->first_item.y + MAX_VIS_DEVICES) && OldDevice < (BYTE)pMS->first_item.x; ++OldDevice) { s.frame = SetAbsFrameIndex ( MiscDataFrame, 77 + pDeviceMap[OldDevice]); DrawStamp (&s); if (OldDevice != NewDevice) { t.baseline.y = cy; t.pStr = GAME_STRING (pDeviceMap[OldDevice] + DEVICE_STRING_BASE + 1); t.CharCount = utf8StringPos (t.pStr, ' '); font_DrawText (&t); t.baseline.y += 7; t.pStr = skipUTF8Chars (t.pStr, t.CharCount + 1); t.CharCount = (COUNT)~0; font_DrawText (&t); } cy += 18; s.origin.y += 18; } OldDevice = NewDevice; } r.extent.width = 41; r.extent.height = 14; r.corner.x = t.baseline.x - (r.extent.width >> 1); if (OldDevice != NewDevice) { cy = y + ((OldDevice - pMS->first_item.y) * 18); r.corner.y = cy - 6; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); t.baseline.y = cy; t.pStr = GAME_STRING (pDeviceMap[OldDevice] + DEVICE_STRING_BASE + 1); t.CharCount = utf8StringPos (t.pStr, ' '); font_DrawText (&t); t.baseline.y += 7; t.pStr = skipUTF8Chars (t.pStr, t.CharCount + 1); t.CharCount = (COUNT)~0; font_DrawText (&t); } if (NewDevice < NUM_DEVICES) { cy = y + ((NewDevice - pMS->first_item.y) * 18); r.corner.y = cy - 6; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)); t.baseline.y = cy; t.pStr = GAME_STRING (pDeviceMap[NewDevice] + DEVICE_STRING_BASE + 1); t.CharCount = utf8StringPos (t.pStr, ' '); font_DrawText (&t); t.baseline.y += 7; t.pStr = skipUTF8Chars (t.pStr, t.CharCount + 1); t.CharCount = (COUNT)~0; font_DrawText (&t); } UnlockMutex (GraphicsLock); } // Returns TRUE if the broadcaster has been successfully activated, // and FALSE otherwise. static BOOLEAN UseCaster (void) { if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { SET_GAME_STATE (USED_BROADCASTER, 1); return TRUE; } return FALSE; } if (LOBYTE (GLOBAL (CurrentActivity)) != IN_INTERPLANETARY || pSolarSysState == NULL) return FALSE; if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[1] && pSolarSysState->MenuState.Initialized == 3 && CurStarDescPtr->Index == CHMMR_DEFINED && !GET_GAME_STATE (CHMMR_UNLEASHED)) { // In orbit around the Chenjesu/Mmrnmhrm home planet. NextActivity |= CHECK_LOAD; /* fake a load game */ GLOBAL (CurrentActivity) |= START_ENCOUNTER; EncounterGroup = 0; PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); SaveFlagshipState (); return TRUE; } { BOOLEAN FoundIlwrath; HSTARSHIP hStarShip; FoundIlwrath = (BOOLEAN)(CurStarDescPtr->Index == ILWRATH_DEFINED); // In the Ilwrath home system? if (!FoundIlwrath && (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)))) { // Ilwrath ship is in the system. SHIP_FRAGMENTPTR FragPtr; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); FoundIlwrath = (BOOLEAN)( GET_RACE_ID (FragPtr) == ILWRATH_SHIP); UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } if (FoundIlwrath) { NextActivity |= CHECK_LOAD; /* fake a load game */ GLOBAL (CurrentActivity) |= START_ENCOUNTER; EncounterGroup = 0; PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); if (CurStarDescPtr->Index == ILWRATH_DEFINED) { // Ilwrath home system. SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 4); } else { // Ilwrath ship. SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 5); } if (pSolarSysState->MenuState.Initialized >= 3) SaveFlagshipState (); return TRUE; } } return FALSE; } static UWORD DeviceFailed (BYTE which_device) { BYTE val; switch (which_device) { case ROSY_SPHERE_DEVICE: val = GET_GAME_STATE (ULTRON_CONDITION); if (val) { SET_GAME_STATE (ULTRON_CONDITION, val + 1); SET_GAME_STATE (ROSY_SPHERE_ON_SHIP, 0); SET_GAME_STATE (DISCUSSED_ULTRON, 0); SET_GAME_STATE (SUPOX_ULTRON_HELP, 0); return (FALSE); } break; case ARTIFACT_2_DEVICE: break; case ARTIFACT_3_DEVICE: break; case SUN_EFFICIENCY_DEVICE: if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY && pSolarSysState && pSolarSysState->pOrbitalDesc && pSolarSysState->MenuState.Initialized == 3) { BYTE fade_buf[1]; PlayMenuSound (MENU_SOUND_INVOKED); fade_buf[0] = FadeAllToWhite; SleepThreadUntil ( XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND * 1) + (ONE_SECOND * 2)); if (CurStarDescPtr->Index != CHMMR_DEFINED || pSolarSysState->pOrbitalDesc != &pSolarSysState->PlanetDesc[1]) { fade_buf[0] = FadeAllToColor; XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND * 2); } else { SET_GAME_STATE (CHMMR_EMERGING, 1); EncounterGroup = 0; GLOBAL (CurrentActivity) |= START_ENCOUNTER; PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (CHMMR_SHIP, &GLOBAL (npc_built_ship_q), 0); } return (MAKE_WORD (0, 1)); } break; case UTWIG_BOMB_DEVICE: SET_GAME_STATE (UTWIG_BOMB, 0); GLOBAL (CurrentActivity) &= ~IN_BATTLE; GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; return (FALSE); case ULTRON_0_DEVICE: break; case ULTRON_1_DEVICE: break; case ULTRON_2_DEVICE: break; case ULTRON_3_DEVICE: break; case MAIDENS_DEVICE: break; case TALKING_PET_DEVICE: NextActivity |= CHECK_LOAD; /* fake a load game */ GLOBAL (CurrentActivity) |= START_ENCOUNTER; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 0); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { if (GetHeadEncounter ()) { SET_GAME_STATE (SHIP_TO_COMPEL, 1); } GLOBAL (CurrentActivity) &= ~IN_BATTLE; } else { EncounterGroup = 0; if (GetHeadLink (&GLOBAL (npc_built_ship_q))) { SET_GAME_STATE (SHIP_TO_COMPEL, 1); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); } if (CurStarDescPtr->Index == SAMATRA_DEFINED) { SET_GAME_STATE (READY_TO_CONFUSE_URQUAN, 1); } if (pSolarSysState->MenuState.Initialized < 3) return (FALSE); } SaveFlagshipState (); return (FALSE); case AQUA_HELIX_DEVICE: val = GET_GAME_STATE (ULTRON_CONDITION); if (val) { SET_GAME_STATE (ULTRON_CONDITION, val + 1); SET_GAME_STATE (AQUA_HELIX_ON_SHIP, 0); SET_GAME_STATE (DISCUSSED_ULTRON, 0); SET_GAME_STATE (SUPOX_ULTRON_HELP, 0); return (FALSE); } break; case CLEAR_SPINDLE_DEVICE: val = GET_GAME_STATE (ULTRON_CONDITION); if (val) { SET_GAME_STATE (ULTRON_CONDITION, val + 1); SET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 0); SET_GAME_STATE (DISCUSSED_ULTRON, 0); SET_GAME_STATE (SUPOX_ULTRON_HELP, 0); return (FALSE); } break; case UMGAH_HYPERWAVE_DEVICE: case BURVIX_HYPERWAVE_DEVICE: if (UseCaster ()) return FALSE; break; case TAALO_PROTECTOR_DEVICE: break; case EGG_CASING0_DEVICE: case EGG_CASING1_DEVICE: case EGG_CASING2_DEVICE: break; case SYREEN_SHUTTLE_DEVICE: break; case VUX_BEAST_DEVICE: break; case DESTRUCT_CODE_DEVICE: break; case PORTAL_SPAWNER_DEVICE: #define PORTAL_FUEL_COST (10 * FUEL_TANK_SCALE) if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1 && GLOBAL_SIS (FuelOnBoard) >= PORTAL_FUEL_COST) { /* No DeltaSISGauges because the flagship picture * is currently obscured. */ GLOBAL_SIS (FuelOnBoard) -= PORTAL_FUEL_COST; SET_GAME_STATE (PORTAL_COUNTER, 1); return (FALSE); } break; case URQUAN_WARP_DEVICE: break; case LUNAR_BASE_DEVICE: break; } return (TRUE); } static BOOLEAN DoManipulateDevices (PMENU_STATE pMS) { BYTE NewState; BOOLEAN select, cancel, back, forward; select = PulsedInputState.menu[KEY_MENU_SELECT]; cancel = PulsedInputState.menu[KEY_MENU_CANCEL]; back = PulsedInputState.menu[KEY_MENU_UP] || PulsedInputState.menu[KEY_MENU_LEFT]; forward = PulsedInputState.menu[KEY_MENU_DOWN] || PulsedInputState.menu[KEY_MENU_RIGHT]; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); if (!(pMS->Initialized & 1)) { DrawDevices (pMS, (BYTE)~0, (BYTE)~0); pMS->InputFunc = DoManipulateDevices; ++pMS->Initialized; NewState = pMS->CurState; goto SelectDevice; } else if (cancel) { return (FALSE); } else if (select) { UWORD status; LockMutex (GraphicsLock); status = DeviceFailed ( ((PBYTE)pMS->CurFrame)[pMS->CurState - 1] ); NewState = LOBYTE (status); if (NewState) PlayMenuSound (MENU_SOUND_FAILURE); else if (HIBYTE (status) == 0) PlayMenuSound (MENU_SOUND_INVOKED); UnlockMutex (GraphicsLock); return ((BOOLEAN)NewState); } else { SIZE NewTop; NewTop = pMS->first_item.y; NewState = pMS->CurState - 1; if (back) { if (NewState-- == 0) NewState = 0; if ((SIZE)NewState < NewTop && (NewTop -= MAX_VIS_DEVICES) < 0) NewTop = 0; } else if (forward) { if (++NewState == (BYTE)pMS->first_item.x) NewState = (BYTE)(pMS->first_item.x - 1); if (NewState >= NewTop + MAX_VIS_DEVICES) NewTop = NewState; } if (++NewState != pMS->CurState) { if (NewTop != pMS->first_item.y) { pMS->first_item.y = NewTop; pMS->CurState = (BYTE)~0; } SelectDevice: DrawDevices (pMS, (BYTE)(pMS->CurState - 1), (BYTE)(NewState - 1)); pMS->CurState = NewState; } } return (TRUE); } SIZE InventoryDevices (BYTE *pDeviceMap) { BYTE i; SIZE DevicesOnBoard; DevicesOnBoard = 0; for (i = 0; i < NUM_DEVICES; ++i) { BYTE DeviceState; DeviceState = 0; switch (i) { case ROSY_SPHERE_DEVICE: DeviceState = GET_GAME_STATE (ROSY_SPHERE_ON_SHIP); break; case ARTIFACT_2_DEVICE: DeviceState = GET_GAME_STATE (ARTIFACT_2_ON_SHIP); break; case ARTIFACT_3_DEVICE: DeviceState = GET_GAME_STATE (ARTIFACT_3_ON_SHIP); break; case SUN_EFFICIENCY_DEVICE: DeviceState = GET_GAME_STATE (SUN_DEVICE_ON_SHIP); break; case UTWIG_BOMB_DEVICE: DeviceState = GET_GAME_STATE (UTWIG_BOMB_ON_SHIP); break; case ULTRON_0_DEVICE: DeviceState = (GET_GAME_STATE (ULTRON_CONDITION) == 1); break; case ULTRON_1_DEVICE: DeviceState = (GET_GAME_STATE (ULTRON_CONDITION) == 2); break; case ULTRON_2_DEVICE: DeviceState = (GET_GAME_STATE (ULTRON_CONDITION) == 3); break; case ULTRON_3_DEVICE: DeviceState = (GET_GAME_STATE (ULTRON_CONDITION) == 4); break; case MAIDENS_DEVICE: DeviceState = GET_GAME_STATE (MAIDENS_ON_SHIP); break; case TALKING_PET_DEVICE: DeviceState = GET_GAME_STATE (TALKING_PET_ON_SHIP); break; case AQUA_HELIX_DEVICE: DeviceState = GET_GAME_STATE (AQUA_HELIX_ON_SHIP); break; case CLEAR_SPINDLE_DEVICE: DeviceState = GET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP); break; case UMGAH_HYPERWAVE_DEVICE: DeviceState = GET_GAME_STATE (UMGAH_BROADCASTERS_ON_SHIP); break; case TAALO_PROTECTOR_DEVICE: DeviceState = GET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP); break; case EGG_CASING0_DEVICE: DeviceState = GET_GAME_STATE (EGG_CASE0_ON_SHIP); break; case EGG_CASING1_DEVICE: DeviceState = GET_GAME_STATE (EGG_CASE1_ON_SHIP); break; case EGG_CASING2_DEVICE: DeviceState = GET_GAME_STATE (EGG_CASE2_ON_SHIP); break; case SYREEN_SHUTTLE_DEVICE: DeviceState = GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP); break; case VUX_BEAST_DEVICE: DeviceState = GET_GAME_STATE (VUX_BEAST_ON_SHIP); break; case DESTRUCT_CODE_DEVICE: #ifdef NEVER DeviceState = GET_GAME_STATE (DESTRUCT_CODE_ON_SHIP); #endif /* NEVER */ break; case PORTAL_SPAWNER_DEVICE: DeviceState = GET_GAME_STATE (PORTAL_SPAWNER_ON_SHIP); break; case URQUAN_WARP_DEVICE: DeviceState = GET_GAME_STATE (PORTAL_KEY_ON_SHIP); break; case BURVIX_HYPERWAVE_DEVICE: DeviceState = GET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP); break; case LUNAR_BASE_DEVICE: DeviceState = GET_GAME_STATE (MOONBASE_ON_SHIP); break; } #ifndef DEBUG_DEVICES if (DeviceState) #endif /* DEBUG_DEVICES */ { *pDeviceMap++ = i; ++DevicesOnBoard; } } return (DevicesOnBoard); } BOOLEAN Devices (PMENU_STATE pMS) { BYTE DeviceMap[NUM_DEVICES]; pMS->first_item.x = InventoryDevices (DeviceMap); if (pMS->first_item.x) { pMS->InputFunc = DoManipulateDevices; --pMS->Initialized; pMS->CurState = 1; pMS->first_item.y = 0; pMS->CurFrame = (FRAME)DeviceMap; TFB_ResetControls (); DoManipulateDevices (pMS); /* to make sure it's initialized */ SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); DoInput ((PVOID)pMS, TRUE); pMS->CurFrame = 0; pMS->InputFunc = DoFlagshipCommands; pMS->CurState = EQUIP_DEVICE + 1; if (GLOBAL_SIS (CrewEnlisted) != (COUNT)~0 && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) { LockMutex (GraphicsLock); ClearSISRect (DRAW_SIS_DISPLAY); UnlockMutex (GraphicsLock); if (!GET_GAME_STATE (PORTAL_COUNTER) && !(GLOBAL (CurrentActivity) & START_ENCOUNTER) && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) // DrawMenuStateStrings (PM_SCAN, pMS->CurState - 1); return (TRUE); } } return (FALSE); } uqm-0.6.2/sc2/src/sc2code/planets/genvault.c0000600000175000017500000000675010543202100017241 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "encount.h" #include "globdata.h" #include "lander.h" #include "nameref.h" #include "resinst.h" #include "setup.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateShipVault (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) { DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (!GET_GAME_STATE (SHIP_VAULT_UNLOCKED)) pSolarSysState->SysInfo.PlanetInfo.CurType = 0; else pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->CurNode = 1; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << 0); if (GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP)) { ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; SET_GAME_STATE (SHIP_VAULT_UNLOCKED, 1); SET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP, 0); SET_GAME_STATE (SYREEN_HOME_VISITS, 0); } else if (!GET_GAME_STATE (KNOW_SYREEN_VAULT)) { SET_GAME_STATE (KNOW_SYREEN_VAULT, 1); SET_GAME_STATE (SYREEN_HOME_VISITS, 0); } } TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (VAULT_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (VAULT_STRTAB) ); if (GET_GAME_STATE (SHIP_VAULT_UNLOCKED)) pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetAbsStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 2 ); else if (GET_GAME_STATE (SYREEN_SHUTTLE_ON_SHIP)) pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetAbsStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 1 ); } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/genpku.c0000600000175000017500000001113410543202100016675 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "lander.h" #include "nameref.h" #include "resinst.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" void GeneratePkunk (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i, which_node; DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; if (!GET_GAME_STATE (CLEAR_SPINDLE)) pSolarSysState->SysInfo.PlanetInfo.CurType = 0; else pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i)) { pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << i); if (!GET_GAME_STATE (CLEAR_SPINDLE)) { ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; SET_GAME_STATE (CLEAR_SPINDLE, 1); SET_GAME_STATE (CLEAR_SPINDLE_ON_SHIP, 1); } } if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 1; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 104L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { if (ActivateStarShip (PKUNK_SHIP, SPHERE_TRACKING)) { NotifyOthers (PKUNK_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (PKUNK_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); InitCommunication (PKUNK_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } else { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (PKUNK_RUINS_STRTAB) ); if (GET_GAME_STATE (CLEAR_SPINDLE)) pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetAbsStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 1 ); } } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/genwreck.c0000600000175000017500000000552110543202100017214 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "globdata.h" #include "lander.h" #include "nameref.h" #include "resinst.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateUrquanWreck (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[6]) { DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (!GET_GAME_STATE (PORTAL_KEY)) pSolarSysState->SysInfo.PlanetInfo.CurType = 0; else pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->CurNode = 1; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << 0); if (!GET_GAME_STATE (PORTAL_KEY)) { ((PPLANETSIDE_DESC)pMenuState->ModuleFrame)->InTransit = TRUE; SET_GAME_STATE (PORTAL_KEY, 1); SET_GAME_STATE (PORTAL_KEY_ON_SHIP, 1); } } TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[6]) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (WRECK_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (WRECK_STRTAB) ); if (GET_GAME_STATE (PORTAL_KEY)) pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetAbsStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 1 ); } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/plangen.c0000600000175000017500000014707410543202100017045 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "nameref.h" #include "resinst.h" #include "setup.h" #include "options.h" #include "planets/planets.h" #include "planets/scan.h" #include "libs/graphics/gfx_common.h" #include "libs/graphics/drawable.h" #include "libs/mathlib.h" #include "libs/log.h" #include #include #define PROFILE_ROTATION 1 #define ROTATION_TIME 12 // The initial size of the planet when zooming. MUST BE ODD #define PLANET_INIT_ZOOM_SIZE 3 // define USE_ALPHA_SHIELD to use an aloha overlay instead of // an additive overlay for the shield effect #undef USE_ALPHA_SHIELD // XXX: these are currently defined in libs/graphics/sdl/3do_getbody.c // they should be sorted out and cleaned up at some point extern DWORD frame_mapRGBA (FRAME FramePtr, UBYTE r, UBYTE g, UBYTE b, UBYTE a); extern void process_rgb_bmp (FRAME FramePtr, DWORD *rgba, int maxx, int maxy); extern FRAME stretch_frame (FRAME FramePtr, int neww, int newh, int destroy); extern void fill_frame_rgb (FRAME FramePtr, DWORD color, int x0, int y0, int x, int y); extern void arith_frame_blit (FRAME srcFrame, RECT *rsrc, FRAME dstFrame, RECT *rdst, int num, int denom); extern void getpixelarray (void *map, int Bpp, FRAMEPTR FramePtr, int width, int height); #define SHIELD_GLOW_COMP 120 #define SHIELD_REFLECT_COMP 100 #define NUM_BATCH_POINTS 64 #define USE_3D_PLANET 1 #define RADIUS 37 //2*RADIUS #define TWORADIUS (RADIUS << 1) //RADIUS^2 #define RADIUS_2 (RADIUS * RADIUS) // distance beyond which all pixels are transparent (for aa) #define RADIUS_THRES ((RADIUS + 1) * (RADIUS + 1)) #define DIAMETER (TWORADIUS + 1) #if 0 # define SPHERE_SPAN_X (MAP_WIDTH >> 1) #else # define SPHERE_SPAN_X (MAP_HEIGHT) #endif // XXX: technically, the sphere's span over X should be MAP_WIDTH/2 // but this causes visible surface compression over X, because // the surface dims ratio is H x H*PI, instead of H x 2*H // see bug #885 #define DIFFUSE_BITS 16 #define AA_WEIGHT_BITS 16 #ifndef M_TWOPI #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define M_TWOPI (M_PI * 2.0) #endif #ifndef M_DEG2RAD #define M_DEG2RAD (M_TWOPI / 360.0) #endif DWORD light_diff[DIAMETER][DIAMETER]; typedef struct { POINT p[4]; DWORD m[4]; } MAP3D_POINT; MAP3D_POINT map_rotate[DIAMETER][DIAMETER]; typedef struct { double x, y, z; } POINT3; static void TransformTopography (FRAME DstFrame, PBYTE pTopoData, int w, int h) { CONTEXT OldContext; FRAME OldFrame; OldContext = SetContext (TaskContext); OldFrame = SetContextFGFrame (DstFrame); if (pSolarSysState->XlatRef == 0) { STAMP s; s.origin.x = s.origin.y = 0; #if 0 s.frame = SetAbsFrameIndex ( pSolarSysState->PlanetFrameArray[2], 1 ); DrawStamp (&s); #endif } else { COUNT i; BYTE AlgoType; SIZE base, d; POINT pt; PLANDATAPTR PlanDataPtr; PRIMITIVE BatchArray[NUM_BATCH_POINTS]; PPRIMITIVE pBatch; PBYTE pSrc, xlat_tab, cbase; HOT_SPOT OldHot; RECT ClipRect; OldHot = SetFrameHot (DstFrame, MAKE_HOT_SPOT (0, 0)); GetContextClipRect (&ClipRect); SetContextClipRect (NULL_PTR); SetContextClipping (FALSE); pBatch = &BatchArray[0]; for (i = 0; i < NUM_BATCH_POINTS; ++i, ++pBatch) { SetPrimNextLink (pBatch, (COUNT)(i + 1)); SetPrimType (pBatch, POINT_PRIM); } SetPrimNextLink (&pBatch[-1], END_OF_LIST); PlanDataPtr = &PlanData[ pSolarSysState->pOrbitalDesc->data_index & ~PLANET_SHIELDED ]; AlgoType = PLANALGO (PlanDataPtr->Type); base = PlanDataPtr->base_elevation; xlat_tab = (PBYTE)((XLAT_DESCPTR)pSolarSysState->XlatPtr)->xlat_tab; cbase = GetColorMapAddress (pSolarSysState->OrbitalCMap); i = NUM_BATCH_POINTS; pBatch = &BatchArray[i]; pSrc = pTopoData; for (pt.y = 0; pt.y < h; ++pt.y) { for (pt.x = 0; pt.x < w; ++pt.x, ++pSrc) { PBYTE ctab; d = (SBYTE)*pSrc; if (AlgoType == GAS_GIANT_ALGO) { d &= 255; } else { d += base; if (d < 0) d = 0; else if (d > 255) d = 255; } --pBatch; pBatch->Object.Point.x = pt.x; pBatch->Object.Point.y = pt.y; d = xlat_tab[d] - cbase[0]; ctab = (cbase + 2) + d * 3; // fixed planet surfaces being too dark // ctab shifts were previously >> 3 .. -Mika SetPrimColor (pBatch, BUILD_COLOR (MAKE_RGB15 (ctab[0] >> 1, ctab[1] >> 1, ctab[2] >> 1), d)); if (--i == 0) { // flush the batch and start the next one DrawBatch (BatchArray, 0, 0); i = NUM_BATCH_POINTS; pBatch = &BatchArray[i]; } } } if (i < NUM_BATCH_POINTS) { DrawBatch (BatchArray, i, 0); } SetContextClipping (TRUE); SetContextClipRect (&ClipRect); SetFrameHot (DstFrame, OldHot); } SetContextFGFrame (OldFrame); SetContext (OldContext); } static void RenderTopography (BOOLEAN Reconstruct) // Reconstruct arg was not used on 3DO and is not needed here either { TransformTopography (pSolarSysState->TopoFrame, pSolarSysState->Orbit.lpTopoData, MAP_WIDTH, MAP_HEIGHT); (void)Reconstruct; // swallow compiler whining } static inline void P3mult (POINT3 *res, POINT3 *vec, double cnst) { res->x = vec->x * cnst; res->y = vec->y * cnst; res->z = vec->z * cnst; } static inline void P3sub (POINT3 *res, POINT3 *v1, POINT3 *v2) { res->x = v1->x - v2->x; res->y = v1->y - v2->y; res->z = v1->z - v2->z; } static inline double P3dot (POINT3 *v1, POINT3 *v2) { return (v1->x * v2->x + v1->y * v2->y + v1->z * v2->z); } static inline void P3norm (POINT3 *res, POINT3 *vec) { double mag = sqrt (P3dot (vec, vec)); P3mult (res, vec, 1/mag); } // RenderPhongMask builds a shadow map for the rotating planet // loc indicates the planet's position relative to the sun static void RenderPhongMask (POINT loc) { POINT pt; POINT3 light; double lrad; const DWORD step = 1 << DIFFUSE_BITS; int y, x; #define AMBIENT_LIGHT 0.1 #define LIGHT_Z 1.2 // lrad is the distance from the sun to the planet lrad = sqrt (loc.x * loc.x + loc.y * loc.y); // light is the sun's position. the z-coordinate is whatever // looks good light.x = -((double)loc.x); light.y = -((double)loc.y); light.z = LIGHT_Z * lrad; P3norm (&light, &light); for (pt.y = 0, y = -RADIUS; pt.y <= TWORADIUS; ++pt.y, y++) { DWORD y_2 = y * y; for (pt.x = 0, x = -RADIUS; pt.x <= TWORADIUS; ++pt.x, x++) { DWORD x_2 = x * x; DWORD rad_2 = x_2 + y_2; DWORD diff_int = 0; POINT3 norm; double diff; if (rad_2 < RADIUS_THRES) { // norm is the sphere's surface normal. norm.x = (double)x; norm.y = (double)y; norm.z = (sqrt (RADIUS_2 - x_2) * sqrt (RADIUS_2 - y_2)) / RADIUS; P3norm (&norm, &norm); // diffuse component is norm dot light diff = P3dot (&norm, &light); // negative diffuse is bad if (diff < 0) diff = 0.0; #if 0 // Specular is not used in practice and is left here // if someone decides to use it later for some reason. // Specular highlight is only good for perfectly smooth // surfaces, like balls (of which planets are not) // This wouldn't be RenderPhongMask without the Phong eq. #define LIGHT_INTENS 0.3 #define MSHI 2 double fb, spec; POINT3 rvec; POINT3 view; // always view along the z-axis // ideally use a view point, and have the view change // per pixel, but that is too much effort for now. // the view MUST be normalized! view.x = 0; view.y = 0; view.z = 1.0; // specular highlight is the phong equation: // (rvec dot view)^MSHI // where rvec = (2*diff)*norm - light (reflection of light // around norm) P3mult (&rvec, &norm, 2 * diff); P3sub (&rvec, &rvec, &light); fb = P3dot (&rvec, &view); if (fb > 0.0) spec = LIGHT_INTENS * pow (fb, MSHI); else spec = 0; #endif // adjust for the ambient light if (diff < AMBIENT_LIGHT) diff = AMBIENT_LIGHT; // Now we antialias the edge of the spere to look nice if (rad_2 > RADIUS_2) { diff *= 1 - (sqrt(rad_2) - RADIUS); if (diff < 0) diff = 0; } // diff_int allows us multiply by a ratio without using // floating-point. diff_int = (DWORD)(diff * step); } light_diff[pt.y][pt.x] = diff_int; } } } //create_aa_points creates weighted averages for // 4 points around the 'ideal' point at x,y // the concept is to compute the weight based on the // distance from the integer location points to the ideal point static void create_aa_points (MAP3D_POINT *ppt, double x, double y) { double deltax, deltay, inv_deltax, inv_deltay; COORD nextx, nexty; COUNT i; double d1, d2, d3, d4, m[4]; if (x < 0) x = 0; else if (x >= SPHERE_SPAN_X) x = SPHERE_SPAN_X - 1; if (y < 0) y = 0; else if (y >= MAP_HEIGHT) y = MAP_HEIGHT - 1; // get the integer value of this point ppt->p[0].x = (COORD)x; ppt->p[0].y = (COORD)y; deltax = x - ppt->p[0].x; deltay = y - ppt->p[0].y; // if this point doesn't need modificaton, set m[0]=0 if (deltax == 0 && deltay == 0) { ppt->m[0] = 0; return; } // get the neighboring points surrounding the 'ideal' point if (deltax != 0) nextx = ppt->p[0].x + 1; else nextx = ppt->p[0].x; if (deltay != 0) nexty = ppt->p[0].y + 1; else nexty = ppt->p[0].y; //(x1,y) ppt->p[1].x = nextx; ppt->p[1].y = ppt->p[0].y; //(x,y1) ppt->p[2].x = ppt->p[0].x; ppt->p[2].y = nexty; //(x1y1) ppt->p[3].x = nextx; ppt->p[3].y = nexty; //the square 1x1, so opposite poinnts are at 1-delta inv_deltax = 1.0 - fabs (deltax); inv_deltax *= inv_deltax; inv_deltay = 1.0 - fabs (deltay); inv_deltay *= inv_deltay; deltax *= deltax; deltay *= deltay; //d1-d4 contain the distances from the poinnts to the ideal point d1 = sqrt (deltax + deltay); d2 = sqrt (inv_deltax + deltay); d3 = sqrt (deltax + inv_deltay); d4 = sqrt (inv_deltax + inv_deltay); //compute the weights. the sum(ppt->m[])=65536 m[0] = 1 / (1 + d1 * (1 / d2 + 1 / d3 + 1 / d4)); m[1] = m[0] * d1 / d2; m[2] = m[0] * d1 / d3; m[3] = m[0] * d1 / d4; for (i = 0; i < 4; i++) ppt->m[i] = (DWORD)(m[i] * (1 << AA_WEIGHT_BITS) + 0.5); } //get_avg_rgb creates either a red, green, or blue value by //computing the weightd averages of the 4 points in p1 static UBYTE get_avg_rgb (DWORD p1[4], DWORD mult[4], COUNT offset) { COUNT i, j; UBYTE c; DWORD ci = 0; i = offset << 3; //sum(mult[])==65536 //c is the red/green/blue value of this pixel for (j = 0; j < 4; j++) { c = (UBYTE)(p1[j] >> i); ci += c * mult[j]; } ci >>= AA_WEIGHT_BITS; //check for overflow if (ci > 255) ci = 255; return ((UBYTE)ci); } // SetPlanetTilt creates 'map_rotate' to map the topo data // for a tilted planet. It also does the sphere->plane mapping void SetPlanetTilt (int angle) { int x, y; const double multx = ((double)SPHERE_SPAN_X / M_PI); const double multy = ((double)MAP_HEIGHT / M_PI); const double xadj = ((double)SPHERE_SPAN_X / 2.0); for (y = -RADIUS; y <= RADIUS; y++) { int y_2 = y * y; for (x = -RADIUS; x <= RADIUS; x++) { double dx, dy, newx, newy; double da, rad, rad_2; double xa, ya; MAP3D_POINT *ppt = &map_rotate[y + RADIUS][x + RADIUS]; rad_2 = x * x + y_2; if (rad_2 >= RADIUS_THRES) { // pixel won't be present ppt->p[0].x = x + RADIUS; ppt->p[0].y = y + RADIUS; ppt->m[0] = 0; continue; } rad = sqrt (rad_2); // antialiasing goes beyond the actual radius if (rad >= RADIUS) rad = (double)RADIUS - 0.1; da = atan2 ((double)y, (double)x); // compute the planet-tilt da += M_DEG2RAD * angle; dx = rad * cos (da); dy = rad * sin (da); // Map the sphere onto a plane xa = acos (-dx / RADIUS); ya = acos (-dy / RADIUS); newx = multx * xa; newy = multy * ya; // Adjust for vertical curvature if (ya <= 0.05 || ya >= 3.1 /* almost PI */) newx = xadj; // exact centerline else newx = xadj + ((newx - xadj) / sin (ya)); create_aa_points (ppt, newx, newy); } } } //init_zoom_array // evaluate the function 5/6*(1-e^(-x/14)) to get a decelerating zoom // on entering planet orbit. This gives us nearly equivalent to what // the 3DO does. #define ZOOM_TIME (1.13) #define ZOOM_FACT1 (6.0 / 5) #define ZOOM_FACT2 (14.0 / 25) COUNT init_zoom_array (COUNT *zoom_arr) { float frames_per_sec; int num_frames, i; int base = GSCALE_IDENTITY; frames_per_sec = (float)MAP_WIDTH / ROTATION_TIME; num_frames = (int)((frames_per_sec * ZOOM_TIME) + 0.5); for (i = 0; i < num_frames; i++) { zoom_arr[i] = (COUNT) (base * ZOOM_FACT1 * (1 - exp (-(i + 1) / (ZOOM_FACT2 * num_frames)))); } zoom_arr[i] = base; return i; } //CreateShieldMask // The shield is created in two parts. This routine creates the Halo. // The red tint of the planet is currently applied in RenderLevelMasks // This was done because the shield glows and needs to modify how the planet // gets lit. Currently, the planet area is transparent in the mask made by // this routine, but a filter can be applied if desired too. // HALO rim size #define SHIELD_HALO 7 #define SHIELD_RADIUS (RADIUS + SHIELD_HALO) #define SHIELD_DIAM ((SHIELD_RADIUS << 1) + 1) #define SHIELD_RADIUS_2 (SHIELD_RADIUS * SHIELD_RADIUS) #define SHIELD_RADIUS_THRES ((SHIELD_RADIUS + 1) * (SHIELD_RADIUS + 1)) #define SHIELD_HALO_GLOW (SHIELD_GLOW_COMP + SHIELD_REFLECT_COMP) #define SHIELD_HALO_GLOW_MIN (SHIELD_HALO_GLOW >> 2) static FRAME CreateShieldMask (void) { DWORD clear, *rgba, *p_rgba; int x, y; FRAME ShieldFrame; PLANET_ORBIT *Orbit = &pSolarSysState->Orbit; ShieldFrame = CaptureDrawable ( CreateDrawable (WANT_PIXMAP | WANT_ALPHA, SHIELD_DIAM, SHIELD_DIAM, 1)); rgba = Orbit->ScratchArray; p_rgba = rgba; // This is 100% transparent. clear = frame_mapRGBA (ShieldFrame, 0, 0, 0, 0); for (y = -SHIELD_RADIUS; y <= SHIELD_RADIUS; y++) { for (x = -SHIELD_RADIUS; x <= SHIELD_RADIUS; x++, p_rgba++) { int rad_2 = x * x + y * y; // This is a non-transparent red for the halo int red = SHIELD_HALO_GLOW; int alpha = 255; double rad; if (rad_2 >= SHIELD_RADIUS_THRES) { // outside all bounds *p_rgba = clear; continue; } // Inside the halo if (rad_2 <= RADIUS_2) { // planet's pixels, ours transparent *p_rgba = clear; continue; } // The halo itself rad = sqrt (rad_2); if (rad <= RADIUS + 0.8) { // pixels common between the shield and planet // do antialiasing using alpha alpha = (int) (red * (rad - RADIUS)); red = 255; } else { // shield pixels red -= (int) ((red - SHIELD_HALO_GLOW_MIN) * (rad - RADIUS) / SHIELD_HALO); if (red < 0) red = 0; } *p_rgba = frame_mapRGBA (ShieldFrame, red, 0, 0, alpha); } } process_rgb_bmp (ShieldFrame, rgba, SHIELD_DIAM, SHIELD_DIAM); SetFrameHot (ShieldFrame, MAKE_HOT_SPOT (SHIELD_RADIUS + 1, SHIELD_RADIUS + 1)); return ShieldFrame; } // SetShieldThrobEffect adjusts the red levels in the shield glow graphic // the throbbing cycle is tied to the planet rotation cycle #define SHIELD_THROBS 12 // throb cycles per revolution #define THROB_CYCLE ((MAP_WIDTH << 8) / SHIELD_THROBS) #define THROB_HALF_CYCLE (THROB_CYCLE >> 1) #define THROB_MAX_LEVEL 256 #define THROB_MIN_LEVEL 100 #define THROB_D_LEVEL (THROB_MAX_LEVEL - THROB_MIN_LEVEL) static inline int shield_level (int offset) { int level; offset = (offset << 8) % THROB_CYCLE; level = abs (offset - THROB_HALF_CYCLE); level = THROB_MIN_LEVEL + level * THROB_D_LEVEL / THROB_HALF_CYCLE; return level; } // See description above // offset is effectively the angle of rotation around the planet's axis static void SetShieldThrobEffect (FRAME ShieldFrame, int offset, FRAME ThrobFrame) { int i; int width, height; PLANET_ORBIT *Orbit = &pSolarSysState->Orbit; DWORD *rgba; int level; level = shield_level (offset); width = GetFrameWidth (ShieldFrame); height = GetFrameHeight (ShieldFrame); getpixelarray (Orbit->ScratchArray, 4, ShieldFrame, width, height); for (i = 0, rgba = Orbit->ScratchArray; i < width * height; ++i, ++rgba) { DWORD p = *rgba; int r, g, b, a; r = (UBYTE)(p >> 24); g = (UBYTE)(p >> 16); b = (UBYTE)(p >> 8); a = (UBYTE)(p); if (a == 255) { // adjust color data for full-alpha pixels r = r * level / THROB_MAX_LEVEL; g = g * level / THROB_MAX_LEVEL; b = b * level / THROB_MAX_LEVEL; } else if (a > 0) { // adjust alpha for translucent pixels a = a * level / THROB_MAX_LEVEL; } *rgba = frame_mapRGBA (ThrobFrame, r, g, b, a); } process_rgb_bmp (ThrobFrame, Orbit->ScratchArray, width, height); SetFrameHot (ThrobFrame, GetFrameHot (ShieldFrame)); } // Apply the shield to the topo image static void ApplyShieldTint (void) { UBYTE a; int blit_type; FRAME tintFrame = pSolarSysState->Orbit.TintFrame; DWORD p; #ifdef USE_ALPHA_SHIELD a = 200; blit_type = 0; #else //additive_blit a = 255; blit_type = -1; #endif p = frame_mapRGBA (tintFrame, 255, 0, 0, a); fill_frame_rgb (tintFrame, p, 0, 0, 0, 0); arith_frame_blit (tintFrame, NULL, pSolarSysState->TopoFrame, NULL, 0, blit_type); } static inline UBYTE calc_map_light (UBYTE val, DWORD dif, int lvf) { int i; // apply diffusion i = (dif * val) >> DIFFUSE_BITS; // apply light variance for 3d lighting effect i += (lvf * val) >> 7; if (i < 0) i = 0; else if (i > 255) i = 255; return ((UBYTE)i); } static inline DWORD get_map_pixel (DWORD *pixels, int x, int y) { return pixels[y * (MAP_WIDTH + SPHERE_SPAN_X) + x]; } static inline int get_map_elev (SBYTE *elevs, int x, int y, int offset) { return elevs[y * MAP_WIDTH + (offset + x) % MAP_WIDTH]; } // RenderLevelMasks builds a frame for the rotating planet view // offset is effectively the angle of rotation around the planet's axis // We use the SDL routines to directly write to the SDL_Surface to improve performance void RenderLevelMasks (FRAME MaskFrame, int offset, BOOLEAN doThrob) { POINT pt; DWORD *rgba, *p_rgba; DWORD clear; int x, y; DWORD *pixels; SBYTE *elevs; int shLevel; #if PROFILE_ROTATION static clock_t t = 0; static int frames_done = 1; clock_t t1; t1 = clock (); #endif shLevel = shield_level (offset); rgba = pSolarSysState->Orbit.ScratchArray; p_rgba = rgba; clear = frame_mapRGBA (MaskFrame, 0, 0, 0, 0); pixels = pSolarSysState->Orbit.lpTopoMap + offset; elevs = pSolarSysState->Orbit.lpTopoData; for (pt.y = 0, y = -RADIUS; pt.y <= TWORADIUS; ++pt.y, ++y) { for (pt.x = 0, x = -RADIUS; pt.x <= TWORADIUS; ++pt.x, ++x, ++p_rgba) { UBYTE c[3]; DWORD diffus = light_diff[pt.y][pt.x]; int i; MAP3D_POINT *ppt = &map_rotate[pt.y][pt.x]; int lvf; // light variance factor if (diffus == 0) { // full diffusion *p_rgba = clear; continue; } // get pixel from topo map and factor from light variance map if (ppt->m[0] == 0) { // exact pixel from the topo map DWORD p = get_map_pixel (pixels, ppt->p[0].x, ppt->p[0].y); c[0] = (UBYTE)(p >> 8); c[1] = (UBYTE)(p >> 16); c[2] = (UBYTE)(p >> 24); lvf = get_map_elev (elevs, ppt->p[0].x, ppt->p[0].y, offset); } else { // fractional pixel -- blend from 4 DWORD p[4]; int lvsum; // compute 'ideal' pixel for (i = 0; i < 4; i++) p[i] = get_map_pixel (pixels, ppt->p[i].x, ppt->p[i].y); for (i = 1; i < 4; i++) c[i - 1] = get_avg_rgb (p, ppt->m, i); // compute 'ideal' light variance for (i = 0, lvsum = 0; i < 4; i++) lvsum += get_map_elev (elevs, ppt->p[0].x, ppt->p[0].y, offset) * ppt->m[i]; lvf = lvsum >> AA_WEIGHT_BITS; } // Apply the lighting model. This also bounds the sphere // to make it circular. if (pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) { int r; // add lite red filter (3/4) component c[1] = (c[1] >> 1) + (c[1] >> 2); c[0] = (c[0] >> 1) + (c[0] >> 2); c[2] = calc_map_light (c[2], diffus, lvf); c[1] = calc_map_light (c[1], diffus, lvf); c[0] = calc_map_light (c[0], diffus, lvf); // The shield is glow + reflect (+ filter for others) r = calc_map_light (SHIELD_REFLECT_COMP, diffus, 0); r += SHIELD_GLOW_COMP; if (doThrob) { // adjust red level for throbbing shield r = r * shLevel / THROB_MAX_LEVEL; } r += c[2]; if (r > 255) r = 255; c[2] = r; } else { c[2] = calc_map_light (c[2], diffus, lvf); c[1] = calc_map_light (c[1], diffus, lvf); c[0] = calc_map_light (c[0], diffus, lvf); } *p_rgba = frame_mapRGBA (MaskFrame, c[2], c[1], c[0], 255); } } // Map the rgb bitmap onto the SDL_Surface process_rgb_bmp (MaskFrame, rgba, DIAMETER, DIAMETER); SetFrameHot (MaskFrame, MAKE_HOT_SPOT (RADIUS + 1, RADIUS + 1)); #if PROFILE_ROTATION t += clock() - t1; if (frames_done == MAP_WIDTH) { log_add (log_Debug, "Rotation frames/sec: %d/%ld(msec)=%f", frames_done, (long int) (((double)t / CLOCKS_PER_SEC) * 1000.0 + 0.5), frames_done / ((double)t / CLOCKS_PER_SEC + 0.5)); frames_done = 1; t = clock () - t1; } else frames_done++; #endif } #define RANGE_SHIFT 6 static void DitherMap (PSBYTE DepthArray) { COUNT i; PSBYTE lpDst; i = (MAP_WIDTH * MAP_HEIGHT) >> 2; lpDst = DepthArray; do { DWORD rand_val; rand_val = TFB_Random (); *lpDst++ += (SBYTE) ((1 << (RANGE_SHIFT - 4)) - (LOBYTE (LOWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1))); *lpDst++ += (SBYTE) ((1 << (RANGE_SHIFT - 4)) - (HIBYTE (LOWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1))); *lpDst++ += (SBYTE) ((1 << (RANGE_SHIFT - 4)) - (LOBYTE (HIWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1))); *lpDst++ += (SBYTE) ((1 << (RANGE_SHIFT - 4)) - (HIBYTE (HIWORD (rand_val)) & ((1 << (RANGE_SHIFT - 3)) - 1))); } while (--i); } static void MakeCrater (PRECT pRect, PSBYTE DepthArray, SIZE rim_delta, SIZE crater_delta, BOOLEAN SetDepth) { COORD x, y, lf_x, rt_x; SIZE A, B; long Asquared, TwoAsquared, Bsquared, TwoBsquared; long d, dx, dy; COUNT TopIndex, BotIndex, rim_pixels; A = pRect->extent.width >> 1; B = pRect->extent.height >> 1; x = 0; y = B; Asquared = (DWORD)A * A; TwoAsquared = Asquared << 1; Bsquared = (DWORD)B * B; TwoBsquared = Bsquared << 1; dx = 0; dy = TwoAsquared * B; d = Bsquared - (dy >> 1) + (Asquared >> 2); A += pRect->corner.x; B += pRect->corner.y; TopIndex = (B - y) * MAP_WIDTH; BotIndex = (B + y) * MAP_WIDTH; rim_pixels = 1; while (dx < dy) { if (d > 0) { lf_x = A - x; rt_x = A + x; if (SetDepth) { memset ((PSBYTE)&DepthArray[TopIndex + lf_x], 0, rt_x - lf_x + 1); memset ((PSBYTE)&DepthArray[BotIndex + lf_x], 0, rt_x - lf_x + 1); } if (lf_x == rt_x) { DepthArray[TopIndex + lf_x] += rim_delta; DepthArray[BotIndex + lf_x] += rim_delta; rim_pixels = 0; } else { do { DepthArray[TopIndex + lf_x] += rim_delta; DepthArray[BotIndex + lf_x] += rim_delta; if (lf_x != rt_x) { DepthArray[TopIndex + rt_x] += rim_delta; DepthArray[BotIndex + rt_x] += rim_delta; } ++lf_x; --rt_x; } while (--rim_pixels); while (lf_x < rt_x) { DepthArray[TopIndex + lf_x] += crater_delta; DepthArray[BotIndex + lf_x] += crater_delta; DepthArray[TopIndex + rt_x] += crater_delta; DepthArray[BotIndex + rt_x] += crater_delta; ++lf_x; --rt_x; } if (lf_x == rt_x) { DepthArray[TopIndex + lf_x] += crater_delta; DepthArray[BotIndex + lf_x] += crater_delta; } } --y; TopIndex += MAP_WIDTH; BotIndex -= MAP_WIDTH; dy -= TwoAsquared; d -= dy; } ++rim_pixels; ++x; dx += TwoBsquared; d += Bsquared + dx; } d += ((((Asquared - Bsquared) * 3) >> 1) - (dx + dy)) >> 1; while (y > 0) { lf_x = A - x; rt_x = A + x; if (SetDepth) { memset ((PSBYTE)&DepthArray[TopIndex + lf_x], 0, rt_x - lf_x + 1); memset ((PSBYTE)&DepthArray[BotIndex + lf_x], 0, rt_x - lf_x + 1); } if (lf_x == rt_x) { DepthArray[TopIndex + lf_x] += rim_delta; DepthArray[BotIndex + lf_x] += rim_delta; } else { do { DepthArray[TopIndex + lf_x] += rim_delta; DepthArray[BotIndex + lf_x] += rim_delta; if (lf_x != rt_x) { DepthArray[TopIndex + rt_x] += rim_delta; DepthArray[BotIndex + rt_x] += rim_delta; } ++lf_x; --rt_x; } while (--rim_pixels); while (lf_x < rt_x) { DepthArray[TopIndex + lf_x] += crater_delta; DepthArray[BotIndex + lf_x] += crater_delta; DepthArray[TopIndex + rt_x] += crater_delta; DepthArray[BotIndex + rt_x] += crater_delta; ++lf_x; --rt_x; } if (lf_x == rt_x) { DepthArray[TopIndex + lf_x] += crater_delta; DepthArray[BotIndex + lf_x] += crater_delta; } } if (d < 0) { ++x; dx += TwoBsquared; d += dx; } rim_pixels = 1; --y; TopIndex += MAP_WIDTH; BotIndex -= MAP_WIDTH; dy -= TwoAsquared; d += Asquared - dy; } lf_x = A - x; rt_x = A + x; if (SetDepth) memset ((PSBYTE)&DepthArray[TopIndex + lf_x], 0, rt_x - lf_x + 1); if (lf_x == rt_x) { DepthArray[TopIndex + lf_x] += rim_delta; } else { do { DepthArray[TopIndex + lf_x] += rim_delta; if (lf_x != rt_x) DepthArray[TopIndex + rt_x] += rim_delta; ++lf_x; --rt_x; } while (--rim_pixels); while (lf_x < rt_x) { DepthArray[TopIndex + lf_x] += crater_delta; DepthArray[TopIndex + rt_x] += crater_delta; ++lf_x; --rt_x; } if (lf_x == rt_x) { DepthArray[TopIndex + lf_x] += crater_delta; } } } #define NUM_BAND_COLORS 4 static void MakeStorms (COUNT storm_count, PSBYTE DepthArray) { #define MAX_STORMS 8 COUNT i; RECT storm_r[MAX_STORMS]; PRECT pstorm_r; pstorm_r = &storm_r[i = storm_count]; while (i--) { BOOLEAN intersect; DWORD rand_val; UWORD loword, hiword; SIZE band_delta; --pstorm_r; do { COUNT j; intersect = FALSE; rand_val = TFB_Random (); loword = LOWORD (rand_val); hiword = HIWORD (rand_val); switch (HIBYTE (hiword) & 31) { case 0: pstorm_r->extent.height = (LOBYTE (hiword) % (MAP_HEIGHT >> 2)) + (MAP_HEIGHT >> 2); break; case 1: case 2: case 3: case 4: pstorm_r->extent.height = (LOBYTE (hiword) % (MAP_HEIGHT >> 3)) + (MAP_HEIGHT >> 3); break; default: pstorm_r->extent.height = (LOBYTE (hiword) % (MAP_HEIGHT >> 4)) + 4; break; } if (pstorm_r->extent.height <= 4) pstorm_r->extent.height += 4; rand_val = TFB_Random (); loword = LOWORD (rand_val); hiword = HIWORD (rand_val); pstorm_r->extent.width = pstorm_r->extent.height + (LOBYTE (loword) % pstorm_r->extent.height); pstorm_r->corner.x = HIBYTE (loword) % (MAP_WIDTH - pstorm_r->extent.width); pstorm_r->corner.y = LOBYTE (loword) % (MAP_HEIGHT - pstorm_r->extent.height); for (j = i + 1; j < storm_count; ++j) { COORD x, y; SIZE w, h; x = storm_r[j].corner.x - pstorm_r->corner.x; y = storm_r[j].corner.y - pstorm_r->corner.y; w = x + storm_r[j].extent.width + 4; h = y + storm_r[j].extent.height + 4; intersect = (BOOLEAN) (w > 0 && h > 0 && x < pstorm_r->extent.width + 4 && y < pstorm_r->extent.height + 4); if (intersect) break; } } while (intersect); MakeCrater (pstorm_r, DepthArray, 6, 6, FALSE); ++pstorm_r->corner.x; ++pstorm_r->corner.y; pstorm_r->extent.width -= 2; pstorm_r->extent.height -= 2; band_delta = HIBYTE (loword) & ((3 << RANGE_SHIFT) + 20); MakeCrater (pstorm_r, DepthArray, band_delta, band_delta, TRUE); ++pstorm_r->corner.x; ++pstorm_r->corner.y; pstorm_r->extent.width -= 2; pstorm_r->extent.height -= 2; band_delta += 2; if (pstorm_r->extent.width > 2 && pstorm_r->extent.height > 2) { MakeCrater (pstorm_r, DepthArray, band_delta, band_delta, TRUE); ++pstorm_r->corner.x; ++pstorm_r->corner.y; pstorm_r->extent.width -= 2; pstorm_r->extent.height -= 2; } band_delta += 2; if (pstorm_r->extent.width > 2 && pstorm_r->extent.height > 2) { MakeCrater (pstorm_r, DepthArray, band_delta, band_delta, TRUE); ++pstorm_r->corner.x; ++pstorm_r->corner.y; pstorm_r->extent.width -= 2; pstorm_r->extent.height -= 2; } band_delta += 4; MakeCrater (pstorm_r, DepthArray, band_delta, band_delta, TRUE); } } static void MakeGasGiant (COUNT num_bands, PSBYTE DepthArray, PRECT pRect, SIZE depth_delta) { COORD last_y, next_y; SIZE band_error, band_bump, band_delta; COUNT i, j, band_height; PSBYTE lpDst; UWORD loword, hiword; DWORD rand_val; band_height = pRect->extent.height / num_bands; band_bump = pRect->extent.height % num_bands; band_error = num_bands >> 1; lpDst = DepthArray; band_delta = ((LOWORD (TFB_Random ()) & (NUM_BAND_COLORS - 1)) << RANGE_SHIFT) + (1 << (RANGE_SHIFT - 1)); last_y = next_y = 0; for (i = num_bands; i > 0; --i) { COORD cur_y; rand_val = TFB_Random (); loword = LOWORD (rand_val); hiword = HIWORD (rand_val); next_y += band_height; if ((band_error -= band_bump) < 0) { ++next_y; band_error += num_bands; } if (i == 1) cur_y = pRect->extent.height; else { RECT r; cur_y = next_y + ((band_height - 2) >> 1) - ((LOBYTE (hiword) % (band_height - 2)) + 1); r.corner.x = r.corner.y = 0; r.extent.width = pRect->extent.width; r.extent.height = 5; DeltaTopography (50, &DepthArray[(cur_y - 2) * r.extent.width], &r, depth_delta); } for (j = cur_y - last_y; j > 0; --j) { COUNT k; for (k = pRect->extent.width; k > 0; --k) *lpDst++ += band_delta; } last_y = cur_y; band_delta = (band_delta + ((((LOBYTE (loword) & 1) << 1) - 1) << RANGE_SHIFT)) & (((1 << RANGE_SHIFT) * NUM_BAND_COLORS) - 1); } MakeStorms ((COUNT)(4 + ((COUNT)TFB_Random () & 3) + 1), DepthArray); DitherMap (DepthArray); } static void ValidateMap (PSBYTE DepthArray) { BYTE state; BYTE pixel_count[2], lb[2]; SBYTE last_byte; COUNT i; PSBYTE lpDst; i = MAP_WIDTH - 1; lpDst = DepthArray; last_byte = *lpDst++; state = pixel_count[0] = pixel_count[1] = 0; do { if (pixel_count[state]++ == 0) lb[state] = last_byte; if (last_byte > *lpDst) { if (last_byte - *lpDst > 128) state ^= 1; } else { if (*lpDst - last_byte > 128) state ^= 1; } last_byte = *lpDst++; } while (--i); i = MAP_WIDTH * MAP_HEIGHT; lpDst = DepthArray; if (pixel_count[0] > pixel_count[1]) last_byte = lb[0]; else last_byte = lb[1]; do { if (last_byte > *lpDst) { if (last_byte - *lpDst > 128) *lpDst = last_byte; } else { if (*lpDst - last_byte > 128) *lpDst = last_byte; } last_byte = *lpDst++; } while (--i); } void planet_orbit_init () { PLANET_ORBIT *Orbit = &pSolarSysState->Orbit; Orbit->PlanetFrameArray = CaptureDrawable ( CreateDrawable (WANT_PIXMAP | WANT_ALPHA, DIAMETER, DIAMETER, 2)); Orbit->TintFrame = CaptureDrawable ( CreateDrawable (WANT_PIXMAP | WANT_ALPHA, (SWORD)MAP_WIDTH, (SWORD)MAP_HEIGHT, 2)); Orbit->ObjectFrame = 0; Orbit->WorkFrame = 0; Orbit->lpTopoData = HMalloc (MAP_WIDTH * MAP_HEIGHT); Orbit->TopoZoomFrame = CaptureDrawable ( CreateDrawable (WANT_PIXMAP, (COUNT)(MAP_WIDTH << 2), (COUNT)(MAP_HEIGHT << 2), 1)); Orbit->lpTopoMap = HMalloc (sizeof (DWORD) * (MAP_HEIGHT * (MAP_WIDTH + SPHERE_SPAN_X))); // always allocate the scratch array to largest needed size Orbit->ScratchArray = HMalloc (sizeof (DWORD) * (SHIELD_DIAM) * (SHIELD_DIAM)); } static unsigned frandom () { static unsigned seed = 0x12345678; if (seed == 0) seed = 15807; seed = (seed >> 4) * 227; return seed; } static inline int TopoVarianceFactor (int step, int allowed, int min) { #define SCALE_SHIFT 8 return ((abs(step) * allowed) >> SCALE_SHIFT) + min; } static inline int TopoVarianceCalc (int factor) { if (factor == 0) return 0; else return (frandom () % factor) - (factor >> 1); } static void TopoScale4x (PBYTE pDstTopo, PBYTE pSrcTopo, int num_faults, int fault_var) { // Interpolate the topographical data by connecting the elevations // to their nearest neighboors using straight lines (in random // direction) with random variance factors defined by // num_faults and fault_var args #define AVG_VARIANCE 250 int x, y; const int w = MAP_WIDTH, h = MAP_HEIGHT; const int spitch = MAP_WIDTH, dpitch = MAP_WIDTH * 4; PSBYTE pSrc, pDst; int* prevrow; int* prow; int elev[5][5]; int var_allow, var_min; static const struct line_def_t { int x0, y0, x1, y1; int dx, dy; } fill_lines[4][6] = { { // diag set 0 { 0, 2, 2, 0, 1, -1}, { 0, 3, 3, 0, 1, -1}, { 0, 4, 4, 0, 1, -1}, { 1, 4, 4, 1, 1, -1}, { 2, 4, 4, 2, 1, -1}, {-1, -1, -1, -1, 0, 0}, // term }, { // diag set 1 { 0, 2, 2, 4, 1, 1}, { 0, 1, 3, 4, 1, 1}, { 0, 0, 4, 4, 1, 1}, { 1, 0, 4, 3, 1, 1}, { 2, 0, 4, 2, 1, 1}, {-1, -1, -1, -1, 0, 0}, // term }, { // horizontal { 0, 1, 4, 1, 1, 0}, { 0, 2, 4, 2, 1, 0}, { 0, 3, 4, 3, 1, 0}, {-1, -1, -1, -1, 0, 0}, // term }, { // vertical { 1, 0, 1, 4, 0, 1}, { 2, 0, 2, 4, 0, 1}, { 3, 0, 3, 4, 0, 1}, {-1, -1, -1, -1, 0, 0}, // term }, }; prevrow = (int *) alloca ((MAP_WIDTH * 4 + 1) * sizeof(prevrow[0])); var_allow = (num_faults << SCALE_SHIFT) / AVG_VARIANCE; var_min = fault_var << SCALE_SHIFT; //memset (pDstTopo, 0, MAP_WIDTH * MAP_HEIGHT * 16); // init the first row in advance pSrc = pSrcTopo; prow = prevrow; #define STEP_RANGE (4 - 1) prow[0] = ((int)pSrc[0]) << SCALE_SHIFT;; for (x = 0; x < w; ++x, ++pSrc, prow += 4) { int x2; int val, step, rndfact; // next point in row if (x < w - 1) // one right prow[4] = ((int)pSrc[1]) << SCALE_SHIFT; else // wrap around prow[4] = ((int)pSrc[1 - spitch]) << SCALE_SHIFT; // compute elevations between 2 points val = prow[0]; step = (prow[4] - val) / STEP_RANGE; rndfact = TopoVarianceFactor (step, var_allow, var_min); for (x2 = 1, val += step; x2 < 4; ++x2, val += step) prow[x2] = val + TopoVarianceCalc (rndfact); } pSrc = pSrcTopo; pDst = pDstTopo; for (y = 0; y < h; ++y, pDst += dpitch * 3) { int x2, y2; PSBYTE p; int val, step, rndfact; const struct line_def_t* pld; prow = prevrow; // prime the first interpolated column elev[4][0] = prow[0]; if (y < h - 1) elev[4][4] = ((int)pSrc[spitch]) << SCALE_SHIFT; else elev[4][4] = elev[4][0]; // compute elevations for interpolated column val = elev[4][0]; step = (elev[4][4] - val) / STEP_RANGE; rndfact = TopoVarianceFactor (step, var_allow, var_min); for (y2 = 1, val += step; y2 < 4; ++y2, val += step) elev[4][y2] = val + TopoVarianceCalc (rndfact); for (x = 0; x < w; ++x, ++pSrc, pDst += 4, prow += 4) { // recall the first interpolated row from prevrow for (x2 = 0; x2 <= 4; ++x2) elev[x2][0] = prow[x2]; // recall the first interpolated column for (y2 = 1; y2 <= 4; ++y2) elev[0][y2] = elev[4][y2]; if (y < h - 1) { if (x < w - 1) // one right, one down elev[4][4] = ((int)pSrc[1 + spitch]) << SCALE_SHIFT; else // wrap around, one down elev[4][4] = ((int)pSrc[1]) << SCALE_SHIFT; } else { elev[4][4] = elev[4][0]; } // compute elevations for the rest of square borders first val = elev[0][4]; step = (elev[4][4] - val) / STEP_RANGE; rndfact = TopoVarianceFactor (step, var_allow, var_min); for (x2 = 1, val += step; x2 < 4; ++x2, val += step) elev[x2][4] = val + TopoVarianceCalc (rndfact); val = elev[4][0]; step = (elev[4][4] - val) / STEP_RANGE; rndfact = TopoVarianceFactor (step, var_allow, var_min); for (y2 = 1, val += step; y2 < 4; ++y2, val += step) elev[4][y2] = val + TopoVarianceCalc (rndfact); // fill in the rest by connecting opposing elevations // some randomness to determine which elevations to connect for (pld = fill_lines[frandom () & 3]; pld->x0 >= 0; ++pld) { int num_steps; x2 = pld->x0; y2 = pld->y0; val = elev[x2][y2]; num_steps = pld->x1 - pld->x0; if (num_steps == 0) num_steps = pld->y1 - pld->y0; step = (elev[pld->x1][pld->y1] - val) / num_steps; rndfact = TopoVarianceFactor (step, var_allow, var_min); for (x2 += pld->dx, y2 += pld->dy, val += step; x2 != pld->x1 || y2 != pld->y1; x2 += pld->dx, y2 += pld->dy, val += step) { elev[x2][y2] = val + TopoVarianceCalc (rndfact); } } // output the interpolated topography for (y2 = 0; y2 < 4; ++y2) { p = pDst + y2 * dpitch; for (x2 = 0; x2 < 4; ++x2, ++p) { int e = elev[x2][y2] >> SCALE_SHIFT; if (e > 127) e = 127; else if (e < -128) e = -128; *p = (SBYTE)e; } } // save last interpolated row to prevrow for later for (x2 = 0; x2 < 4; ++x2) prow[x2] = elev[x2][4]; } // save last row point prow[0] = elev[4][4]; } } // GenerateLightMap produces a surface light variance map for the // rotating planet by, first, transforming absolute elevation data // into normalized relative and then applying a weighted // average-median of surrounding points // Lots of pure Voodoo here ;) // the goal is a 3D illusion, not mathematically correct lighting #define LMAP_AVG_BLOCK ((MAP_HEIGHT + 4) / 5) #define LMAP_MAX_DIST ((LMAP_AVG_BLOCK + 1) >> 1) #define LMAP_WEIGHT_THRES (LMAP_MAX_DIST * 2 / 3) typedef struct { int min; int max; int avg; } elev_block_t; static inline void get_vblock_avg (elev_block_t *pblk, PSBYTE pTopo, int x, int y) { SBYTE *elev = pTopo; int y0, y1, i; int min = 127, max = -127; int avg = 0, total_weight = 0; // surface wraps around along x x = (x + MAP_WIDTH) % MAP_WIDTH; y0 = y - LMAP_MAX_DIST; y1 = y + LMAP_MAX_DIST; if (y0 < 0) y0 = 0; if (y1 > MAP_HEIGHT) y1 = MAP_HEIGHT; elev = pTopo + y0 * MAP_HEIGHT + x; for (i = y0; i < y1; ++i, elev += MAP_HEIGHT) { int delta = abs (i - y); int weight = 255; // full weight int v = *elev; if (delta >= LMAP_WEIGHT_THRES) { // too far -- progressively reduced weight weight = weight * (LMAP_MAX_DIST - delta + 1) / (LMAP_MAX_DIST - LMAP_WEIGHT_THRES + 2); } if (v > max) max = v; if (v < min) min = v; avg += pblk->avg * weight; total_weight += weight; } avg /= total_weight; pblk->min = min; pblk->max = max; pblk->avg = avg / (y1 - y0); } // See description above static void GenerateLightMap (PSBYTE pTopo, int w, int h) { #define LMAP_BLOCKS (2 * LMAP_MAX_DIST + 1) int x, y; elev_block_t vblocks[LMAP_BLOCKS]; // we use a running block average to reduce the amount of work // where a block is a vertical line of map points SBYTE *elev; int min, max, med; int sfact, spread; // normalize the topo data min = 127; max = -128; for (x = 0, elev = pTopo; x < w * h; ++x, ++elev) { int v = *elev; if (v > max) max = v; if (v < min) min = v; } med = (min + max) / 2; spread = max - med; if (spread == 0) { // perfectly smooth surface -- nothing to do but // level it out completely if (max != 0) memset (pTopo, 0, w * h); return; } // these are whatever looks right if (spread < 10) sfact = 30; // minimal spread else if (spread < 30) sfact = 60; else sfact = 100; // full spread // apply spread for (x = 0, elev = pTopo; x < w * h; ++x, ++elev) { int v = *elev; v = (v - med) * sfact / spread; *elev = v; } // compute and apply weighted averages of surrounding points for (y = 0, elev = pTopo; y < h; ++y) { elev_block_t *pblk; int i; // prime the running block average // get the minimum, maximum and avg elevation for each block for (i = -LMAP_MAX_DIST; i < LMAP_MAX_DIST; ++i) { // blocks wrap around on both sides pblk = vblocks + ((i + LMAP_BLOCKS) % LMAP_BLOCKS); get_vblock_avg (pblk, pTopo, i, y); } for (x = 0; x < w; ++x, ++elev) { int avg = 0, total_weight = 0; min = 127; max = -127; // prepare next block as we move along x pblk = vblocks + ((x + LMAP_MAX_DIST) % LMAP_BLOCKS); get_vblock_avg (pblk, pTopo, x + LMAP_MAX_DIST, y); // compute the min, max and weighted avg of blocks for (i = x - LMAP_MAX_DIST; i <= x + LMAP_MAX_DIST; ++i) { int delta = abs (i - x); int weight = 255; // full weight pblk = vblocks + ((i + LMAP_BLOCKS) % LMAP_BLOCKS); if (delta >= LMAP_WEIGHT_THRES) { // too far -- progressively reduced weight weight = weight * (LMAP_MAX_DIST - delta + 1) / (LMAP_MAX_DIST - LMAP_WEIGHT_THRES + 2); } if (pblk->max > max) max = pblk->max; if (pblk->min < min) min = pblk->min; avg += pblk->avg * weight; total_weight += weight; } avg /= total_weight; // This is mostly Voodoo // figure out what kind of relative lighting factor // to assign to this point #if 0 // relative to median med = (min + max) / 2; // median *elev = (int)*elev - med; #else // relative to median of (average, median) med = (min + max) / 2; // median med = (med + avg) / 2; *elev = (int)*elev - med; #endif } } } void GeneratePlanetMask (PPLANET_DESC pPlanetDesc, FRAME SurfDefFrame) { RECT r; DWORD old_seed; PLANDATAPTR PlanDataPtr; COUNT i, y; POINT loc; CONTEXT OldContext; PLANET_ORBIT *Orbit = &pSolarSysState->Orbit; PBYTE pScaledTopo = 0; old_seed = TFB_SeedRandom (pPlanetDesc->rand_seed); OldContext = SetContext (TaskContext); planet_orbit_init (); PlanDataPtr = &PlanData[pPlanetDesc->data_index & ~PLANET_SHIELDED]; if (SurfDefFrame) { // This is a defined planet; pixmap for the topography and // elevation data is supplied in Surface Definition frame BOOLEAN DeleteDef = FALSE; FRAME ElevFrame; // surface pixmap SurfDefFrame = SetAbsFrameIndex (SurfDefFrame, 0); if (GetFrameWidth (SurfDefFrame) != MAP_WIDTH || GetFrameHeight (SurfDefFrame) != MAP_HEIGHT) { pSolarSysState->TopoFrame = stretch_frame (SurfDefFrame, MAP_WIDTH, MAP_HEIGHT, 0); // will not need the passed FRAME anymore DeleteDef = TRUE; } else pSolarSysState->TopoFrame = SurfDefFrame; if (GetFrameCount (SurfDefFrame) > 1) { // 2nd frame is elevation data int i; BYTE* elev; ElevFrame = SetAbsFrameIndex (SurfDefFrame, 1); if (GetFrameWidth (ElevFrame) != MAP_WIDTH || GetFrameHeight (ElevFrame) != MAP_HEIGHT) { ElevFrame = stretch_frame (ElevFrame, MAP_WIDTH, MAP_HEIGHT, 0); } // grab the elevation data in 1 byte per pixel format getpixelarray (Orbit->lpTopoData, 1, ElevFrame, MAP_WIDTH, MAP_HEIGHT); // the supplied data is in unsigned format, must convert for (i = 0, elev = Orbit->lpTopoData; i < MAP_WIDTH * MAP_HEIGHT; ++i, ++elev) { *elev -= 128; } } else { // no elevation data -- planet flat as a pancake memset (Orbit->lpTopoData, 0, MAP_WIDTH * MAP_HEIGHT); } if (DeleteDef) DestroyDrawable (ReleaseDrawable (SurfDefFrame)); } else { // Generate planet surface elevation data and look r.corner.x = r.corner.y = 0; r.extent.width = MAP_WIDTH; r.extent.height = MAP_HEIGHT; { memset (Orbit->lpTopoData, 0, MAP_WIDTH * MAP_HEIGHT); switch (PLANALGO (PlanDataPtr->Type)) { case GAS_GIANT_ALGO: MakeGasGiant (PlanDataPtr->num_faults, Orbit->lpTopoData, &r, PlanDataPtr->fault_depth); break; case TOPO_ALGO: case CRATERED_ALGO: if (PlanDataPtr->num_faults) DeltaTopography (PlanDataPtr->num_faults, Orbit->lpTopoData, &r, PlanDataPtr->fault_depth); for (i = 0; i < PlanDataPtr->num_blemishes; ++i) { RECT crater_r; UWORD loword; loword = LOWORD (TFB_Random ()); switch (HIBYTE (loword) & 31) { case 0: crater_r.extent.width = (LOBYTE (loword) % (MAP_HEIGHT >> 2)) + (MAP_HEIGHT >> 2); break; case 1: case 2: case 3: case 4: crater_r.extent.width = (LOBYTE (loword) % (MAP_HEIGHT >> 3)) + (MAP_HEIGHT >> 3); break; default: crater_r.extent.width = (LOBYTE (loword) % (MAP_HEIGHT >> 4)) + 4; break; } loword = LOWORD (TFB_Random ()); crater_r.extent.height = crater_r.extent.width; crater_r.corner.x = HIBYTE (loword) % (MAP_WIDTH - crater_r.extent.width); crater_r.corner.y = LOBYTE (loword) % (MAP_HEIGHT - crater_r.extent.height); MakeCrater (&crater_r, Orbit->lpTopoData, PlanDataPtr->fault_depth << 2, -(PlanDataPtr->fault_depth << 2), FALSE); } if (PLANALGO (PlanDataPtr->Type) == CRATERED_ALGO) DitherMap (Orbit->lpTopoData); ValidateMap (Orbit->lpTopoData); break; } } pSolarSysState->TopoFrame = CaptureDrawable ( CreateDrawable (WANT_PIXMAP, (SIZE)MAP_WIDTH, (SIZE)MAP_HEIGHT, 1)); pSolarSysState->OrbitalCMap = CaptureColorMap ( LoadColorMap (PlanDataPtr->CMapInstance)); pSolarSysState->XlatRef = CaptureStringTable ( LoadStringTable (PlanDataPtr->XlatTabInstance)); if (pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature > HOT_THRESHOLD) { pSolarSysState->OrbitalCMap = SetAbsColorMapIndex ( pSolarSysState->OrbitalCMap, 2); pSolarSysState->XlatRef = SetAbsStringTableIndex ( pSolarSysState->XlatRef, 2); } else if (pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature > COLD_THRESHOLD) { pSolarSysState->OrbitalCMap = SetAbsColorMapIndex ( pSolarSysState->OrbitalCMap, 1); pSolarSysState->XlatRef = SetAbsStringTableIndex ( pSolarSysState->XlatRef, 1); } pSolarSysState->XlatPtr = GetStringAddress (pSolarSysState->XlatRef); RenderTopography (FALSE); } if (!(pPlanetDesc->data_index & PLANET_SHIELDED) && pSolarSysState->SysInfo.PlanetInfo.AtmoDensity != GAS_GIANT_ATMOSPHERE) { // produce 4x scaled topo image for IP // for the planets that we can land on pScaledTopo = HMalloc (MAP_WIDTH * 4 * MAP_HEIGHT * 4); if (pScaledTopo) { TopoScale4x (pScaledTopo, Orbit->lpTopoData, PlanDataPtr->num_faults, PlanDataPtr->fault_depth * (PLANALGO (PlanDataPtr->Type) == CRATERED_ALGO ? 2 : 1 )); TransformTopography (Orbit->TopoZoomFrame, pScaledTopo, MAP_WIDTH * 4, MAP_HEIGHT * 4); HFree (pScaledTopo); } } // Generate a pixel array from the Topography map. // We use this instead of lpTopoData because it needs to be // WAP_WIDTH+SPHERE_SPAN_X wide and we need this method for Earth anyway. // It may be more efficient to build it from lpTopoData instead of the // FRAMPTR though. getpixelarray (Orbit->lpTopoMap, 4, pSolarSysState->TopoFrame, MAP_WIDTH + SPHERE_SPAN_X, MAP_HEIGHT); // Extend the width from MAP_WIDTH to MAP_WIDTH+SPHERE_SPAN_X for (y = 0; y < MAP_HEIGHT * (MAP_WIDTH + SPHERE_SPAN_X); y += MAP_WIDTH + SPHERE_SPAN_X) memcpy (Orbit->lpTopoMap + y + MAP_WIDTH, Orbit->lpTopoMap + y, SPHERE_SPAN_X * sizeof (Orbit->lpTopoMap[0])); if (PLANALGO (PlanDataPtr->Type) != GAS_GIANT_ALGO) { // convert topo data to a light map, based on relative // map point elevations GenerateLightMap (Orbit->lpTopoData, MAP_WIDTH, MAP_HEIGHT); } else { // gas giants are pretty much flat memset (Orbit->lpTopoData, 0, MAP_WIDTH * MAP_HEIGHT); } if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->SunDesc[0]) { // this is a planet -- get its location loc = pSolarSysState->pOrbitalDesc->location; } else { // this is a moon -- get its planet's location loc = pSolarSysState->pOrbitalDesc->pPrevDesc->location; } RenderPhongMask (loc); if (pPlanetDesc->data_index & PLANET_SHIELDED) { Orbit->ObjectFrame = CreateShieldMask (); ApplyShieldTint (); } SetContext (OldContext); TFB_SeedRandom (old_seed); } int rotate_planet_task (void *data) { Task task = (Task) data; SIZE spin_dir; COORD init_x; DWORD TimeIn; PSOLARSYS_STATE pSS; BOOLEAN zooming; RECT r, *repair = &r; UBYTE zoom_from; COUNT zoom_arr[50]; COUNT zoom_amt, frame_num = 0, zoom_frames; PLANET_ORBIT *Orbit; FRAME OldShieldFrame = 0; FRAME ShieldFrame = 0; BOOLEAN doThrob = FALSE; COUNT altfi; // alternating frame index r.extent.width = 0; zooming = TRUE; pSS = pSolarSysState; while (*(volatile SIZE *)&pSS->MenuState.Initialized < 2 && !Task_ReadState (task, TASK_EXIT)) TaskSwitch (); SetPlanetTilt (pSS->SysInfo.PlanetInfo.AxialTilt); Orbit = &pSolarSysState->Orbit; spin_dir = 1 - ((pSS->SysInfo.PlanetInfo.AxialTilt & 1) << 1); init_x = (spin_dir == 1) ? (0) : (MAP_WIDTH - 1); altfi = 0; if (optWhichShield == OPT_3DO && pSolarSysState->pOrbitalDesc->data_index & PLANET_SHIELDED) { // prepare the shield throb effect doThrob = TRUE; OldShieldFrame = Orbit->ObjectFrame; ShieldFrame = CaptureDrawable ( CreateDrawable (WANT_PIXMAP | WANT_ALPHA, GetFrameWidth (OldShieldFrame), GetFrameHeight (OldShieldFrame), 2)); SetShieldThrobEffect (OldShieldFrame, init_x, ShieldFrame); } // Render the first planet frame RenderLevelMasks (Orbit->PlanetFrameArray, init_x, doThrob); zoom_from = (UBYTE)TFB_Random () & 0x03; zoom_frames = init_zoom_array (zoom_arr); zoom_amt = zoom_arr[frame_num]; // Disable zooming when already in orbit if (LastActivity & CHECK_LOAD) zoom_amt = 0; TimeIn = GetTimeCounter (); while (!Task_ReadState (task, TASK_EXIT)) { BYTE view_index; COORD x; x = init_x; view_index = MAP_WIDTH; do { // This lock was placed before the RotatePlanet call // To prevent the thread from being interrupted by the flash // task while computing the Planet Frame. This should help // to smooth out the planet rotation animation. // The PauseRotate needs to be placed after the lock, // to guarantee that PauseRotate doesn't change while waiting // to acquire the graphics lock LockMutex (GraphicsLock); if (*(volatile UBYTE *)&pSS->PauseRotate != 1 // if (((PSOLARSYS_STATE volatile)pSS)->MenuState.Initialized <= 3 && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) { //PauseRotate == 2 is a single-step if (*(volatile UBYTE *)&pSS->PauseRotate == 2) pSS->PauseRotate = 1; // go to the next frame Orbit->PlanetFrameArray = SetAbsFrameIndex ( Orbit->PlanetFrameArray, altfi); if (doThrob) { Orbit->ObjectFrame = SetAbsFrameIndex ( ShieldFrame, altfi); } repair = RotatePlanet (x, SIS_SCREEN_WIDTH >> 1, (148 - SIS_ORG_Y) >> 1, zoom_amt, zoom_from, repair); if (!repair && zooming) { zooming = FALSE; zoom_amt = 0; ++pSS->MenuState.Initialized; } x += spin_dir; } else view_index++; UnlockMutex (GraphicsLock); // Generate the next rotation frame altfi ^= 1; RenderLevelMasks (SetAbsFrameIndex (Orbit->PlanetFrameArray, altfi), x, doThrob); if (doThrob) { // prepare next throb frame SetShieldThrobEffect (OldShieldFrame, x, SetAbsFrameIndex (ShieldFrame, altfi)); } if (zooming) { frame_num++; if (frame_num > zoom_frames) { log_add (log_Warning, "rotate_planet_task() : zoom frame" " out of bounds!"); frame_num = zoom_frames; } zoom_amt = zoom_arr[frame_num]; } SleepThreadUntil (TimeIn + (ONE_SECOND * ROTATION_TIME) / (MAP_WIDTH)); TimeIn = GetTimeCounter (); } while (--view_index && !Task_ReadState (task, TASK_EXIT)); } if (OldShieldFrame) { Orbit->ObjectFrame = OldShieldFrame; DestroyDrawable (ReleaseDrawable (ShieldFrame)); } FinishTask (task); return 0; } uqm-0.6.2/sc2/src/sc2code/planets/genorz.c0000600000175000017500000002616310543202077016735 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "lander.h" #include "nameref.h" #include "resinst.h" #include "setup.h" #include "state.h" #include "sounds.h" #include "planets/genall.h" #include "libs/mathlib.h" static void GenerateAndrosynth (BYTE control) { switch (control) { case GENERATE_ENERGY: { DWORD rand_val, old_rand; if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[1]) { COUNT i, which_node; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 0; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i)) { pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] &= ~(1L << i); /* so won't get freed in lander.c */ CaptureStringTable (GetStringTable ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString )); if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << (i + 16)))) { SET_GAME_STATE (PLANETARY_CHANGE, 1); pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] |= (1L << (i + 16)); if (pSolarSysState->SysInfo.PlanetInfo.DiscoveryString) { PPLANETSIDE_DESC pPSD; pPSD = (PPLANETSIDE_DESC)pMenuState->ModuleFrame; UnbatchGraphics (); DoDiscoveryReport (MenuSounds); BatchGraphics (); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetRelStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 1 ); if (GetStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString ) == 0) /* so will get freed in lander.c */ ReleaseStringTable ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString ); } } } if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; } case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[1].data_index = TELLURIC_WORLD; pSolarSysState->PlanetDesc[1].radius = EARTH_RADIUS * 204L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[1].location.x, pSolarSysState->PlanetDesc[1].location.y ); pSolarSysState->PlanetDesc[1].location.x = COSINE (angle, pSolarSysState->PlanetDesc[1].radius); pSolarSysState->PlanetDesc[1].location.y = SINE (angle, pSolarSysState->PlanetDesc[1].radius); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[1]) { UWORD retval; LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (ANDROSYNTH_RUINS_STRTAB) ); retval = HIWORD ( pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] ); while (retval) { if (retval & 1) { pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = SetRelStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString, 1 ); if (GetStringTableIndex ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString ) == 0) { DestroyStringTable (ReleaseStringTable ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString )); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = 0; } } retval >>= 1; } } GenerateRandomIP (GENERATE_ORBITAL); if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[1]) { pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = EARTH_ATMOSPHERE * 144 / 100; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 28; pSolarSysState->SysInfo.PlanetInfo.Weather = 1; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; } break; default: GenerateRandomIP (control); break; } } void GenerateOrz (BYTE control) { if (CurStarDescPtr->Index == ANDROSYNTH_DEFINED) { GenerateAndrosynth (control); return; } switch (control) { case GENERATE_ENERGY: { DWORD rand_val, old_rand; if (CurStarDescPtr->Index != ORZ_DEFINED && pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[1] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[2] && !GET_GAME_STATE (TAALO_PROTECTOR)) { old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; pSolarSysState->SysInfo.PlanetInfo.CurType = 0; if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; else { pSolarSysState->CurNode = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { SET_GAME_STATE (TAALO_PROTECTOR, 1); SET_GAME_STATE (TAALO_PROTECTOR_ON_SHIP, 1); } } TFB_SeedRandom (old_rand); break; } else if (CurStarDescPtr->Index == ORZ_DEFINED && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i, which_node; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; } case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); if (CurStarDescPtr->Index == ORZ_DEFINED) { pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 156L / 100; pSolarSysState->PlanetDesc[0].NumPlanets = 0; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); } break; } case GENERATE_ORBITAL: if ((CurStarDescPtr->Index == ORZ_DEFINED && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) || (CurStarDescPtr->Index == TAALO_PROTECTOR_DEFINED && pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[1] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[2] && !GET_GAME_STATE (TAALO_PROTECTOR))) { COUNT i; if ((CurStarDescPtr->Index == ORZ_DEFINED || !GET_GAME_STATE (TAALO_UNPROTECTED)) && ActivateStarShip (ORZ_SHIP, SPHERE_TRACKING)) { NotifyOthers (ORZ_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); if (CurStarDescPtr->Index == ORZ_DEFINED) { CloneShipFragment (ORZ_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); } else { for (i = 0; i < 14; ++i) CloneShipFragment (ORZ_SHIP, &GLOBAL (npc_built_ship_q), 0); SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); } pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; InitCommunication (ORZ_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) break; else { BOOLEAN OrzSurvivors; OrzSurvivors = GetHeadLink (&GLOBAL (npc_built_ship_q)) && (CurStarDescPtr->Index == ORZ_DEFINED || !GET_GAME_STATE (TAALO_UNPROTECTED)); GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); if (OrzSurvivors) break; LockMutex (GraphicsLock); RepairSISBorder (); UnlockMutex (GraphicsLock); } } SET_GAME_STATE (TAALO_UNPROTECTED, 1); if (CurStarDescPtr->Index == TAALO_PROTECTOR_DEFINED) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (TAALO_DEVICE_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (TAALO_DEVICE_STRTAB) ); } else { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (RUINS_STRTAB) ); } } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/genvux.c0000600000175000017500000002443410543202100016727 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "lander.h" #include "lifeform.h" #include "nameref.h" #include "resinst.h" #include "setup.h" #include "state.h" #include "sounds.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateVUX (BYTE control) { DWORD rand_val; switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0] && CurStarDescPtr->Index != VUX_BEAST_DEFINED) { if (CurStarDescPtr->Index == MAIDENS_DEFINED && !GET_GAME_STATE (SHOFIXTI_MAIDENS)) { pSolarSysState->SysInfo.PlanetInfo.CurPt.x = MAP_WIDTH / 3; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = MAP_HEIGHT * 5 / 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; pSolarSysState->SysInfo.PlanetInfo.CurType = 0; if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; else { pSolarSysState->CurNode = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { SET_GAME_STATE (SHOFIXTI_MAIDENS, 1); SET_GAME_STATE (MAIDENS_ON_SHIP, 1); } } break; } else if (CurStarDescPtr->Index == VUX_DEFINED) { COUNT i, which_node; DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); if (CurStarDescPtr->Index == MAIDENS_DEFINED) { GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = REDUX_WORLD; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 212L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); } else { if (CurStarDescPtr->Index == VUX_DEFINED) { pSolarSysState->PlanetDesc[0].data_index = REDUX_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 1; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 42L / 100; angle = HALF_CIRCLE + OCTANT; } else /* if (CurStarDescPtr->Index == VUX_BEAST_DEFINED) */ { memmove (&pSolarSysState->PlanetDesc[1], &pSolarSysState->PlanetDesc[0], sizeof (pSolarSysState->PlanetDesc[0]) * pSolarSysState->SunDesc[0].NumPlanets); ++pSolarSysState->SunDesc[0].NumPlanets; angle = HALF_CIRCLE - OCTANT; pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 110L / 100; pSolarSysState->PlanetDesc[0].NumPlanets = 0; } pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].rand_seed = MAKE_DWORD ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); } break; } case GENERATE_ORBITAL: { if ((pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0] && (CurStarDescPtr->Index == VUX_DEFINED || (CurStarDescPtr->Index == MAIDENS_DEFINED && !GET_GAME_STATE (ZEX_IS_DEAD)))) && ActivateStarShip (VUX_SHIP, SPHERE_TRACKING)) { NotifyOthers (VUX_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (VUX_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); if (CurStarDescPtr->Index == VUX_DEFINED) { SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); } else { SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); } pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; InitCommunication (VUX_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) break; else { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); if (CurStarDescPtr->Index == VUX_DEFINED || !GET_GAME_STATE (ZEX_IS_DEAD)) break; LockMutex (GraphicsLock); RepairSISBorder (); UnlockMutex (GraphicsLock); } } if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { if (CurStarDescPtr->Index == MAIDENS_DEFINED) { if (!GET_GAME_STATE (SHOFIXTI_MAIDENS)) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (MAIDENS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (MAIDENS_STRTAB) ); } } else if (CurStarDescPtr->Index == VUX_BEAST_DEFINED) { if (!GET_GAME_STATE (VUX_BEAST)) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = 0; pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (BEAST_STRTAB) ); } } else { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (RUINS_STRTAB) ); } } GenerateRandomIP (GENERATE_ORBITAL); if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { pSolarSysState->SysInfo.PlanetInfo.Weather = 2; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; } break; } case GENERATE_LIFE: if (CurStarDescPtr->Index == MAIDENS_DEFINED && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i; DWORD old_rand; old_rand = TFB_SeedRandom (pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]); i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; if (i < 4) pSolarSysState->SysInfo.PlanetInfo.CurType = 9; else if (i < 8) pSolarSysState->SysInfo.PlanetInfo.CurType = 14; else /* if (i < 12) */ pSolarSysState->SysInfo.PlanetInfo.CurType = 18; if (i >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] & (1L << i))) break; } while (++i < 12); pSolarSysState->CurNode = i; TFB_SeedRandom (old_rand); break; } else if (CurStarDescPtr->Index == VUX_BEAST_DEFINED && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i; DWORD old_rand; old_rand = TFB_SeedRandom (pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]); i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; if (i == 0) pSolarSysState->SysInfo.PlanetInfo.CurType = NUM_CREATURE_TYPES + 2; else if (i <= 5) /* {SPEED_MOTIONLESS | DANGER_NORMAL, MAKE_BYTE (5, 3)}, */ pSolarSysState->SysInfo.PlanetInfo.CurType = 3; else /* if (i <= 10) */ /* {BEHAVIOR_UNPREDICTABLE | SPEED_SLOW | DANGER_NORMAL, MAKE_BYTE (3, 8)}, */ pSolarSysState->SysInfo.PlanetInfo.CurType = 8; if (i >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] & (1L << i))) break; else if (i == 0 && (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] & (1L << i)) && !GET_GAME_STATE (VUX_BEAST)) { PPLANETSIDE_DESC pPSD; pPSD = (PPLANETSIDE_DESC)pMenuState->ModuleFrame; UnbatchGraphics (); DoDiscoveryReport (MenuSounds); BatchGraphics (); pPSD->InTransit = TRUE; SET_GAME_STATE (VUX_BEAST, 1); SET_GAME_STATE (VUX_BEAST_ON_SHIP, 1); } } while (++i < 11); pSolarSysState->CurNode = i; TFB_SeedRandom (old_rand); break; } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/elemdata.h0000600000175000017500000000634710543202100017177 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _ELEMDATA_H #define _ELEMDATA_H #include "libs/compiler.h" /*------------------------------ Type Defines ----------------------------- */ enum { COMMON = 0, CORROSIVE, BASE_METAL, NOBLE, RARE_EARTH, PRECIOUS, RADIOACTIVE, EXOTIC, NUM_ELEMENT_CATEGORIES }; #define ElementCategory(et) (Elements[et] & 0x7) /*------------------------------ Global Data ------------------------------ */ enum { HYDROGEN, HELIUM, LITHIUM, BERYLLIUM, BORON, CARBON, NITROGEN, OXYGEN, FLUORINE, NEON, SODIUM, MAGNESIUM, ALUMINUM, SILICON, PHOSPHORUS, SULFUR, CHLORINE, ARGON, POTASSIUM, CALCIUM, SCANDIUM, TITANIUM, VANADIUM, CHROMIUM, MANGANESE, IRON, COBALT, NICKEL, COPPER, ZINC, GALLIUM, GERMANIUM, ARSENIC, SELENIUM, BROMINE, KRYPTON, RUBIDIUM, STRONTIUM, YTTRIUM, ZIRCONIUM, NIOBIUM, MOLYBDENUM, TECHNETIUM, RUTHENIUM, RHODIUM, PALLADIUM, SILVER, CADMIUM, INDIUM, TIN, ANTIMONY, TELLURIUM, IODINE, XENON, CESIUM, BARIUM, LANTHANUM, CERIUM, PRASEODYMIUM, NEODYMIUM, PROMETHIUM, SAMARIUM, EUROPIUM, GADOLINIUM, TERBIUM, DYPROSIUM, HOLMIUM, ERBIUM, THULIUM, YTTERBIUM, LUTETIUM, HAFNIUM, TANTALUM, TUNGSTEN, RHENIUM, OSMIUM, IRIDIUM, PLATINUM, GOLD, MERCURY, THALLIUM, LEAD, BISMUTH, POLONIUM, ASTATINE, RADON, FRANCIUM, RADIUM, ACTINIUM, THORIUM, PROTACTINIUM, URANIUM, NEPTUNIUM, PLUTONIUM, NUMBER_OF_NORMAL, OZONE = NUMBER_OF_NORMAL, FREE_RADICALS, CARBON_DIOXIDE, CARBON_MONOXIDE, AMMONIA, METHANE, SULFURIC_ACID, HYDROCHLORIC_ACID, HYDROCYANIC_ACID, FORMIC_ACID, PHOSPHORIC_ACID, FORMALDEHYDE, CYANOACETYLENE, METHANOL, ETHANOL, SILICON_MONOXIDE, TITANIUM_OXIDE, ZIRCONIUM_OXIDE, WATER, SILICON_COMPOUNDS, METAL_OXIDES, QUANTUM_BH, NEUTRONIUM, MAGNETIC_MONOPOLES, DEGENERATE_MATTER, RT_SUPER_FLUID, AGUUTI_NODULES, IRON_COMPOUNDS, ALUMINUM_COMPOUNDS, NITROUS_OXIDE, RADIOACTIVE_COMPOUNDS, HYDROCARBONS, CARBON_COMPOUNDS, ANTIMATTER, CHARON_DUST, REISBURG_HELICES, TZO_CRYSTALS, CALCIUM_COMPOUNDS, NITRIC_ACID, NUMBER_OF_ELEMENTS }; #define NUMBER_OF_SPECIAL (NUMBER_OF_ELEMENTS - NUMBER_OF_NORMAL) #define CHANCE_MASK ((1 << 2) - 1) #define FEW 1 #define MODERATE 4 #define NUMEROUS 8 enum { LIGHT = 0, MEDIUM, HEAVY }; #define NOTHING (BYTE)(~0) #define MINERAL_DEPOSIT(qn,ql) MAKE_BYTE (qn, ql) #define DEPOSIT_QUANTITY(md) LONIBBLE (md) #define DEPOSIT_QUALITY(md) HINIBBLE (md) #define MAX_ELEMENT_UNITS 0xF extern const BYTE *Elements; #endif /* _ELEMDATA_H */ uqm-0.6.2/sc2/src/sc2code/planets/gensyr.c0000600000175000017500000000705510543202100016722 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "encount.h" #include "resinst.h" #include "planets/genall.h" static void GenerateTrap (BYTE control) { switch (control) { case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = TELLURIC_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 1; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 203L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: GenerateRandomIP (GENERATE_ORBITAL); if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = EARTH_ATMOSPHERE * 2; pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 35; pSolarSysState->SysInfo.PlanetInfo.Weather = 3; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; } break; default: GenerateRandomIP (control); break; } } void GenerateSyreen (BYTE control) { if (CurStarDescPtr->Index == MYCON_TRAP_DEFINED) { GenerateTrap (control); return; } switch (control) { case GENERATE_MOONS: GenerateRandomIP (GENERATE_MOONS); if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[0]) { pSolarSysState->MoonDesc[0].data_index = (BYTE)~0; pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS; pSolarSysState->MoonDesc[0].location.x = COSINE (QUADRANT, pSolarSysState->MoonDesc[0].radius); pSolarSysState->MoonDesc[0].location.y = SINE (QUADRANT, pSolarSysState->MoonDesc[0].radius); } break; case GENERATE_PLANETS: { GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD | PLANET_SHIELDED; pSolarSysState->PlanetDesc[0].NumPlanets = 1; break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { GenerateRandomIP (GENERATE_ORBITAL); pSolarSysState->SysInfo.PlanetInfo.SurfaceTemperature = 19; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; pSolarSysState->SysInfo.PlanetInfo.Weather = 0; pSolarSysState->SysInfo.PlanetInfo.AtmoDensity = EARTH_ATMOSPHERE * 9 / 10; break; } /* Starbase */ else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) { pSolarSysState->MenuState.Initialized += 2; InitCommunication (SYREEN_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; break; } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/genshof.c0000600000175000017500000000626210543202100017043 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "globdata.h" #include "state.h" #include "planets/genall.h" static void check_old_shofixti (void) { HSTARSHIP hStarShip; if (GLOBAL (BattleGroupRef) && (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q))) && GET_GAME_STATE (SHOFIXTI_RECRUITED)) { BYTE task; SHIP_FRAGMENTPTR FragPtr; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); task = GET_GROUP_MISSION (FragPtr); SET_GROUP_MISSION (FragPtr, FLEE | IGNORE_FLAGSHIP | (task & REFORM_GROUP)); SET_GROUP_DEST (FragPtr, 0); UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } } void GenerateShofixti (BYTE control) { switch (control) { case INIT_NPCS: if (!GET_GAME_STATE (SHOFIXTI_RECRUITED) && (!GET_GAME_STATE (SHOFIXTI_KIA) || (!GET_GAME_STATE (SHOFIXTI_BRO_KIA) && GET_GAME_STATE (MAIDENS_ON_SHIP)))) { GLOBAL (BattleGroupRef) = GET_GAME_STATE_32 (SHOFIXTI_GRPOFFS0); if (GLOBAL (BattleGroupRef) == 0 || !GetGroupInfo (GLOBAL (BattleGroupRef), GROUP_INIT_IP)) { if (GLOBAL (BattleGroupRef) == 0) GLOBAL (BattleGroupRef) = ~0L; CloneShipFragment (SHOFIXTI_SHIP, &GLOBAL (npc_built_ship_q), 1); GLOBAL (BattleGroupRef) = PutGroupInfo ( GLOBAL (BattleGroupRef), 1); SET_GAME_STATE_32 (SHOFIXTI_GRPOFFS0, GLOBAL (BattleGroupRef)); } } case REINIT_NPCS: GenerateRandomIP (control); check_old_shofixti (); break; case UNINIT_NPCS: if (GLOBAL (BattleGroupRef) && !GET_GAME_STATE (SHOFIXTI_RECRUITED) && GetHeadLink (&GLOBAL (npc_built_ship_q)) == 0) { if (!GET_GAME_STATE (SHOFIXTI_KIA)) { SET_GAME_STATE (SHOFIXTI_KIA, 1); SET_GAME_STATE (SHOFIXTI_VISITS, 0); } else if (GET_GAME_STATE (MAIDENS_ON_SHIP)) { SET_GAME_STATE (SHOFIXTI_BRO_KIA, 1); } } GenerateRandomIP (UNINIT_NPCS); break; case GENERATE_PLANETS: { COUNT i; PPLANET_DESC pCurDesc; #define NUM_PLANETS 6 pSolarSysState->SunDesc[0].NumPlanets = NUM_PLANETS; for (i = 0, pCurDesc = pSolarSysState->PlanetDesc; i < NUM_PLANETS; ++i, ++pCurDesc) { pCurDesc->NumPlanets = 0; if (i < (NUM_PLANETS >> 1)) pCurDesc->data_index = SELENIC_WORLD; else pCurDesc->data_index = METAL_WORLD; } FillOrbits (pSolarSysState, NUM_PLANETS, &pSolarSysState->PlanetDesc[0], TRUE); break; } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/gensam.c0000600000175000017500000002026110543202100016657 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "resinst.h" #include "races.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" static void BuildUrquanGuard (void) { BYTE ship1, ship2; BYTE b0, b1; POINT org; HSTARSHIP hStarShip, hNextShip; GLOBAL (BattleGroupRef) = GET_GAME_STATE_32 (SAMATRA_GRPOFFS0); if (!GET_GAME_STATE (KOHR_AH_FRENZY)) ship1 = URQUAN_SHIP, ship2 = BLACK_URQUAN_SHIP; else ship1 = BLACK_URQUAN_SHIP, ship2 = URQUAN_SHIP; for (b0 = 0; b0 < MAX_SHIPS_PER_SIDE; ++b0) CloneShipFragment (ship1, &GLOBAL (npc_built_ship_q), 0); if (GLOBAL (BattleGroupRef) == 0) { GLOBAL (BattleGroupRef) = PutGroupInfo (GROUPS_ADD_NEW, 1); SET_GAME_STATE_32 (SAMATRA_GRPOFFS0, GLOBAL (BattleGroupRef)); } #define NUM_URQUAN_GUARDS0 12 for (b0 = 1; b0 <= NUM_URQUAN_GUARDS0; ++b0) PutGroupInfo (GLOBAL (BattleGroupRef), b0); ReinitQueue (&GLOBAL (npc_built_ship_q)); for (b0 = 0; b0 < MAX_SHIPS_PER_SIDE; ++b0) CloneShipFragment (ship2, &GLOBAL (npc_built_ship_q), 0); #define NUM_URQUAN_GUARDS1 4 for (b0 = 1; b0 <= NUM_URQUAN_GUARDS1; ++b0) PutGroupInfo (GLOBAL (BattleGroupRef), (BYTE)(NUM_URQUAN_GUARDS0 + b0)); GetGroupInfo (GLOBAL (BattleGroupRef), GROUP_INIT_IP); XFormIPLoc ( &pSolarSysState->PlanetDesc[4].image.origin, &org, FALSE ); hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); for (b0 = 0, b1 = 0; b0 < NUM_URQUAN_GUARDS0; ++b0, b1 += FULL_CIRCLE / (NUM_URQUAN_GUARDS0 + NUM_URQUAN_GUARDS1)) { SHIP_FRAGMENTPTR FragPtr; if (b1 % (FULL_CIRCLE / NUM_URQUAN_GUARDS1) == 0) b1 += FULL_CIRCLE / (NUM_URQUAN_GUARDS0 + NUM_URQUAN_GUARDS1); FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); hNextShip = _GetSuccLink (FragPtr); SET_GROUP_MISSION (FragPtr, ON_STATION | IGNORE_FLAGSHIP); SET_GROUP_LOC (FragPtr, 0); SET_GROUP_DEST (FragPtr, 4 + 1); SET_ORBIT_LOC (FragPtr, NORMALIZE_FACING (ANGLE_TO_FACING (b1))); FragPtr->ShipInfo.group_counter = 0; FragPtr->ShipInfo.loc.x = org.x + COSINE (b1, STATION_RADIUS); FragPtr->ShipInfo.loc.y = org.y + SINE (b1, STATION_RADIUS); UnlockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); hStarShip = hNextShip; } for (b0 = 0, b1 = 0; b0 < NUM_URQUAN_GUARDS1; ++b0, b1 += FULL_CIRCLE / NUM_URQUAN_GUARDS1) { SHIP_FRAGMENTPTR FragPtr; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); hNextShip = _GetSuccLink (FragPtr); SET_GROUP_MISSION (FragPtr, ON_STATION | IGNORE_FLAGSHIP); SET_GROUP_LOC (FragPtr, 0); SET_GROUP_DEST (FragPtr, 4 + 1); SET_ORBIT_LOC (FragPtr, NORMALIZE_FACING (ANGLE_TO_FACING (b1))); FragPtr->ShipInfo.group_counter = 0; FragPtr->ShipInfo.loc.x = org.x + COSINE (b1, STATION_RADIUS); FragPtr->ShipInfo.loc.y = org.y + SINE (b1, STATION_RADIUS); UnlockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); hStarShip = hNextShip; } } void GenerateSamatra (BYTE control) { switch (control) { case INIT_NPCS: if (!GET_GAME_STATE (URQUAN_MESSED_UP)) BuildUrquanGuard (); else { // Exorcise Ur-Quan ghosts upon system reentry PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); // wipe out the group } break; case REINIT_NPCS: GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); EncounterGroup = 0; EncounterRace = -1; // Do not want guards to chase the player { BOOLEAN GuardEngaged; HSTARSHIP hStarShip, hNextShip; GuardEngaged = FALSE; for (hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); hStarShip; hStarShip = hNextShip) { BYTE task; SHIP_FRAGMENTPTR FragPtr; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); hNextShip = _GetSuccLink (FragPtr); task = GET_GROUP_MISSION (FragPtr); if (GET_GAME_STATE (URQUAN_MESSED_UP)) { SET_GROUP_MISSION (FragPtr, FLEE | IGNORE_FLAGSHIP | (task & REFORM_GROUP)); SET_GROUP_DEST (FragPtr, 0); } else if (task & REFORM_GROUP) { task &= ~REFORM_GROUP; FragPtr->ShipInfo.group_counter = 0; SET_GROUP_MISSION (FragPtr, task); GuardEngaged = TRUE; } UnlockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); } if (GuardEngaged) { COUNT angle; POINT org; XFormIPLoc ( &pSolarSysState->PlanetDesc[4].image.origin, &org, FALSE ); angle = ARCTAN ( GLOBAL (ip_location.x) - org.x, GLOBAL (ip_location.y) - org.y ); GLOBAL (ip_location.x) = org.x + COSINE (angle, 3000); GLOBAL (ip_location.y) = org.y + SINE (angle, 3000); XFormIPLoc ( &GLOBAL (ip_location), &GLOBAL (ShipStamp.origin), TRUE ); } } break; case GENERATE_MOONS: GenerateRandomIP (GENERATE_MOONS); if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[4]) { COUNT angle; DWORD rand_val; pSolarSysState->MoonDesc[0].data_index = (BYTE)(~0 - 1); pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS + (2 * MOON_DELTA); rand_val = TFB_Random (); angle = NORMALIZE_ANGLE (LOWORD (rand_val)); pSolarSysState->MoonDesc[0].location.x = COSINE (angle, pSolarSysState->MoonDesc[0].radius); pSolarSysState->MoonDesc[0].location.y = SINE (angle, pSolarSysState->MoonDesc[0].radius); } break; case GENERATE_PLANETS: GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[4].NumPlanets = 1; break; case GENERATE_ORBITAL: /* Samatra */ if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[4] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) { PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); if (!GET_GAME_STATE (URQUAN_MESSED_UP)) CloneShipFragment (!GET_GAME_STATE (KOHR_AH_FRENZY) ? URQUAN_SHIP : BLACK_URQUAN_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); else { #define URQUAN_REMNANTS 3 BYTE i; for (i = 0; i < URQUAN_REMNANTS; ++i) { CloneShipFragment (URQUAN_SHIP, &GLOBAL (npc_built_ship_q), 0); CloneShipFragment (BLACK_URQUAN_SHIP, &GLOBAL (npc_built_ship_q), 0); } } pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); SET_GAME_STATE (URQUAN_PROTECTING_SAMATRA, 1); InitCommunication (URQUAN_CONVERSATION); if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { BOOLEAN UrquanSurvivors; UrquanSurvivors = GetHeadLink ( &GLOBAL (npc_built_ship_q) ) != 0; GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); if (UrquanSurvivors) { SET_GAME_STATE (URQUAN_PROTECTING_SAMATRA, 0); } else { EncounterGroup = 0; EncounterRace = -1; GLOBAL (CurrentActivity) = IN_LAST_BATTLE | START_ENCOUNTER; if (GET_GAME_STATE (YEHAT_CIVIL_WAR) && ActivateStarShip (YEHAT_SHIP, SPHERE_TRACKING) && ActivateStarShip (YEHAT_REBEL_SHIP, FEASIBILITY_STUDY)) InitCommunication (YEHAT_REBEL_CONVERSATION); } } pSolarSysState->MenuState.Initialized -= 2; break; } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/report.c0000600000175000017500000001540110543202100016720 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "colors.h" #include "controls.h" #include "gamestr.h" #include "options.h" #include "setup.h" #include "sounds.h" #include "planets/lander.h" #include "planets/planets.h" #include "uqmdebug.h" #include "libs/inplib.h" #include #include #define NUM_CELL_COLS MAP_WIDTH / 6 #define NUM_CELL_ROWS MAP_HEIGHT / 6 #define MAX_CELL_COLS 40 extern FRAME SpaceJunkFrame; static void ClearReportArea (void) { COUNT x, y; RECT r; STAMP s; COORD startx; if (optWhichFonts == OPT_PC) s.frame = SetAbsFrameIndex (SpaceJunkFrame, 21); else s.frame = SetAbsFrameIndex (SpaceJunkFrame, 18); GetFrameRect (s.frame, &r); BatchGraphics (); SetContextBackGroundColor (BLACK_COLOR); ClearDrawable (); SetContextClipping (FALSE); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x07, 0x00), 0x57)); startx = 1 + (r.extent.width >> 1) - 1; s.origin.y = 1; for (y = 0; y < NUM_CELL_ROWS; ++y) { s.origin.x = startx; for (x = 0; x < NUM_CELL_COLS; ++x) { if (optWhichFonts == OPT_PC) DrawStamp (&s); else DrawFilledStamp (&s); s.origin.x += r.extent.width + 1; } s.origin.y += r.extent.height + 1; } SetContextClipping (TRUE); UnbatchGraphics (); } static void MakeReport (SOUND ReadOutSounds, UNICODE *pStr, COUNT StrLen) { BYTE ButtonState; int end_page_len; UNICODE end_page_buf[200]; wchar_t last_c; COUNT row_cells; BOOLEAN Sleepy; RECT r; TEXT t; sprintf (end_page_buf, "%s\n", GAME_STRING (SCAN_STRING_BASE + NUM_SCAN_TYPES)); end_page_len = utf8StringCount (end_page_buf); GetFrameRect (SetAbsFrameIndex (SpaceJunkFrame, 18), &r); t.align = ALIGN_LEFT; t.CharCount = 1; t.pStr = pStr; Sleepy = TRUE; UnlockMutex (GraphicsLock); FlushInput (); // XXX: this is a pretty ugly goto goto InitPageCell; while (StrLen) { COUNT col_cells; const UNICODE *pLastStr; const UNICODE *pNextStr; COUNT lf_pos; pLastStr = t.pStr; // scan for LFs in the remaining string // trailing LF will be ignored for (lf_pos = StrLen, pNextStr = t.pStr; lf_pos && getCharFromString (&pNextStr) != '\n'; --lf_pos) ; col_cells = 0; // check if the remaining text fits on current screen if (row_cells == NUM_CELL_ROWS - 1 && (StrLen > NUM_CELL_COLS || lf_pos > 1)) { col_cells = (NUM_CELL_COLS >> 1) - (end_page_len >> 1); t.pStr = end_page_buf; StrLen += end_page_len; } t.baseline.x = 1 + (r.extent.width >> 1) + (col_cells * (r.extent.width + 1)) - 1; do { COUNT word_chars; const UNICODE *pStr; wchar_t c; pStr = t.pStr; pNextStr = t.pStr; while (isWideGraphChar (getCharFromString (&pNextStr))) pStr = pNextStr; word_chars = utf8StringCountN (t.pStr, pStr); if ((col_cells += word_chars) <= NUM_CELL_COLS) { DWORD TimeOut; if (StrLen -= word_chars) --StrLen; TimeOut = GetTimeCounter (); while (word_chars--) { pNextStr = t.pStr; c = getCharFromString (&pNextStr); if (!Sleepy || (GLOBAL (CurrentActivity) & CHECK_ABORT)) font_DrawText (&t); else { LockMutex (GraphicsLock); font_DrawText (&t); UnlockMutex (GraphicsLock); PlaySound (ReadOutSounds, NotPositional (), NULL, GAME_SOUND_PRIORITY); if (c == ',') TimeOut += ONE_SECOND / 4; if (c == '.' || c == '!' || c == '?') TimeOut += ONE_SECOND / 2; else TimeOut += ONE_SECOND / 20; if (word_chars == 0) TimeOut += ONE_SECOND / 20; TaskSwitch (); while (GetTimeCounter () < TimeOut) { if (ButtonState) { if (!AnyButtonPress (TRUE)) ButtonState = 0; } else if (AnyButtonPress (TRUE)) { Sleepy = FALSE; LockMutex (GraphicsLock); BatchGraphics (); break; } TaskSwitch(); } } t.pStr = pNextStr; t.baseline.x += r.extent.width + 1; } ++col_cells; last_c = getCharFromString (&t.pStr); t.baseline.x += r.extent.width + 1; } } while (col_cells <= NUM_CELL_COLS && last_c != '\n' && StrLen); t.baseline.y += r.extent.height + 1; if (++row_cells == NUM_CELL_ROWS || StrLen == 0) { t.pStr = pLastStr; if (!Sleepy) { UnbatchGraphics (); UnlockMutex (GraphicsLock); } if (WaitAnyButtonOrQuit (TRUE)) break; InitPageCell: ButtonState = 1; t.baseline.y = r.extent.height + 1; row_cells = 0; if (StrLen) { LockMutex (GraphicsLock); if (!Sleepy) BatchGraphics (); ClearReportArea(); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x1F, 0x00), 0xFF)); if (Sleepy) UnlockMutex (GraphicsLock); } } } LockMutex (GraphicsLock); } void DoDiscoveryReport (SOUND ReadOutSounds) { POINT old_curs; CONTEXT OldContext; #ifdef DEBUG if (disableInteractivity) return; #endif if (pMenuState) { old_curs = pMenuState->flash_rect0.corner; /* Disable cursor: */ pMenuState->flash_rect0.corner.x = -1000; pMenuState->flash_rect0.corner.y = -1000; } OldContext = SetContext (ScanContext); { FONT OldFont; FRAME OldFontEffect; OldFont = SetContextFont ( pSolarSysState->SysInfo.PlanetInfo.LanderFont); if (optWhichFonts == OPT_PC) OldFontEffect = SetContextFontEffect ( pSolarSysState->SysInfo.PlanetInfo.LanderFontEff); else OldFontEffect = SetContextFontEffect (NULL); MakeReport (ReadOutSounds, (UNICODE *)GetStringAddress (pSolarSysState->SysInfo.PlanetInfo.DiscoveryString), GetStringLength (pSolarSysState->SysInfo.PlanetInfo.DiscoveryString)); SetContextFontEffect (OldFontEffect); SetContextFont (OldFont); } #ifdef OLD ClearDrawable (); if (pSolarSysState->MenuState.Initialized >= 3) DrawScannedObjects (FALSE); #else /* !OLD */ if (pSolarSysState->MenuState.Initialized < 3) ClearDrawable (); #endif /* OLD */ SetContext (OldContext); UnlockMutex (GraphicsLock); FlushInput (); while (AnyButtonPress (TRUE)) TaskSwitch (); LockMutex (GraphicsLock); if (pMenuState) pMenuState->flash_rect0.corner = old_curs; } uqm-0.6.2/sc2/src/sc2code/planets/scan.h0000600000175000017500000000245110543202100016337 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _SCAN_H #define _SCAN_H #include "libs/gfxlib.h" typedef struct { POINT start; COUNT start_dot, num_dots, dots_per_semi; } SCAN_DESC; typedef SCAN_DESC *PSCAN_DESC; typedef struct { PPOINT line_base; COUNT num_scans, num_same_scans; PSCAN_DESC scan_base; } SCAN_BLOCK; typedef SCAN_BLOCK *PSCAN_BLOCK; #define SAME_SCAN (1 << 16) #define SCALED_ROOT_TWO 92682L /* root 2 * (1 << 16) */ #define SCALE_FACTOR 16 extern void RepairBackRect (PRECT pRect); extern void GeneratePlanetSide (void); #endif /* _SCAN_H */ uqm-0.6.2/sc2/src/sc2code/planets/genburv.c0000600000175000017500000001354510543202100017064 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "globdata.h" #include "nameref.h" #include "resinst.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateBurvixes (BYTE control) { COUNT i; DWORD rand_val; switch (control) { case GENERATE_ENERGY: { DWORD rand_val, old_rand; if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT which_node; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0] && !GET_GAME_STATE (BURVIXESE_BROADCASTERS)) { old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; pSolarSysState->SysInfo.PlanetInfo.CurType = 0; if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; else { pSolarSysState->CurNode = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { SET_GAME_STATE (BURVIXESE_BROADCASTERS, 1); SET_GAME_STATE (BURV_BROADCASTERS_ON_SHIP, 1); } } TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; } case GENERATE_MOONS: GenerateRandomIP (GENERATE_MOONS); if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[0]) { COUNT angle; pSolarSysState->MoonDesc[0].data_index = SELENIC_WORLD; pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS + (MAX_MOONS - 1) * MOON_DELTA; rand_val = TFB_Random (); angle = NORMALIZE_ANGLE (LOWORD (rand_val)); pSolarSysState->MoonDesc[0].location.x = COSINE (angle, pSolarSysState->MoonDesc[0].radius); pSolarSysState->MoonDesc[0].location.y = SINE (angle, pSolarSysState->MoonDesc[0].radius); } break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = REDUX_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 1; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 39L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: { rand_val = DoPlanetaryAnalysis ( &pSolarSysState->SysInfo, pSolarSysState->pOrbitalDesc ); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[BIOLOGICAL_SCAN] = rand_val; i = (COUNT)~0; rand_val = GenerateLifeForms (&pSolarSysState->SysInfo, &i); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[MINERAL_SCAN] = rand_val; i = (COUNT)~0; GenerateMineralDeposits (&pSolarSysState->SysInfo, &i); pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] = rand_val; if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM)); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (BURV_RUINS_STRTAB)); pSolarSysState->SysInfo.PlanetInfo.Weather = 0; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 0; } else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[0] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0] && !GET_GAME_STATE (BURVIXESE_BROADCASTERS)) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (BURV_BCS_MASK_PMAP_ANIM)); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (BURV_BCS_STRTAB)); } LoadPlanet (NULL); break; } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/genrain.c0000600000175000017500000000443110543202100017031 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "encount.h" #include "globdata.h" #include "planets/genall.h" void GenerateRainbow (BYTE control) { switch (control) { case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = RAINBOW_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 0; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 50L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); if (angle <= QUADRANT) angle += QUADRANT; else if (angle >= FULL_CIRCLE - QUADRANT) angle -= QUADRANT; pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { BYTE which_rainbow; UWORD rainbow_mask; STAR_DESCPTR SDPtr; rainbow_mask = MAKE_WORD ( GET_GAME_STATE (RAINBOW_WORLD0), GET_GAME_STATE (RAINBOW_WORLD1) ); which_rainbow = 0; SDPtr = &star_array[0]; while (SDPtr != CurStarDescPtr) { if (SDPtr->Index == RAINBOW_DEFINED) ++which_rainbow; ++SDPtr; } rainbow_mask |= 1 << which_rainbow; SET_GAME_STATE (RAINBOW_WORLD0, LOBYTE (rainbow_mask)); SET_GAME_STATE (RAINBOW_WORLD1, HIBYTE (rainbow_mask)); } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/planets.c0000600000175000017500000001621510543202077017074 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "element.h" #include "scan.h" #include "lander.h" #include "settings.h" #include "setup.h" #include "uqmdebug.h" #include "libs/graphics/gfx_common.h" #include "resinst.h" #include "nameref.h" extern int rotate_planet_task (PVOID data); void DrawScannedObjects (BOOLEAN Reversed) { HELEMENT hElement, hNextElement; for (hElement = Reversed ? GetTailElement () : GetHeadElement (); hElement; hElement = hNextElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); hNextElement = Reversed ? GetPredElement (ElementPtr) : GetSuccElement (ElementPtr); if (ElementPtr->state_flags & APPEARING) { STAMP s; s.origin = ElementPtr->current.location; s.frame = ElementPtr->next.image.frame; DrawStamp (&s); } UnlockElement (hElement); } } typedef enum { DRAW_ORBITAL_FULL, DRAW_ORBITAL_WAIT, DRAW_ORBITAL_UPDATE, } DRAW_ORBITAL_MODE; static void DrawOrbitalDisplay (DRAW_ORBITAL_MODE Mode) { RECT r = { { SIS_ORG_X, SIS_ORG_Y }, { SIS_SCREEN_WIDTH, SIS_SCREEN_HEIGHT } }; BatchGraphics (); if (Mode != DRAW_ORBITAL_UPDATE) { SetTransitionSource (NULL); DrawSISFrame (); DrawSISMessage (NULL_PTR); DrawSISTitle (GLOBAL_SIS (PlanetName)); DrawStarBackGround (TRUE); } SetContext (SpaceContext); if (Mode == DRAW_ORBITAL_WAIT) { STAMP s; s.frame = CaptureDrawable ( LoadGraphic (ORBENTER_PMAP_ANIM)); s.origin.x = -SAFE_X; s.origin.y = SIS_SCREEN_HEIGHT - MAP_HEIGHT; DrawStamp (&s); DestroyDrawable (ReleaseDrawable (s.frame)); } else { DrawPlanet (SIS_SCREEN_WIDTH - MAP_WIDTH, SIS_SCREEN_HEIGHT - MAP_HEIGHT, 0, 0); } if (Mode != DRAW_ORBITAL_UPDATE) { ScreenTransition (3, &r); } UnbatchGraphics (); if (Mode != DRAW_ORBITAL_WAIT) { LoadIntoExtraScreen (&r); } } // Initialise the surface graphics, and start the planet music. // Called from the GENERATE_ORBITAL case of an IP generation function // (when orbit is entered; either from IP, or from loading a saved game) // and when "starmap" is selected from orbit and then cancelled; // also after in-orbit comm and after defeating planet guards in combat. // SurfDefFrame contains surface definition images when a planet comes // with its own bitmap (currently only for Earth) void LoadPlanet (FRAME SurfDefFrame) { BOOLEAN WaitMode; #ifdef DEBUG if (disableInteractivity) return; #endif WaitMode = !(LastActivity & CHECK_LOAD) && (pSolarSysState->MenuState.Initialized <= 2); if (WaitMode) { LockMutex (GraphicsLock); DrawOrbitalDisplay (DRAW_ORBITAL_WAIT); UnlockMutex (GraphicsLock); } if (pSolarSysState->MenuState.flash_task == 0) { // The "rotate planets" task is not initialised yet. // This means the call to LoadPlanet is made from a // GENERATE_ORBITAL case of an IP generation function. PPLANET_DESC pPlanetDesc; StopMusic (); TaskContext = CaptureContext (CreateContext ()); pPlanetDesc = pSolarSysState->pOrbitalDesc; /* if (pPlanetDesc->data_index & PLANET_SHIELDED) pSolarSysState->PlanetSideFrame[2] = CaptureDrawable ( LoadGraphic (PLANET_SHIELDED_MASK_PMAP_ANIM) ); else if (pSolarSysState->SysInfo.PlanetInfo.AtmoDensity != GAS_GIANT_ATMOSPHERE) LoadLanderData (); */ GeneratePlanetMask (pPlanetDesc, SurfDefFrame); SetPlanetMusic ((UBYTE)(pPlanetDesc->data_index & ~PLANET_SHIELDED)); if (pPlanetDesc->pPrevDesc != &pSolarSysState->SunDesc[0]) pPlanetDesc = pPlanetDesc->pPrevDesc; GeneratePlanetSide (); } LockMutex (GraphicsLock); DrawOrbitalDisplay (WaitMode ? DRAW_ORBITAL_UPDATE : DRAW_ORBITAL_FULL); #if 0 // this used to draw the static slave shield graphic SetContext (SpaceContext); s.frame = pSolarSysState->PlanetSideFrame[2]; if (s.frame) { s.origin.x = SIS_SCREEN_WIDTH >> 1; s.origin.y = ((116 - SIS_ORG_Y) >> 1) + 2; DrawStamp (&s); } #endif UnlockMutex (GraphicsLock); if (!PLRPlaying ((MUSIC_REF)~0)) PlayMusic (LanderMusic, TRUE, 1); if (pSolarSysState->MenuState.flash_task == 0) { pSolarSysState->MenuState.flash_task = AssignTask (rotate_planet_task, 4096, "rotate planets"); while (pSolarSysState->MenuState.Initialized == 2) TaskSwitch (); } } void FreePlanet (void) { COUNT i; PLANET_ORBIT *Orbit = &pSolarSysState->Orbit; if (pSolarSysState->MenuState.flash_task) { ConcludeTask (pSolarSysState->MenuState.flash_task); // Task_SetState (pSolarSysState->MenuState.flash_task, TASK_EXIT); pSolarSysState->MenuState.flash_task = 0; } StopMusic (); LockMutex (GraphicsLock); for (i = 0; i < sizeof (pSolarSysState->PlanetSideFrame) / sizeof (pSolarSysState->PlanetSideFrame[0]); ++i) { DestroyDrawable (ReleaseDrawable (pSolarSysState->PlanetSideFrame[i])); pSolarSysState->PlanetSideFrame[i] = 0; } // FreeLanderData (); DestroyStringTable (ReleaseStringTable (pSolarSysState->XlatRef)); pSolarSysState->XlatRef = 0; DestroyDrawable (ReleaseDrawable (pSolarSysState->TopoFrame)); pSolarSysState->TopoFrame = 0; DestroyColorMap (ReleaseColorMap (pSolarSysState->OrbitalCMap)); pSolarSysState->OrbitalCMap = 0; HFree (Orbit->lpTopoData); Orbit->lpTopoData = 0; DestroyDrawable (ReleaseDrawable (Orbit->TopoZoomFrame)); Orbit->TopoZoomFrame = 0; DestroyDrawable (ReleaseDrawable (Orbit->PlanetFrameArray)); Orbit->PlanetFrameArray = 0; DestroyDrawable (ReleaseDrawable (Orbit->TintFrame)); Orbit->TintFrame = 0; pSolarSysState->Tint_rgb = 0; DestroyDrawable (ReleaseDrawable (Orbit->ObjectFrame)); Orbit->ObjectFrame = 0; DestroyDrawable (ReleaseDrawable (Orbit->WorkFrame)); Orbit->WorkFrame = 0; if (Orbit->lpTopoMap != 0) { HFree (Orbit->lpTopoMap); Orbit->lpTopoMap = 0; } if (Orbit->ScratchArray != 0) { HFree (Orbit->ScratchArray); Orbit->ScratchArray = 0; } DestroyContext (ReleaseContext (TaskContext)); TaskContext = 0; DestroyStringTable (ReleaseStringTable ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString )); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = 0; FreeLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PauseRotate = 0; UnlockMutex (GraphicsLock); } void LoadStdLanderFont (PLANET_INFO *info) { info->LanderFont = CaptureFont (LoadFont (LANDER_FONT)); info->LanderFontEff = CaptureDrawable ( LoadGraphic (LANDER_FONTEFF_PMAP_ANIM)); } void FreeLanderFont (PLANET_INFO *info) { DestroyFont (ReleaseFont (info->LanderFont)); info->LanderFont = 0; DestroyDrawable (ReleaseDrawable (info->LanderFontEff)); info->LanderFontEff = 0; } uqm-0.6.2/sc2/src/sc2code/planets/surface.c0000600000175000017500000001627210543202100017044 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "lifeform.h" #include "planets.h" #include "libs/mathlib.h" #include "libs/log.h" //#define DEBUG_SURFACE const BYTE *Elements; const PlanetFrame *PlanData; static COUNT CalcMineralDeposits (SYSTEM_INFOPTR SysInfoPtr, COUNT which_deposit) { BYTE j; COUNT num_deposits; ELEMENT_ENTRYPTR eptr; eptr = &SysInfoPtr->PlanetInfo.PlanDataPtr->UsefulElements[0]; num_deposits = 0; j = NUM_USEFUL_ELEMENTS; do { BYTE num_possible; num_possible = (BYTE)((BYTE)TFB_Random () % (DEPOSIT_QUANTITY (eptr->Density) + 1)); while (num_possible--) { #define MEDIUM_DEPOSIT_THRESHOLD 150 #define LARGE_DEPOSIT_THRESHOLD 225 DWORD rand_val; UWORD loword, hiword; COUNT deposit_quality_fine, deposit_quality_gross; deposit_quality_fine = ((COUNT)TFB_Random () % 100) + ( DEPOSIT_QUALITY (eptr->Density) + SysInfoPtr->StarSize ) * 50; if (deposit_quality_fine < MEDIUM_DEPOSIT_THRESHOLD) deposit_quality_gross = 0; else if (deposit_quality_fine < LARGE_DEPOSIT_THRESHOLD) deposit_quality_gross = 1; else deposit_quality_gross = 2; rand_val = TFB_Random (); loword = LOWORD (rand_val); hiword = HIWORD (rand_val); SysInfoPtr->PlanetInfo.CurPt.x = (LOBYTE (loword) % (MAP_WIDTH - (8 << 1))) + 8; SysInfoPtr->PlanetInfo.CurPt.y = (HIBYTE (loword) % (MAP_HEIGHT - (8 << 1))) + 8; SysInfoPtr->PlanetInfo.CurDensity = MAKE_WORD ( deposit_quality_gross, deposit_quality_fine / 10 + 1 ); SysInfoPtr->PlanetInfo.CurType = eptr->ElementType; #ifdef DEBUG_SURFACE log_add (log_Debug, "\t\t%d units of %Fs", SysInfoPtr->PlanetInfo.CurDensity, Elements[eptr->ElementType].name); #endif /* DEBUG_SURFACE */ if ((num_deposits >= which_deposit && !(SysInfoPtr->PlanetInfo.ScanRetrieveMask[MINERAL_SCAN] & (1L << num_deposits))) || ++num_deposits == sizeof (DWORD) * 8) goto ExitCalcMinerals; } ++eptr; } while (--j); ExitCalcMinerals: return (num_deposits); } DWORD GenerateMineralDeposits (SYSTEM_INFOPTR SysInfoPtr, PCOUNT pwhich_deposit) { DWORD old_rand; old_rand = TFB_SeedRandom (SysInfoPtr->PlanetInfo.ScanSeed[MINERAL_SCAN]); *pwhich_deposit = CalcMineralDeposits (SysInfoPtr, *pwhich_deposit); return (TFB_SeedRandom (old_rand)); } static COUNT CalcLifeForms (SYSTEM_INFOPTR SysInfoPtr, COUNT which_life) { COUNT num_life_forms; num_life_forms = 0; if (PLANSIZE (SysInfoPtr->PlanetInfo.PlanDataPtr->Type) == GAS_GIANT) SysInfoPtr->PlanetInfo.LifeChance = -1; else { #define MIN_LIFE_CHANCE 10 SIZE life_var; life_var = 0; if (SysInfoPtr->PlanetInfo.SurfaceTemperature < -151) life_var -= 300; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < -51) life_var -= 100; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 0) life_var += 100; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 50) life_var += 300; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 150) life_var += 50; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 250) life_var -= 100; else if (SysInfoPtr->PlanetInfo.SurfaceTemperature < 500) life_var -= 400; else life_var -= 800; if (SysInfoPtr->PlanetInfo.AtmoDensity == 0) life_var -= 1000; else if (SysInfoPtr->PlanetInfo.AtmoDensity < 15) life_var += 100; else if (SysInfoPtr->PlanetInfo.AtmoDensity < 30) life_var += 200; else if (SysInfoPtr->PlanetInfo.AtmoDensity < 100) life_var += 300; else if (SysInfoPtr->PlanetInfo.AtmoDensity < 1000) life_var += 150; else if (SysInfoPtr->PlanetInfo.AtmoDensity < 2500) ; else life_var -= 100; #ifndef NOTYET life_var += 200 + 80 + 80; #else /* NOTYET */ if (SysInfoPtr->PlanetInfo.SurfaceGravity < 10) ; else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 35) life_var += 50; else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 75) life_var += 100; else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 150) life_var += 200; else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 400) life_var += 50; else if (SysInfoPtr->PlanetInfo.SurfaceGravity < 800) ; else life_var -= 100; if (SysInfoPtr->PlanetInfo.Tectonics < 1) life_var += 80; else if (SysInfoPtr->PlanetInfo.Tectonics < 2) life_var += 70; else if (SysInfoPtr->PlanetInfo.Tectonics < 3) life_var += 60; else if (SysInfoPtr->PlanetInfo.Tectonics < 4) life_var += 50; else if (SysInfoPtr->PlanetInfo.Tectonics < 5) life_var += 25; else if (SysInfoPtr->PlanetInfo.Tectonics < 6) ; else life_var -= 100; if (SysInfoPtr->PlanetInfo.Weather < 1) life_var += 80; else if (SysInfoPtr->PlanetInfo.Weather < 2) life_var += 70; else if (SysInfoPtr->PlanetInfo.Weather < 3) life_var += 60; else if (SysInfoPtr->PlanetInfo.Weather < 4) life_var += 50; else if (SysInfoPtr->PlanetInfo.Weather < 5) life_var += 25; else if (SysInfoPtr->PlanetInfo.Weather < 6) ; else life_var -= 100; #endif /* NOTYET */ SysInfoPtr->PlanetInfo.LifeChance = life_var; life_var = (COUNT)TFB_Random () & 1023; if (life_var < SysInfoPtr->PlanetInfo.LifeChance || (SysInfoPtr->PlanetInfo.LifeChance < MIN_LIFE_CHANCE && life_var < MIN_LIFE_CHANCE)) { BYTE num_types; num_types = (BYTE)(((BYTE)TFB_Random () % MAX_LIFE_VARIATION) + 1); do { BYTE index, num_creatures; UWORD rand_val; rand_val = (UWORD)TFB_Random (); index = LOBYTE (rand_val) % NUM_CREATURE_TYPES; num_creatures = (BYTE)((HIBYTE (rand_val) % 10) + 1); do { rand_val = (UWORD)TFB_Random (); SysInfoPtr->PlanetInfo.CurPt.x = (LOBYTE (rand_val) % (MAP_WIDTH - (8 << 1))) + 8; SysInfoPtr->PlanetInfo.CurPt.y = (HIBYTE (rand_val) % (MAP_HEIGHT - (8 << 1))) + 8; SysInfoPtr->PlanetInfo.CurType = index; if ((num_life_forms >= which_life && !(SysInfoPtr->PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] & (1L << num_life_forms))) || ++num_life_forms == sizeof (DWORD) * 8) { num_types = 1; break; } } while (--num_creatures); } while (--num_types); } #ifdef DEBUG_SURFACE else log_add (log_Debug, "It's dead, Jim! (%d >= %d)", life_var, SysInfoPtr->PlanetInfo.LifeChance); #endif /* DEBUG_SURFACE */ } return (num_life_forms); } DWORD GenerateLifeForms (SYSTEM_INFOPTR SysInfoPtr, PCOUNT pwhich_life) { DWORD old_rand; old_rand = TFB_SeedRandom ( SysInfoPtr->PlanetInfo.ScanSeed[BIOLOGICAL_SCAN]); *pwhich_life = CalcLifeForms (SysInfoPtr, *pwhich_life); return (TFB_SeedRandom (old_rand)); } uqm-0.6.2/sc2/src/sc2code/planets/genzoq.c0000600000175000017500000001360510543202100016714 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "nameref.h" #include "resinst.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" static void check_scout (void) { HSTARSHIP hStarShip; if (GLOBAL (BattleGroupRef) && (hStarShip = GetHeadLink ( &GLOBAL (npc_built_ship_q) ))) { BYTE task; SHIP_FRAGMENTPTR FragPtr; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); task = GET_GROUP_MISSION (FragPtr); if (task & REFORM_GROUP) { SET_GROUP_MISSION (FragPtr, FLEE | IGNORE_FLAGSHIP | REFORM_GROUP); SET_GROUP_DEST (FragPtr, 0); } UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } } static void GenerateScout (BYTE control) { switch (control) { case INIT_NPCS: if (!GET_GAME_STATE (MET_ZOQFOT)) { GLOBAL (BattleGroupRef) = GET_GAME_STATE_32 (ZOQFOT_GRPOFFS0); if (GLOBAL (BattleGroupRef) == 0) { CloneShipFragment (ZOQFOTPIK_SHIP, &GLOBAL (npc_built_ship_q), 0); GLOBAL (BattleGroupRef) = PutGroupInfo (GROUPS_ADD_NEW, 1); SET_GAME_STATE_32 (ZOQFOT_GRPOFFS0, GLOBAL (BattleGroupRef)); } } GenerateRandomIP (INIT_NPCS); break; case REINIT_NPCS: GenerateRandomIP (REINIT_NPCS); check_scout (); break; default: GenerateRandomIP (control); break; } } void GenerateZoqFotPik (BYTE control) { if (CurStarDescPtr->Index == ZOQ_SCOUT_DEFINED) { GenerateScout (control); return; } switch (control) { case INIT_NPCS: if (GET_GAME_STATE (ZOQFOT_DISTRESS) != 1) GenerateRandomIP (INIT_NPCS); break; case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i, which_node; DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = REDUX_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 1; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 138L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { if (ActivateStarShip (ZOQFOTPIK_SHIP, SPHERE_TRACKING)) { PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); if (GET_GAME_STATE (ZOQFOT_DISTRESS)) { CloneShipFragment (BLACK_URQUAN_SHIP, &GLOBAL (npc_built_ship_q), 0); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); InitCommunication (BLACKURQ_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) break; if (GetHeadLink (&GLOBAL (npc_built_ship_q))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); break; } } CloneShipFragment (ZOQFOTPIK_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); InitCommunication (ZOQFOTPIK_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } else { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (RUINS_STRTAB) ); } } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/Makeinfo0000600000175000017500000000063110543202100016714 0ustar joeyjoeyuqm_CFILES="calc.c cargo.c devices.c genburv.c genchmmr.c gencol.c gendru.c genilw.c genmel.c genmyc.c genorz.c genpet.c genpku.c genrain.c gensam.c genshof.c gensly.c gensol.c genspa.c gensup.c gensyr.c genthrad.c gentopo.c genutw.c genvault.c genvux.c genwreck.c genyeh.c genzoq.c lander.c orbits.c oval.c pl_stuff.c planets.c plangen.c pstarmap.c report.c roster.c scan.c solarsys.c surface.c" uqm-0.6.2/sc2/src/sc2code/planets/cargo.c0000600000175000017500000002154610543202100016507 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "colors.h" #include "controls.h" #include "gamestr.h" #include "shipcont.h" #include "setup.h" #include "sounds.h" #include "util.h" void ShowRemainingCapacity (void) { RECT r; TEXT rt; CONTEXT OldContext; UNICODE rt_amount_buf[40]; OldContext = SetContext (StatusContext); SetContextFont (TinyFont); sprintf (rt_amount_buf, "%u", GetSBayCapacity (NULL_PTR) - GLOBAL_SIS (TotalElementMass)); rt.baseline.x = 59; rt.baseline.y = 113; rt.align = ALIGN_RIGHT; rt.pStr = rt_amount_buf; rt.CharCount = (COUNT)~0; r.corner.x = 40; r.corner.y = rt.baseline.y - 6; r.extent.width = rt.baseline.x - r.corner.x + 1; r.extent.height = 7; BatchGraphics (); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); font_DrawText (&rt); UnbatchGraphics (); SetContext (OldContext); } void DrawCargoStrings (BYTE OldElement, BYTE NewElement) { COORD y, cy; TEXT rt; RECT r; CONTEXT OldContext; UNICODE rt_amount_buf[40]; LockMutex (GraphicsLock); OldContext = SetContext (StatusContext); SetContextFont (TinyFont); BatchGraphics (); y = 41; rt.align = ALIGN_RIGHT; rt.pStr = rt_amount_buf; if (OldElement > NUM_ELEMENT_CATEGORIES) { STAMP s; r.corner.x = 2; r.extent.width = FIELD_WIDTH + 1; { TEXT ct; r.corner.y = 20; r.extent.height = 109; DrawStarConBox (&r, 1, BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F), TRUE, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); SetContextFont (StarConFont); ct.baseline.x = (STATUS_WIDTH >> 1) - 1; ct.baseline.y = 27; ct.align = ALIGN_CENTER; ct.pStr = GAME_STRING (CARGO_STRING_BASE); ct.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)); font_DrawText (&ct); SetContextFont (TinyFont); } r.corner.x = 7; r.extent.width = 7; r.extent.height = 7; s.origin.x = r.corner.x + (r.extent.width >> 1); s.frame = SetAbsFrameIndex ( MiscDataFrame, (NUM_SCANDOT_TRANSITIONS << 1) + 3 ); cy = y; rt.baseline.y = cy - 7; rt.CharCount = 1; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); rt.baseline.x = 32; rt_amount_buf[0] = '$'; font_DrawText (&rt); rt.baseline.x = 58; rt_amount_buf[0] = '#'; font_DrawText (&rt); for (OldElement = 0; OldElement < NUM_ELEMENT_CATEGORIES; ++OldElement) { SetContextForeGroundColor (BLACK_COLOR); r.corner.y = cy - 6; DrawFilledRectangle (&r); s.origin.y = r.corner.y + (r.extent.height >> 1); DrawStamp (&s); s.frame = SetRelFrameIndex (s.frame, 5); if (OldElement != NewElement) { rt.baseline.y = cy; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); rt.baseline.x = 32; sprintf (rt_amount_buf, "%u", GLOBAL (ElementWorth[OldElement])); rt.CharCount = (COUNT)~0; font_DrawText (&rt); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); rt.baseline.x = 58; sprintf (rt_amount_buf, "%u", GLOBAL_SIS (ElementAmounts[OldElement])); rt.CharCount = (COUNT)~0; font_DrawText (&rt); } cy += 9; } OldElement = NewElement; rt.baseline.y = 125; SetContextForeGroundColor (BLACK_COLOR); r.corner.y = rt.baseline.y - 6; DrawFilledRectangle (&r); s.origin.y = r.corner.y + (r.extent.height >> 1); s.frame = SetAbsFrameIndex (s.frame, 68); DrawStamp (&s); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); rt.baseline.x = 58; sprintf (rt_amount_buf, "%u", GLOBAL_SIS (TotalBioMass)); rt.CharCount = (COUNT)~0; font_DrawText (&rt); r.corner.x = 4; r.corner.y = 117; r.extent.width = 56; r.extent.height = 1; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); DrawFilledRectangle (&r); { TEXT lt; lt.baseline.x = 5; lt.baseline.y = 113; lt.align = ALIGN_LEFT; lt.pStr = GAME_STRING (CARGO_STRING_BASE + 1); lt.CharCount = (COUNT)~0; font_DrawText (<); } ShowRemainingCapacity (); } r.corner.x = 19; r.extent.width = 40; r.extent.height = 7; if (OldElement != NewElement) { if (OldElement == NUM_ELEMENT_CATEGORIES) cy = 125; else cy = y + (OldElement * 9); r.corner.y = cy - 6; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); DrawFilledRectangle (&r); rt.baseline.y = cy; if (OldElement == NUM_ELEMENT_CATEGORIES) sprintf (rt_amount_buf, "%u", GLOBAL_SIS (TotalBioMass)); else { SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); rt.baseline.x = 32; sprintf (rt_amount_buf, "%u", GLOBAL (ElementWorth[OldElement])); rt.CharCount = (COUNT)~0; font_DrawText (&rt); sprintf (rt_amount_buf, "%u", GLOBAL_SIS (ElementAmounts[OldElement])); } SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); rt.baseline.x = 58; rt.CharCount = (COUNT)~0; font_DrawText (&rt); } if (NewElement != (BYTE)~0) { if (NewElement == NUM_ELEMENT_CATEGORIES) cy = 125; else cy = y + (NewElement * 9); r.corner.y = cy - 6; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x1F), 0x09)); DrawFilledRectangle (&r); rt.baseline.y = cy; if (NewElement == NUM_ELEMENT_CATEGORIES) sprintf (rt_amount_buf, "%u", GLOBAL_SIS (TotalBioMass)); else { SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); rt.baseline.x = 32; sprintf (rt_amount_buf, "%u", GLOBAL (ElementWorth[NewElement])); rt.CharCount = (COUNT)~0; font_DrawText (&rt); sprintf (rt_amount_buf, "%u", GLOBAL_SIS (ElementAmounts[NewElement])); } SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)); rt.baseline.x = 58; rt.CharCount = (COUNT)~0; font_DrawText (&rt); } UnbatchGraphics (); SetContext (OldContext); UnlockMutex (GraphicsLock); } static BOOLEAN DoDiscardCargo (PMENU_STATE pMS) { BYTE NewState; BOOLEAN select, cancel, back, forward; select = PulsedInputState.menu[KEY_MENU_SELECT]; cancel = PulsedInputState.menu[KEY_MENU_CANCEL]; back = PulsedInputState.menu[KEY_MENU_UP] || PulsedInputState.menu[KEY_MENU_LEFT]; forward = PulsedInputState.menu[KEY_MENU_DOWN] || PulsedInputState.menu[KEY_MENU_RIGHT]; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); if (!(pMS->Initialized & 1)) { pMS->InputFunc = DoDiscardCargo; ++pMS->Initialized; NewState = pMS->CurState; pMS->CurState = (BYTE)~0; goto SelectCargo; } else if (cancel) { LockMutex (GraphicsLock); ClearSISRect (DRAW_SIS_DISPLAY); UnlockMutex (GraphicsLock); return (FALSE); } else if (select) { if (GLOBAL_SIS (ElementAmounts[pMS->CurState - 1])) { --GLOBAL_SIS (ElementAmounts[pMS->CurState - 1]); DrawCargoStrings ((BYTE)(pMS->CurState - 1), (BYTE)(pMS->CurState - 1)); LockMutex (GraphicsLock); --GLOBAL_SIS (TotalElementMass); ShowRemainingCapacity (); UnlockMutex (GraphicsLock); } else { // no element left in cargo hold PlayMenuSound (MENU_SOUND_FAILURE); } } else { NewState = pMS->CurState - 1; if (back) { if (NewState-- == 0) NewState = NUM_ELEMENT_CATEGORIES - 1; } else if (forward) { if (++NewState == NUM_ELEMENT_CATEGORIES) NewState = 0; } if (++NewState != pMS->CurState) { SelectCargo: DrawCargoStrings ((BYTE)(pMS->CurState - 1), (BYTE)(NewState - 1)); LockMutex (GraphicsLock); DrawStatusMessage (GAME_STRING (NewState - 1 + (CARGO_STRING_BASE + 2))); UnlockMutex (GraphicsLock); pMS->CurState = NewState; } } return (TRUE); } void Cargo (PMENU_STATE pMS) { pMS->InputFunc = DoDiscardCargo; --pMS->Initialized; pMS->CurState = 1; LockMutex (GraphicsLock); DrawStatusMessage ((UNICODE *)~0); UnlockMutex (GraphicsLock); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); DoInput ((PVOID)pMS, TRUE); pMS->InputFunc = DoFlagshipCommands; pMS->CurState = CARGO + 1; } uqm-0.6.2/sc2/src/sc2code/planets/gensly.c0000600000175000017500000000261610543202077016727 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "encount.h" #include "resinst.h" #include "planets/genall.h" void GenerateSlylandro (BYTE control) { switch (control) { case GENERATE_PLANETS: GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[3].data_index = RED_GAS_GIANT; pSolarSysState->PlanetDesc[3].NumPlanets = 1; break; case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[3]) { pSolarSysState->MenuState.Initialized += 2; InitCommunication (SLYLANDRO_HOME_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; break; } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/pstarmap.c0000600000175000017500000012327210543202100017242 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "colors.h" #include "controls.h" #include "encount.h" #include "gameopt.h" #include "gamestr.h" #include "globdata.h" #include "options.h" #include "scan.h" #include "shipcont.h" #include "settings.h" #include "setup.h" #include "sounds.h" #include "state.h" #include "uqmdebug.h" #include "libs/inplib.h" #include "libs/strlib.h" #include "libs/graphics/gfx_common.h" #include "libs/mathlib.h" #define UNIVERSE_TO_DISPX(ux) \ (COORD)(((((long)(ux) - pMenuState->flash_rect1.corner.x) \ << LOBYTE (pMenuState->delta_item)) \ * SIS_SCREEN_WIDTH / (MAX_X_UNIVERSE + 1)) + ((SIS_SCREEN_WIDTH - 1) >> 1)) #define UNIVERSE_TO_DISPY(uy) \ (COORD)(((((long)pMenuState->flash_rect1.corner.y - (uy)) \ << LOBYTE (pMenuState->delta_item)) \ * SIS_SCREEN_HEIGHT / (MAX_Y_UNIVERSE + 1)) + ((SIS_SCREEN_HEIGHT - 1) >> 1)) #define DISP_TO_UNIVERSEX(dx) \ ((COORD)((((long)((dx) - ((SIS_SCREEN_WIDTH - 1) >> 1)) \ * (MAX_X_UNIVERSE + 1)) >> LOBYTE (pMenuState->delta_item)) \ / SIS_SCREEN_WIDTH) + pMenuState->flash_rect1.corner.x) #define DISP_TO_UNIVERSEY(dy) \ ((COORD)((((long)(((SIS_SCREEN_HEIGHT - 1) >> 1) - (dy)) \ * (MAX_Y_UNIVERSE + 1)) >> LOBYTE (pMenuState->delta_item)) \ / SIS_SCREEN_HEIGHT) + pMenuState->flash_rect1.corner.y) static BOOLEAN transition_pending; static int flash_cursor_func (void *data) { BYTE c, val; POINT universe; STAMP s; Task task = (Task) data; if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) universe = CurStarDescPtr->star_pt; else { universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); } s.frame = IncFrameIndex (pMenuState->CurFrame); c = 0x00; val = -0x02; while (!Task_ReadState(task, TASK_EXIT)) { DWORD TimeIn; COLOR OldColor; CONTEXT OldContext; TimeIn = GetTimeCounter (); LockMutex (GraphicsLock); OldContext = SetContext (SpaceContext); if (c == 0x00 || c == 0x1A) val = -val; c += val; OldColor = SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (c, c, c), c)); s.origin.x = UNIVERSE_TO_DISPX (universe.x); s.origin.y = UNIVERSE_TO_DISPY (universe.y); DrawFilledStamp (&s); SetContextForeGroundColor (OldColor); SetContext (OldContext); UnlockMutex (GraphicsLock); SleepThreadUntil (TimeIn + (ONE_SECOND >> 4)); } FinishTask (task); return (0); } static void DrawCursor (COORD curs_x, COORD curs_y) { STAMP s; s.origin.x = curs_x; s.origin.y = curs_y; s.frame = pMenuState->CurFrame; DrawStamp (&s); } static void DrawAutoPilot (PPOINT pDstPt) { SIZE dx, dy, xincr, yincr, xerror, yerror, cycle, delta; POINT pt; if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) pt = CurStarDescPtr->star_pt; else { pt.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); pt.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); } pt.x = UNIVERSE_TO_DISPX (pt.x); pt.y = UNIVERSE_TO_DISPY (pt.y); dx = UNIVERSE_TO_DISPX (pDstPt->x) - pt.x; if (dx >= 0) xincr = 1; else { xincr = -1; dx = -dx; } dx <<= 1; dy = UNIVERSE_TO_DISPY (pDstPt->y) - pt.y; if (dy >= 0) yincr = 1; else { yincr = -1; dy = -dy; } dy <<= 1; if (dx >= dy) cycle = dx; else cycle = dy; delta = xerror = yerror = cycle >> 1; SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x04, 0x04, 0x1F), 0x01)); delta &= ~1; while (delta--) { if (!(delta & 1)) DrawPoint (&pt); if ((xerror -= dx) <= 0) { pt.x += xincr; xerror += cycle; } if ((yerror -= dy) <= 0) { pt.y += yincr; yerror += cycle; } } } static void GetSphereRect (EXTENDED_SHIP_FRAGMENTPTR StarShipPtr, PRECT pRect, PRECT pRepairRect) { long diameter; diameter = (long)( StarShipPtr->ShipInfo.known_strength * SPHERE_RADIUS_INCREMENT ); pRect->extent.width = UNIVERSE_TO_DISPX (diameter) - UNIVERSE_TO_DISPX (0); if (pRect->extent.width < 0) pRect->extent.width = -pRect->extent.width; else if (pRect->extent.width == 0) pRect->extent.width = 1; pRect->extent.height = UNIVERSE_TO_DISPY (diameter) - UNIVERSE_TO_DISPY (0); if (pRect->extent.height < 0) pRect->extent.height = -pRect->extent.height; else if (pRect->extent.height == 0) pRect->extent.height = 1; pRect->corner.x = UNIVERSE_TO_DISPX ( StarShipPtr->ShipInfo.known_loc.x ); pRect->corner.y = UNIVERSE_TO_DISPY ( StarShipPtr->ShipInfo.known_loc.y ); pRect->corner.x -= pRect->extent.width >> 1; pRect->corner.y -= pRect->extent.height >> 1; { TEXT t; STRING locString; SetContextFont (TinyFont); t.baseline.x = pRect->corner.x + (pRect->extent.width >> 1); t.baseline.y = pRect->corner.y + (pRect->extent.height >> 1) - 1; t.align = ALIGN_CENTER; locString = SetAbsStringTableIndex ( StarShipPtr->ShipInfo.race_strings, 1 ); t.CharCount = GetStringLength (locString); t.pStr = (UNICODE *)GetStringAddress (locString); TextRect (&t, pRepairRect, NULL_PTR); if (pRepairRect->corner.x <= 0) pRepairRect->corner.x = 1; else if (pRepairRect->corner.x + pRepairRect->extent.width >= SIS_SCREEN_WIDTH) pRepairRect->corner.x = SIS_SCREEN_WIDTH - pRepairRect->extent.width - 1; if (pRepairRect->corner.y <= 0) pRepairRect->corner.y = 1; else if (pRepairRect->corner.y + pRepairRect->extent.height >= SIS_SCREEN_HEIGHT) pRepairRect->corner.y = SIS_SCREEN_HEIGHT - pRepairRect->extent.height - 1; BoxUnion (pRepairRect, pRect, pRepairRect); pRepairRect->extent.width++; pRepairRect->extent.height++; } } static void DrawStarMap (COUNT race_update, PRECT pClipRect) { #define GRID_DELTA 500 SIZE i; COUNT which_space; long diameter; RECT r, old_r; STAMP s; FRAME star_frame; STAR_DESCPTR SDPtr; BOOLEAN draw_cursor; if (pClipRect == (PRECT)-1) { pClipRect = 0; draw_cursor = FALSE; } else { LockMutex (GraphicsLock); draw_cursor = TRUE; } SetContext (SpaceContext); if (pClipRect) { GetContextClipRect (&old_r); pClipRect->corner.x += old_r.corner.x; pClipRect->corner.y += old_r.corner.y; SetContextClipRect (pClipRect); pClipRect->corner.x -= old_r.corner.x; pClipRect->corner.y -= old_r.corner.y; SetFrameHot (Screen, MAKE_HOT_SPOT (pClipRect->corner.x, pClipRect->corner.y)); } if (transition_pending) { SetTransitionSource (NULL); } BatchGraphics (); which_space = GET_GAME_STATE (ARILOU_SPACE_SIDE); if (which_space <= 1) { SDPtr = &star_array[0]; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x07), 0x57)); SetContextBackGroundColor (BLACK_COLOR); } else { SDPtr = &star_array[NUM_SOLAR_SYSTEMS + 1]; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x0B, 0x00), 0x6D)); SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x08, 0x00), 0x6E)); } ClearDrawable (); if (race_update == 0 && which_space < 2 && (diameter = (long)GLOBAL_SIS (FuelOnBoard) << 1)) { COLOR OldColor; if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) r.corner = CurStarDescPtr->star_pt; else { r.corner.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); r.corner.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); } r.extent.width = UNIVERSE_TO_DISPX (diameter) - UNIVERSE_TO_DISPX (0); if (r.extent.width < 0) r.extent.width = -r.extent.width; r.extent.height = UNIVERSE_TO_DISPY (diameter) - UNIVERSE_TO_DISPY (0); if (r.extent.height < 0) r.extent.height = -r.extent.height; r.corner.x = UNIVERSE_TO_DISPX (r.corner.x) - (r.extent.width >> 1); r.corner.y = UNIVERSE_TO_DISPY (r.corner.y) - (r.extent.height >> 1); OldColor = SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x03, 0x03, 0x03), 0x22)); DrawFilledOval (&r); SetContextForeGroundColor (OldColor); } for (i = MAX_Y_UNIVERSE + 1; i >= 0; i -= GRID_DELTA) { SIZE j; r.corner.x = UNIVERSE_TO_DISPX (0); r.corner.y = UNIVERSE_TO_DISPY (i); r.extent.width = SIS_SCREEN_WIDTH << LOBYTE (pMenuState->delta_item); r.extent.height = 1; DrawFilledRectangle (&r); r.corner.y = UNIVERSE_TO_DISPY (MAX_Y_UNIVERSE + 1); r.extent.width = 1; r.extent.height = SIS_SCREEN_HEIGHT << LOBYTE (pMenuState->delta_item); for (j = MAX_X_UNIVERSE + 1; j >= 0; j -= GRID_DELTA) { r.corner.x = UNIVERSE_TO_DISPX (j); DrawFilledRectangle (&r); } } star_frame = SetRelFrameIndex (pMenuState->CurFrame, 2); if (which_space <= 1) { COUNT index; HSTARSHIP hStarShip, hNextShip; static const COLOR race_colors[] = { RACE_COLORS }; for (index = 0, hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); hStarShip != 0; ++index, hStarShip = hNextShip) { EXTENDED_SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip ); hNextShip = _GetSuccLink (StarShipPtr); if (StarShipPtr->ShipInfo.known_strength) { RECT repair_r; GetSphereRect (StarShipPtr, &r, &repair_r); if (r.corner.x < SIS_SCREEN_WIDTH && r.corner.y < SIS_SCREEN_HEIGHT && r.corner.x + r.extent.width > 0 && r.corner.y + r.extent.height > 0 && (pClipRect == 0 || (repair_r.corner.x < pClipRect->corner.x + pClipRect->extent.width && repair_r.corner.y < pClipRect->corner.y + pClipRect->extent.height && repair_r.corner.x + repair_r.extent.width > pClipRect->corner.x && repair_r.corner.y + repair_r.extent.height > pClipRect->corner.y))) { COLOR c; TEXT t; STRING locString; c = race_colors[index]; if (index + 1 == race_update) SetContextForeGroundColor (WHITE_COLOR); else SetContextForeGroundColor (c); DrawOval (&r, 0); SetContextFont (TinyFont); t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.y = r.corner.y + (r.extent.height >> 1) - 1; t.align = ALIGN_CENTER; locString = SetAbsStringTableIndex ( StarShipPtr->ShipInfo.race_strings, 1 ); t.CharCount = GetStringLength (locString); t.pStr = (UNICODE *)GetStringAddress (locString); TextRect (&t, &r, NULL_PTR); if (r.corner.x <= 0) t.baseline.x -= r.corner.x - 1; else if (r.corner.x + r.extent.width >= SIS_SCREEN_WIDTH) t.baseline.x -= (r.corner.x + r.extent.width) - SIS_SCREEN_WIDTH + 1; if (r.corner.y <= 0) t.baseline.y -= r.corner.y - 1; else if (r.corner.y + r.extent.height >= SIS_SCREEN_HEIGHT) t.baseline.y -= (r.corner.y + r.extent.height) - SIS_SCREEN_HEIGHT + 1; { BYTE r, g, b; COLOR c32k; c32k = COLOR_32k (c); r = (BYTE)((c32k >> (5 * 2)) & 0x1F); if ((r += 0x03) > 0x1F) r = 0x1F; g = (BYTE)((c32k >> (5 * 1)) & 0x1F); if ((g += 0x03) > 0x1F) g = 0x1F; b = (BYTE)((c32k >> (5 * 0)) & 0x1F); if ((b += 0x03) > 0x1F) b = 0x1F; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (r, g, b), COLOR_256 (c) - 1) ); } font_DrawText (&t); } } UnlockStarShip ( &GLOBAL (avail_race_q), hStarShip ); } } do { BYTE star_type; star_type = SDPtr->Type; #ifdef NOTYET { UNICODE buf[256]; GetClusterName (SDPtr, buf); printf ("%s\n", buf); } #endif /* NOTYET */ s.origin.x = UNIVERSE_TO_DISPX (SDPtr->star_pt.x); s.origin.y = UNIVERSE_TO_DISPY (SDPtr->star_pt.y); if (which_space <= 1) s.frame = SetRelFrameIndex (star_frame, STAR_TYPE (star_type) * NUM_STAR_COLORS + STAR_COLOR (star_type)); else if (SDPtr->star_pt.x == ARILOU_HOME_X && SDPtr->star_pt.y == ARILOU_HOME_Y) s.frame = SetRelFrameIndex (star_frame, SUPER_GIANT_STAR * NUM_STAR_COLORS + GREEN_BODY); else s.frame = SetRelFrameIndex (star_frame, GIANT_STAR * NUM_STAR_COLORS + GREEN_BODY); DrawStamp (&s); ++SDPtr; } while (SDPtr->star_pt.x <= MAX_X_UNIVERSE && SDPtr->star_pt.y <= MAX_Y_UNIVERSE); if (GET_GAME_STATE (ARILOU_SPACE)) { if (which_space <= 1) { s.origin.x = UNIVERSE_TO_DISPX (ARILOU_SPACE_X); s.origin.y = UNIVERSE_TO_DISPY (ARILOU_SPACE_Y); } else { s.origin.x = UNIVERSE_TO_DISPX (QUASI_SPACE_X); s.origin.y = UNIVERSE_TO_DISPY (QUASI_SPACE_Y); } s.frame = SetRelFrameIndex (star_frame, GIANT_STAR * NUM_STAR_COLORS + GREEN_BODY); DrawStamp (&s); } if (race_update == 0 && GLOBAL (autopilot.x) != ~0 && GLOBAL (autopilot.y) != ~0) DrawAutoPilot (&GLOBAL (autopilot)); if (transition_pending) { GetContextClipRect (&r); ScreenTransition (3, &r); transition_pending = FALSE; } UnbatchGraphics (); if (pClipRect) { SetContextClipRect (&old_r); SetFrameHot (Screen, MAKE_HOT_SPOT (0, 0)); } if (race_update == 0) { if (draw_cursor) { GetContextClipRect (&r); LoadIntoExtraScreen (&r); DrawCursor ( UNIVERSE_TO_DISPX (pMenuState->first_item.x), UNIVERSE_TO_DISPY (pMenuState->first_item.y) ); } } if (draw_cursor) UnlockMutex (GraphicsLock); } static void EraseCursor (COORD curs_x, COORD curs_y) { RECT r; GetFrameRect (pMenuState->CurFrame, &r); if ((r.corner.x += curs_x) < 0) { r.extent.width += r.corner.x; r.corner.x = 0; } else if (r.corner.x + r.extent.width >= SIS_SCREEN_WIDTH) r.extent.width = SIS_SCREEN_WIDTH - r.corner.x; if ((r.corner.y += curs_y) < 0) { r.extent.height += r.corner.y; r.corner.y = 0; } else if (r.corner.y + r.extent.height >= SIS_SCREEN_HEIGHT) r.extent.height = SIS_SCREEN_HEIGHT - r.corner.y; #ifndef OLD RepairBackRect (&r); #else /* NEW */ r.extent.height += r.corner.y & 1; r.corner.y &= ~1; UnlockMutex (GraphicsLock); DrawStarMap (0, &r); LockMutex (GraphicsLock); #endif /* OLD */ } static void ZoomStarMap (SIZE dir) { #define MAX_ZOOM_SHIFT 4 if (dir > 0) { if (LOBYTE (pMenuState->delta_item) < MAX_ZOOM_SHIFT) { ++pMenuState->delta_item; pMenuState->flash_rect1.corner = pMenuState->first_item; DrawStarMap (0, NULL_PTR); SleepThread (ONE_SECOND >> 3); } } else if (dir < 0) { if (LOBYTE (pMenuState->delta_item)) { if (LOBYTE (pMenuState->delta_item) > 1) pMenuState->flash_rect1.corner = pMenuState->first_item; else { pMenuState->flash_rect1.corner.x = MAX_X_UNIVERSE >> 1; pMenuState->flash_rect1.corner.y = MAX_Y_UNIVERSE >> 1; } --pMenuState->delta_item; DrawStarMap (0, NULL_PTR); SleepThread (ONE_SECOND >> 3); } } } static void UpdateCursorLocation (PMENU_STATE pMS, int sx, int sy, const POINT *newpt) { STAMP s; POINT pt; pt.x = UNIVERSE_TO_DISPX (pMS->first_item.x); pt.y = UNIVERSE_TO_DISPY (pMS->first_item.y); if (newpt) { // absolute move sx = sy = 0; s.origin.x = UNIVERSE_TO_DISPX (newpt->x); s.origin.y = UNIVERSE_TO_DISPY (newpt->y); pMS->first_item = *newpt; } else { // incremental move s.origin.x = pt.x + sx; s.origin.y = pt.y + sy; } if (sx) { pMS->first_item.x = DISP_TO_UNIVERSEX (s.origin.x) - sx; while (UNIVERSE_TO_DISPX (pMS->first_item.x) == pt.x) { pMS->first_item.x += sx; if (pMS->first_item.x < 0) { pMS->first_item.x = 0; break; } else if (pMS->first_item.x > MAX_X_UNIVERSE) { pMS->first_item.x = MAX_X_UNIVERSE; break; } } s.origin.x = UNIVERSE_TO_DISPX (pMS->first_item.x); } if (sy) { pMS->first_item.y = DISP_TO_UNIVERSEY (s.origin.y) + sy; while (UNIVERSE_TO_DISPY (pMS->first_item.y) == pt.y) { pMS->first_item.y -= sy; if (pMS->first_item.y < 0) { pMS->first_item.y = 0; break; } else if (pMS->first_item.y > MAX_Y_UNIVERSE) { pMS->first_item.y = MAX_Y_UNIVERSE; break; } } s.origin.y = UNIVERSE_TO_DISPY (pMS->first_item.y); } if (s.origin.x < 0 || s.origin.y < 0 || s.origin.x >= SIS_SCREEN_WIDTH || s.origin.y >= SIS_SCREEN_HEIGHT) { pMS->flash_rect1.corner = pMS->first_item; DrawStarMap (0, NULL_PTR); s.origin.x = UNIVERSE_TO_DISPX (pMS->first_item.x); s.origin.y = UNIVERSE_TO_DISPY (pMS->first_item.y); } else { LockMutex (GraphicsLock); EraseCursor (pt.x, pt.y); // ClearDrawable (); DrawCursor (s.origin.x, s.origin.y); UnlockMutex (GraphicsLock); } } #define CURSOR_INFO_BUFSIZE 256 static void UpdateCursorInfo (PMENU_STATE pMS, UNICODE *prevbuf) { UNICODE buf[CURSOR_INFO_BUFSIZE] = ""; POINT pt; STAR_DESCPTR SDPtr, BestSDPtr; pt.x = UNIVERSE_TO_DISPX (pMS->first_item.x); pt.y = UNIVERSE_TO_DISPY (pMS->first_item.y); SDPtr = BestSDPtr = 0; while ((SDPtr = FindStar (SDPtr, &pMS->first_item, 75, 75))) { if (UNIVERSE_TO_DISPX (SDPtr->star_pt.x) == pt.x && UNIVERSE_TO_DISPY (SDPtr->star_pt.y) == pt.y && (BestSDPtr == 0 || STAR_TYPE (SDPtr->Type) >= STAR_TYPE (BestSDPtr->Type))) BestSDPtr = SDPtr; } if (BestSDPtr) { pMS->first_item = BestSDPtr->star_pt; GetClusterName (BestSDPtr, buf); } if (GET_GAME_STATE (ARILOU_SPACE)) { POINT ari_pt; if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { ari_pt.x = ARILOU_SPACE_X; ari_pt.y = ARILOU_SPACE_Y; } else { ari_pt.x = QUASI_SPACE_X; ari_pt.y = QUASI_SPACE_Y; } if (UNIVERSE_TO_DISPX (ari_pt.x) == pt.x && UNIVERSE_TO_DISPY (ari_pt.y) == pt.y) { pMS->first_item = ari_pt; utf8StringCopy (buf, sizeof (buf), GAME_STRING (STAR_STRING_BASE + 132)); } } LockMutex (GraphicsLock); DrawHyperCoords (pMS->first_item); if (strcmp (buf, prevbuf) != 0) { strcpy (prevbuf, buf); DrawSISMessage (buf); } UnlockMutex (GraphicsLock); } static void UpdateFuelRequirement (PMENU_STATE pMS) { UNICODE buf[80]; COUNT fuel_required; DWORD f; POINT pt; if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) pt = CurStarDescPtr->star_pt; else { pt.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); pt.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); } pt.x -= pMS->first_item.x; pt.y -= pMS->first_item.y; f = (DWORD)((long)pt.x * pt.x + (long)pt.y * pt.y); if (f == 0 || GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1) fuel_required = 0; else fuel_required = square_root (f) + (FUEL_TANK_SCALE / 20); sprintf (buf, "%s %u.%u", GAME_STRING (NAVIGATION_STRING_BASE + 4), fuel_required / FUEL_TANK_SCALE, (fuel_required % FUEL_TANK_SCALE) / 10); LockMutex (GraphicsLock); DrawStatusMessage (buf); UnlockMutex (GraphicsLock); } #define STAR_SEARCH_BUFSIZE 256 typedef struct starsearch_state { PMENU_STATE pMS; UNICODE Text[STAR_SEARCH_BUFSIZE]; UNICODE LastText[STAR_SEARCH_BUFSIZE]; DWORD LastChangeTime; int FirstIndex; int CurIndex; int LastIndex; BOOLEAN SingleClust; BOOLEAN SingleMatch; UNICODE Buffer[STAR_SEARCH_BUFSIZE]; const UNICODE *Prefix; const UNICODE *Cluster; int PrefixLen; int ClusterLen; int ClusterPos; int SortedStars[NUM_SOLAR_SYSTEMS]; } STAR_SEARCH_STATE; static int compStarName (const void *ptr1, const void *ptr2) { int index1; int index2; index1 = *(const int *) ptr1; index2 = *(const int *) ptr2; if (star_array[index1].Postfix != star_array[index2].Postfix) { return utf8StringCompare (GAME_STRING (star_array[index1].Postfix), GAME_STRING (star_array[index2].Postfix)); } if (star_array[index1].Prefix < star_array[index2].Prefix) return -1; if (star_array[index1].Prefix > star_array[index2].Prefix) return 1; return 0; } static void SortStarsOnName (STAR_SEARCH_STATE *pSS) { int i; int *sorted = pSS->SortedStars; for (i = 0; i < NUM_SOLAR_SYSTEMS; i++) sorted[i] = i; qsort (sorted, NUM_SOLAR_SYSTEMS, sizeof (int), compStarName); } static void SplitStarName (STAR_SEARCH_STATE *pSS) { UNICODE *buf = pSS->Buffer; UNICODE *next; UNICODE *sep; pSS->Prefix = 0; pSS->PrefixLen = 0; pSS->Cluster = 0; pSS->ClusterLen = 0; pSS->ClusterPos = 0; // skip leading space for (next = buf; *next != '\0' && getCharFromString ((const UNICODE **)&next) == ' '; buf = next) ; if (*buf == '\0') { // no text return; } pSS->Prefix = buf; // See if player gave a prefix for (buf = next; *next != '\0' && getCharFromString ((const UNICODE **)&next) != ' '; buf = next) ; if (*buf != '\0') { // found possibly separating ' ' sep = buf; // skip separating space for (buf = next; *next != '\0' && getCharFromString ((const UNICODE **)&next) == ' '; buf = next) ; } if (*buf == '\0') { // reached the end -- cluster only pSS->Cluster = pSS->Prefix; pSS->ClusterLen = utf8StringCount (pSS->Cluster); pSS->ClusterPos = utf8StringCountN (pSS->Buffer, pSS->Cluster); pSS->Prefix = 0; return; } // consider the rest cluster name (whatever there is) pSS->Cluster = buf; pSS->ClusterLen = utf8StringCount (pSS->Cluster); pSS->ClusterPos = utf8StringCountN (pSS->Buffer, pSS->Cluster); *sep = '\0'; // split pSS->PrefixLen = utf8StringCount (pSS->Prefix); } static inline int SkipStarCluster (int *sortedStars, int istar) { int Postfix = star_array[sortedStars[istar]].Postfix; for (++istar; istar < NUM_SOLAR_SYSTEMS && star_array[sortedStars[istar]].Postfix == Postfix; ++istar) ; return istar; } static int FindNextStarIndex (STAR_SEARCH_STATE *pSS, int from, BOOLEAN WithinClust) { int i; if (!pSS->Cluster) return -1; // nothing to search for for (i = from; i < NUM_SOLAR_SYSTEMS; ++i) { STAR_DESCPTR SDPtr = &star_array[pSS->SortedStars[i]]; UNICODE FullName[STAR_SEARCH_BUFSIZE]; UNICODE *ClusterName = GAME_STRING (SDPtr->Postfix); const UNICODE *sptr; const UNICODE *dptr; int dlen; int c; dlen = utf8StringCount (ClusterName); if (pSS->ClusterLen > dlen) { // no match, skip the rest of cluster i = SkipStarCluster (pSS->SortedStars, i) - 1; continue; } for (c = 0, sptr = pSS->Cluster, dptr = ClusterName; c < pSS->ClusterLen; ++c) { wchar_t sc = getCharFromString (&sptr); wchar_t dc = getCharFromString (&dptr); if (toWideUpper (sc) != toWideUpper (dc)) break; } if (c < pSS->ClusterLen) { // no match here, skip the rest of cluster i = SkipStarCluster (pSS->SortedStars, i) - 1; continue; } if (!SDPtr->Prefix || WithinClust) // singular star - prefix not checked // or searching within clusters break; if (!pSS->Prefix) { // searching for cluster name only // return only the first stars in a cluster if (i == 0 || SDPtr->Postfix != star_array[pSS->SortedStars[i - 1]].Postfix) { // found one break; } else { // another star in the same cluster, skip cluster i = SkipStarCluster (pSS->SortedStars, i) - 1; continue; } } // check prefix GetClusterName (SDPtr, FullName); dlen = utf8StringCount (FullName); if (pSS->PrefixLen > dlen) continue; for (c = 0, sptr = pSS->Prefix, dptr = FullName; c < pSS->PrefixLen; ++c) { wchar_t sc = getCharFromString (&sptr); wchar_t dc = getCharFromString (&dptr); if (toWideUpper (sc) != toWideUpper (dc)) break; } if (c >= pSS->PrefixLen) break; // found one } return (i < NUM_SOLAR_SYSTEMS) ? i : -1; } static void DrawMatchedStarName (PTEXTENTRY_STATE pTES) { STAR_SEARCH_STATE *pSS = (STAR_SEARCH_STATE *) pTES->CbParam; PMENU_STATE pMS = pSS->pMS; UNICODE buf[STAR_SEARCH_BUFSIZE] = ""; SIZE ExPos = 0; SIZE CurPos = -1; STAR_DESCPTR SDPtr = &star_array[pSS->SortedStars[pSS->CurIndex]]; COUNT flags; if (pSS->SingleClust || pSS->SingleMatch) { // draw full star name GetClusterName (SDPtr, buf); ExPos = -1; flags = DSME_SETFR; } else { // draw substring match UNICODE *pstr = buf; strcpy (pstr, pSS->Text); ExPos = pSS->ClusterPos; pstr = skipUTF8Chars (pstr, pSS->ClusterPos); strcpy (pstr, GAME_STRING (SDPtr->Postfix)); ExPos += pSS->ClusterLen; CurPos = pTES->CursorPos; flags = DSME_CLEARFR; if (pTES->JoystickMode) flags |= DSME_BLOCKCUR; } LockMutex (GraphicsLock); DrawSISMessageEx (buf, CurPos, ExPos, flags); DrawHyperCoords (pMS->first_item); UnlockMutex (GraphicsLock); } static void MatchNextStar (STAR_SEARCH_STATE *pSS, BOOLEAN Reset) { if (Reset) pSS->FirstIndex = -1; // reset cache if (pSS->FirstIndex < 0) { // first time after changes pSS->CurIndex = -1; pSS->LastIndex = -1; pSS->SingleClust = FALSE; pSS->SingleMatch = FALSE; strcpy (pSS->Buffer, pSS->Text); SplitStarName (pSS); } pSS->CurIndex = FindNextStarIndex (pSS, pSS->CurIndex + 1, pSS->SingleClust); if (pSS->FirstIndex < 0) // first search pSS->FirstIndex = pSS->CurIndex; if (pSS->CurIndex >= 0) { // remember as last (searching forward-only) pSS->LastIndex = pSS->CurIndex; } else { // wrap around pSS->CurIndex = pSS->FirstIndex; if (pSS->FirstIndex == pSS->LastIndex && pSS->FirstIndex != -1) { if (!pSS->Prefix) { // only one cluster matching pSS->SingleClust = TRUE; } else { // exact match pSS->SingleMatch = TRUE; } } } } static BOOLEAN OnStarNameChange (PTEXTENTRY_STATE pTES) { STAR_SEARCH_STATE *pSS = (STAR_SEARCH_STATE *) pTES->CbParam; PMENU_STATE pMS = pSS->pMS; COUNT flags; BOOLEAN ret = TRUE; if (strcmp (pSS->Text, pSS->LastText) != 0) { // string changed pSS->LastChangeTime = GetTimeCounter (); strcpy (pSS->LastText, pSS->Text); // reset the search MatchNextStar (pSS, TRUE); } if (pSS->CurIndex < 0) { // nothing found if (pSS->Text[0] == '\0') flags = DSME_SETFR; else flags = DSME_CLEARFR; if (pTES->JoystickMode) flags |= DSME_BLOCKCUR; LockMutex (GraphicsLock); ret = DrawSISMessageEx (pSS->Text, pTES->CursorPos, -1, flags); UnlockMutex (GraphicsLock); } else { STAR_DESCPTR SDPtr; // move the cursor to the found star SDPtr = &star_array[pSS->SortedStars[pSS->CurIndex]]; UpdateCursorLocation (pMS, 0, 0, &SDPtr->star_pt); DrawMatchedStarName (pTES); UpdateFuelRequirement (pMS); } return ret; } static BOOLEAN OnStarNameFrame (PTEXTENTRY_STATE pTES) { STAR_SEARCH_STATE *pSS = (STAR_SEARCH_STATE *) pTES->CbParam; PMENU_STATE pMS = pSS->pMS; if (PulsedInputState.menu[KEY_MENU_NEXT]) { // search for next match STAR_DESCPTR SDPtr; MatchNextStar (pSS, FALSE); if (pSS->CurIndex < 0) { // nothing found if (PulsedInputState.menu[KEY_MENU_NEXT]) PlayMenuSound (MENU_SOUND_FAILURE); return TRUE; } // move the cursor to the found star SDPtr = &star_array[pSS->SortedStars[pSS->CurIndex]]; UpdateCursorLocation (pMS, 0, 0, &SDPtr->star_pt); DrawMatchedStarName (pTES); UpdateFuelRequirement (pMS); } return TRUE; } static BOOLEAN DoStarSearch (PMENU_STATE pMS) { TEXTENTRY_STATE tes; STAR_SEARCH_STATE *pss; BOOLEAN success; pss = HMalloc (sizeof (*pss)); if (!pss) return FALSE; LockMutex (GraphicsLock); DrawSISMessageEx ("", 0, 0, DSME_SETFR); UnlockMutex (GraphicsLock); pss->pMS = pMS; pss->LastChangeTime = 0; pss->Text[0] = '\0'; pss->LastText[0] = '\0'; pss->FirstIndex = -1; SortStarsOnName (pss); // text entry setup tes.Initialized = FALSE; tes.MenuRepeatDelay = 0; tes.BaseStr = pss->Text; tes.MaxSize = sizeof (pss->Text); tes.CursorPos = 0; tes.CbParam = pss; tes.ChangeCallback = OnStarNameChange; tes.FrameCallback = OnStarNameFrame; SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); success = DoTextEntry (&tes); LockMutex (GraphicsLock); DrawSISMessageEx (pss->Text, -1, -1, DSME_CLEARFR); UnlockMutex (GraphicsLock); HFree (pss); return success; } static BOOLEAN DoMoveCursor (PMENU_STATE pMS) { #define MIN_ACCEL_DELAY (ONE_SECOND / 60) #define MAX_ACCEL_DELAY (ONE_SECOND / 8) #define STEP_ACCEL_DELAY (ONE_SECOND / 120) static UNICODE last_buf[CURSOR_INFO_BUFSIZE]; pMS->MenuRepeatDelay = (COUNT)pMS->CurState; if (!pMS->Initialized) { pMS->Initialized = TRUE; pMS->InputFunc = DoMoveCursor; SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); SetMenuRepeatDelay (MIN_ACCEL_DELAY, MAX_ACCEL_DELAY, STEP_ACCEL_DELAY, TRUE); pMS->flash_task = AssignTask (flash_cursor_func, 2048, "flash location on star map"); last_buf[0] = '\0'; UpdateCursorInfo (pMS, last_buf); UpdateFuelRequirement (pMS); return TRUE; } else if (PulsedInputState.menu[KEY_MENU_CANCEL]) { if (pMS->flash_task) { ConcludeTask (pMS->flash_task); pMS->flash_task = 0; } return (FALSE); } else if (PulsedInputState.menu[KEY_MENU_SELECT]) { GLOBAL (autopilot) = pMS->first_item; #ifdef DEBUG if (instantMove) { PlayMenuSound (MENU_SOUND_INVOKED); if (pMS->flash_task) { ConcludeTask (pMS->flash_task); pMS->flash_task = 0; } if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { // Move to the new location immediately. doInstantMove (); } else if (LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY) { // We're in a solar system; exit it. GLOBAL (CurrentActivity) |= END_INTERPLANETARY; // Set a hook to move to the new location: debugHook = doInstantMove; } return (FALSE); } #endif DrawStarMap (0, NULL_PTR); } else if (PulsedInputState.menu[KEY_MENU_SEARCH]) { if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { // HyperSpace search POINT oldpt = pMS->first_item; if (!DoStarSearch (pMS)) { // search failed or canceled - return cursor UpdateCursorLocation (pMS, 0, 0, &oldpt); } // make sure cmp fails strcpy (last_buf, " "); UpdateCursorInfo (pMS, last_buf); UpdateFuelRequirement (pMS); SetMenuRepeatDelay (MIN_ACCEL_DELAY, MAX_ACCEL_DELAY, STEP_ACCEL_DELAY, TRUE); SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); } else { // no search in QuasiSpace PlayMenuSound (MENU_SOUND_FAILURE); } } else { SBYTE sx, sy; SIZE ZoomIn, ZoomOut; ZoomIn = ZoomOut = 0; if (PulsedInputState.menu[KEY_MENU_ZOOM_IN]) ZoomIn = 1; else if (PulsedInputState.menu[KEY_MENU_ZOOM_OUT]) ZoomOut = 1; ZoomStarMap (ZoomIn - ZoomOut); sx = sy = 0; if (PulsedInputState.menu[KEY_MENU_LEFT]) sx = -1; if (PulsedInputState.menu[KEY_MENU_RIGHT]) sx = 1; if (PulsedInputState.menu[KEY_MENU_UP]) sy = -1; if (PulsedInputState.menu[KEY_MENU_DOWN]) sy = 1; if (sx != 0 || sy != 0) { UpdateCursorLocation (pMS, sx, sy, NULL_PTR); UpdateCursorInfo (pMS, last_buf); UpdateFuelRequirement (pMS); } } { BOOLEAN result = !(GLOBAL (CurrentActivity & CHECK_ABORT)); if (!result) { if (pMS->flash_task) { ConcludeTask (pMS->flash_task); pMS->flash_task = 0; } } return result; } } static void RepairMap (COUNT update_race, PRECT pLastRect, PRECT pNextRect) { RECT r; /* make a rect big enough for text */ r.extent.width = 50; r.corner.x = (pNextRect->corner.x + (pNextRect->extent.width >> 1)) - (r.extent.width >> 1); if (r.corner.x < 0) r.corner.x = 0; else if (r.corner.x + r.extent.width >= SIS_SCREEN_WIDTH) r.corner.x = SIS_SCREEN_WIDTH - r.extent.width; r.extent.height = 9; r.corner.y = (pNextRect->corner.y + (pNextRect->extent.height >> 1)) - r.extent.height; if (r.corner.y < 0) r.corner.y = 0; else if (r.corner.y + r.extent.height >= SIS_SCREEN_HEIGHT) r.corner.y = SIS_SCREEN_HEIGHT - r.extent.height; BoxUnion (pLastRect, &r, &r); BoxUnion (pNextRect, &r, &r); *pLastRect = *pNextRect; if (r.corner.x < 0) { r.extent.width += r.corner.x; r.corner.x = 0; } if (r.corner.x + r.extent.width > SIS_SCREEN_WIDTH) r.extent.width = SIS_SCREEN_WIDTH - r.corner.x; if (r.corner.y < 0) { r.extent.height += r.corner.y; r.corner.y = 0; } if (r.corner.y + r.extent.height > SIS_SCREEN_HEIGHT) r.extent.height = SIS_SCREEN_HEIGHT - r.corner.y; r.extent.height += r.corner.y & 1; r.corner.y &= ~1; DrawStarMap (update_race, &r); } static void UpdateMap (void) { BYTE ButtonState, VisibleChange; BOOLEAN MapDrawn, Interrupted; COUNT index; HSTARSHIP hStarShip, hNextShip; FlushInput (); ButtonState = 1; /* assume a button down */ MapDrawn = Interrupted = FALSE; for (index = 1, hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); hStarShip; ++index, hStarShip = hNextShip) { EXTENDED_SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip ); hNextShip = _GetSuccLink (StarShipPtr); if (ButtonState) { if (!AnyButtonPress (TRUE)) ButtonState = 0; } else if ((Interrupted = (BOOLEAN)( Interrupted || AnyButtonPress (TRUE) ))) MapDrawn = TRUE; if (StarShipPtr->ShipInfo.known_strength) { SIZE dx, dy, delta; RECT r, last_r, temp_r0, temp_r1; dx = StarShipPtr->ShipInfo.loc.x - StarShipPtr->ShipInfo.known_loc.x; dy = StarShipPtr->ShipInfo.loc.y - StarShipPtr->ShipInfo.known_loc.y; if (dx || dy) { SIZE xincr, yincr, xerror, yerror, cycle; if (dx >= 0) xincr = 1; else { xincr = -1; dx = -dx; } dx <<= 1; if (dy >= 0) yincr = 1; else { yincr = -1; dy = -dy; } dy <<= 1; if (dx >= dy) cycle = dx; else cycle = dy; delta = xerror = yerror = cycle >> 1; if (!MapDrawn) { DrawStarMap ((COUNT)~0, NULL_PTR); MapDrawn = TRUE; } GetSphereRect (StarShipPtr, &temp_r0, &last_r); ++last_r.extent.width; ++last_r.extent.height; VisibleChange = FALSE; do { do { if ((xerror -= dx) <= 0) { StarShipPtr->ShipInfo.known_loc.x += xincr; xerror += cycle; } if ((yerror -= dy) <= 0) { StarShipPtr->ShipInfo.known_loc.y += yincr; yerror += cycle; } GetSphereRect (StarShipPtr, &temp_r1, &r); } while (delta-- && ((delta & 0x1F) || (temp_r0.corner.x == temp_r1.corner.x && temp_r0.corner.y == temp_r1.corner.y))); if (ButtonState) { if (!AnyButtonPress (TRUE)) ButtonState = 0; } else if ((Interrupted = (BOOLEAN)( Interrupted || AnyButtonPress (TRUE) ))) { MapDrawn = TRUE; goto DoneSphereMove; } ++r.extent.width; ++r.extent.height; if (temp_r0.corner.x != temp_r1.corner.x || temp_r0.corner.y != temp_r1.corner.y) { VisibleChange = TRUE; RepairMap (index, &last_r, &r); } } while (delta >= 0); if (VisibleChange) RepairMap ((COUNT)~0, &last_r, &r); DoneSphereMove: StarShipPtr->ShipInfo.known_loc = StarShipPtr->ShipInfo.loc; } delta = StarShipPtr->ShipInfo.actual_strength - StarShipPtr->ShipInfo.known_strength; if (delta) { if (!MapDrawn) { DrawStarMap ((COUNT)~0, NULL_PTR); MapDrawn = TRUE; } if (delta > 0) dx = 1; else { delta = -delta; dx = -1; } --delta; GetSphereRect (StarShipPtr, &temp_r0, &last_r); ++last_r.extent.width; ++last_r.extent.height; VisibleChange = FALSE; do { do { StarShipPtr->ShipInfo.known_strength += dx; GetSphereRect (StarShipPtr, &temp_r1, &r); } while (delta-- && ((delta & 0xF) || temp_r0.extent.height == temp_r1.extent.height)); if (ButtonState) { if (!AnyButtonPress (TRUE)) ButtonState = 0; } else if ((Interrupted = (BOOLEAN)( Interrupted || AnyButtonPress (TRUE) ))) { MapDrawn = TRUE; goto DoneSphereGrowth; } ++r.extent.width; ++r.extent.height; if (temp_r0.extent.height != temp_r1.extent.height) { VisibleChange = TRUE; RepairMap (index, &last_r, &r); } } while (delta >= 0); if (VisibleChange || temp_r0.extent.width != temp_r1.extent.width) RepairMap ((COUNT)~0, &last_r, &r); DoneSphereGrowth: StarShipPtr->ShipInfo.known_strength = StarShipPtr->ShipInfo.actual_strength; } } UnlockStarShip ( &GLOBAL (avail_race_q), hStarShip ); } } static BOOLEAN DoStarMap (void) { MENU_STATE MenuState; POINT universe; //FRAME OldFrame; RECT clip_r; CONTEXT OldContext; pMenuState = &MenuState; memset (pMenuState, 0, sizeof (*pMenuState)); MenuState.flash_rect1.corner.x = MAX_X_UNIVERSE >> 1; MenuState.flash_rect1.corner.y = MAX_Y_UNIVERSE >> 1; MenuState.CurFrame = SetAbsFrameIndex (MiscDataFrame, 48); MenuState.delta_item = 0; if (LOBYTE (GLOBAL (CurrentActivity)) != IN_HYPERSPACE) universe = CurStarDescPtr->star_pt; else { universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); } MenuState.first_item = GLOBAL (autopilot); if (MenuState.first_item.x == ~0 && MenuState.first_item.y == ~0) MenuState.first_item = universe; UnlockMutex (GraphicsLock); TaskSwitch (); MenuState.InputFunc = DoMoveCursor; MenuState.Initialized = FALSE; transition_pending = TRUE; if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) UpdateMap (); LockMutex (GraphicsLock); DrawStarMap (0, (PRECT)-1); transition_pending = FALSE; BatchGraphics (); OldContext = SetContext (SpaceContext); GetContextClipRect (&clip_r); SetContext (OldContext); LoadIntoExtraScreen (&clip_r); DrawCursor ( UNIVERSE_TO_DISPX (MenuState.first_item.x), UNIVERSE_TO_DISPY (MenuState.first_item.y) ); UnbatchGraphics (); UnlockMutex (GraphicsLock); DoInput ((PVOID)&MenuState, FALSE); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); pMenuState = 0; LockMutex (GraphicsLock); DrawHyperCoords (universe); DrawSISMessage (NULL_PTR); DrawStatusMessage (NULL_PTR); if (GLOBAL (autopilot.x) == universe.x && GLOBAL (autopilot.y) == universe.y) GLOBAL (autopilot.x) = GLOBAL (autopilot.y) = ~0; return (GLOBAL (autopilot.x) != ~0 && GLOBAL (autopilot.y) != ~0); } BOOLEAN DoFlagshipCommands (PMENU_STATE pMS) { /* TODO: Make this carried cleanly by MENU_STATE structure */ // static DWORD NextTime; if (!(pMS->Initialized & 1)) { /* This has some dependency on the IPtask_func */ ChangeSolarSys (); // NextTime = GetTimeCounter (); } else { BOOLEAN select = PulsedInputState.menu[KEY_MENU_SELECT]; LockMutex (GraphicsLock); if (*(volatile BYTE *)&pMS->CurState == 0 && (*(volatile SIZE *)&pMS->Initialized & 1) && !(GLOBAL (CurrentActivity) & (START_ENCOUNTER | END_INTERPLANETARY | CHECK_ABORT | CHECK_LOAD)) && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0) { UnlockMutex (GraphicsLock); IP_frame (); return TRUE; } UnlockMutex (GraphicsLock); if (pMS->CurState) { BOOLEAN DoMenu; BYTE NewState; /* If pMS->CurState == 0, then we're flying * around in interplanetary. This needs to be * corrected for the MenuChooser, which thinks * that "0" is the first menu option */ pMS->CurState --; DoMenu = DoMenuChooser (pMS, (BYTE)(pMS->Initialized <= 1 ? PM_STARMAP : PM_SCAN)); pMS->CurState ++; if (!DoMenu) { NewState = pMS->CurState; if (LastActivity == CHECK_LOAD) select = TRUE; if (select) { if (NewState != SCAN + 1 && NewState != (GAME_MENU) + 1) { LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); } switch (NewState - 1) { case SCAN: ScanSystem (); break; case EQUIP_DEVICE: { pMenuState = pMS; if (!Devices (pMS)) select = FALSE; pMenuState = 0; if (GET_GAME_STATE (PORTAL_COUNTER)) { // A player-induced portal to QuasiSpace is // opening. return (FALSE); } break; } case CARGO: { Cargo (pMS); break; } case ROSTER: { if (!Roster ()) select = FALSE; break; } case GAME_MENU: if (GameOptions () == 0) return (FALSE); break; case STARMAP: { BOOLEAN AutoPilotSet; LockMutex (GraphicsLock); if (++pMS->Initialized > 3) { pSolarSysState->PauseRotate = 1; RepairSISBorder (); } AutoPilotSet = DoStarMap (); SetDefaultMenuRepeatDelay (); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE || (GLOBAL (CurrentActivity) & CHECK_ABORT)) { UnlockMutex (GraphicsLock); return (FALSE); } else if (pMS->Initialized <= 3) { ZoomSystem (); --pMS->Initialized; } UnlockMutex (GraphicsLock); if (!AutoPilotSet && pMS->Initialized >= 3) { LoadPlanet (NULL); --pMS->Initialized; pSolarSysState->PauseRotate = 0; LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); break; } } case NAVIGATION: if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) return (FALSE); if (pMS->Initialized <= 1) { pMS->Initialized = 1; ResumeGameClock (); } else if (pMS->flash_task) { FreePlanet (); LockMutex (GraphicsLock); LoadSolarSys (); ValidateOrbits (); ZoomSystem (); UnlockMutex (GraphicsLock); } LockMutex (GraphicsLock); pMS->CurState = 0; FlushInput (); UnlockMutex (GraphicsLock); break; } if (GLOBAL (CurrentActivity) & CHECK_ABORT) ; else if (pMS->CurState) { LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); if (select) { if (optWhichMenu != OPT_PC) pMS->CurState = (NAVIGATION) + 1; DrawMenuStateStrings ((BYTE)(pMS->Initialized <= 1 ? PM_STARMAP : PM_SCAN), pMS->CurState - 1); } } else { LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); DrawMenuStateStrings (PM_STARMAP, -NAVIGATION); } } } } } return (!(GLOBAL (CurrentActivity) & (START_ENCOUNTER | END_INTERPLANETARY | CHECK_ABORT | CHECK_LOAD)) && GLOBAL_SIS (CrewEnlisted) != (COUNT)~0); } uqm-0.6.2/sc2/src/sc2code/planets/genutw.c0000600000175000017500000001743510543202100016727 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "nameref.h" #include "resinst.h" #include "setup.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateUtwig (BYTE control) { switch (control) { case INIT_NPCS: if (CurStarDescPtr->Index == BOMB_DEFINED && !GET_GAME_STATE (UTWIG_BOMB)) ReinitQueue (&GLOBAL (npc_built_ship_q)); else GenerateRandomIP (INIT_NPCS); break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); if (CurStarDescPtr->Index == UTWIG_DEFINED) { pSolarSysState->PlanetDesc[0].data_index = WATER_WORLD; pSolarSysState->PlanetDesc[0].NumPlanets = 1; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 174L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); } break; } case GENERATE_ENERGY: { DWORD rand_val, old_rand; if (CurStarDescPtr->Index == UTWIG_DEFINED && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i, which_node; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } else if (CurStarDescPtr->Index == BOMB_DEFINED && pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[5] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[1] && !GET_GAME_STATE (UTWIG_BOMB)) { old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; pSolarSysState->SysInfo.PlanetInfo.CurType = 0; if (!(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) && pSolarSysState->CurNode == (COUNT)~0) pSolarSysState->CurNode = 1; else { pSolarSysState->CurNode = 0; if (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << 0)) { SET_GAME_STATE (UTWIG_BOMB, 1); SET_GAME_STATE (UTWIG_BOMB_ON_SHIP, 1); SET_GAME_STATE (DRUUGE_MANNER, 1); SET_GAME_STATE (DRUUGE_VISITS, 0); SET_GAME_STATE (DRUUGE_HOME_VISITS, 0); } } TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; } case GENERATE_ORBITAL: if ((CurStarDescPtr->Index == UTWIG_DEFINED && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) || (CurStarDescPtr->Index == BOMB_DEFINED && pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[5] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[1] && !GET_GAME_STATE (UTWIG_BOMB))) { if ((CurStarDescPtr->Index == UTWIG_DEFINED || !GET_GAME_STATE (UTWIG_HAVE_ULTRON)) && ActivateStarShip (UTWIG_SHIP, SPHERE_TRACKING)) { NotifyOthers (UTWIG_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (UTWIG_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; if (CurStarDescPtr->Index == UTWIG_DEFINED) { SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); } else { SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); } InitCommunication (UTWIG_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } else if (CurStarDescPtr->Index == BOMB_DEFINED && !GET_GAME_STATE (BOMB_UNPROTECTED) && ActivateStarShip (DRUUGE_SHIP, SPHERE_TRACKING)) { COUNT i; PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); for (i = 0; i < 5; ++i) CloneShipFragment (DRUUGE_SHIP, &GLOBAL (npc_built_ship_q), 0); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); InitCommunication (DRUUGE_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) break; else { BOOLEAN DruugeSurvivors; DruugeSurvivors = GetHeadLink ( &GLOBAL (npc_built_ship_q) ) != 0; GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); if (DruugeSurvivors) break; LockMutex (GraphicsLock); RepairSISBorder (); UnlockMutex (GraphicsLock); SET_GAME_STATE (BOMB_UNPROTECTED, 1); } } if (CurStarDescPtr->Index == BOMB_DEFINED) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (BOMB_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (BOMB_STRTAB) ); } else { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (RUINS_STRTAB) ); } } GenerateRandomIP (GENERATE_ORBITAL); if (CurStarDescPtr->Index == UTWIG_DEFINED && pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { pSolarSysState->SysInfo.PlanetInfo.Weather = 1; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 1; } break; default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/genpet.c0000600000175000017500000001655010543202100016675 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "nameref.h" #include "resinst.h" #include "setup.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" static void ZapToUrquanEncounter (void) { HENCOUNTER hEncounter; if ((hEncounter = AllocEncounter ()) || (hEncounter = GetHeadEncounter ())) { SIZE dx, dy; ENCOUNTERPTR EncounterPtr; HSTARSHIP hStarShip; EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; LockEncounter (hEncounter, &EncounterPtr); if (hEncounter == GetHeadEncounter ()) RemoveEncounter (hEncounter); memset (EncounterPtr, 0, sizeof (*EncounterPtr)); InsertEncounter (hEncounter, GetHeadEncounter ()); hStarShip = GetStarShipFromIndex (&GLOBAL (avail_race_q), URQUAN_SHIP); TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip ); EncounterPtr->origin = TemplatePtr->ShipInfo.loc; EncounterPtr->radius = TemplatePtr->ShipInfo.actual_strength; EncounterPtr->SD.Type = URQUAN_SHIP; EncounterPtr->SD.Index = MAKE_BYTE (1, 0) | ONE_SHOT_ENCOUNTER; EncounterPtr->SD.ShipList[0] = ((SHIP_FRAGMENTPTR)TemplatePtr)->ShipInfo; EncounterPtr->SD.ShipList[0].var1 = URQUAN_SHIP; EncounterPtr->SD.star_pt.x = 5288; EncounterPtr->SD.star_pt.y = 4892; EncounterPtr->log_x = UNIVERSE_TO_LOGX (EncounterPtr->SD.star_pt.x); EncounterPtr->log_y = UNIVERSE_TO_LOGY (EncounterPtr->SD.star_pt.y); GLOBAL_SIS (log_x) = EncounterPtr->log_x; GLOBAL_SIS (log_y) = EncounterPtr->log_y; UnlockStarShip ( &GLOBAL (avail_race_q), hStarShip ); { #define LOST_DAYS 15 COUNT i; BYTE black_buf[] = {FadeAllToBlack}; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)black_buf, ONE_SECOND * 2)); for (i = 0; i < LOST_DAYS; ++i) { while (ClockTick () > 0) ; ResumeGameClock (); SleepThread (ONE_SECOND / 60); SuspendGameClock (); } } GLOBAL (CurrentActivity) = MAKE_WORD (IN_HYPERSPACE, 0) | START_ENCOUNTER; dx = CurStarDescPtr->star_pt.x - EncounterPtr->SD.star_pt.x; dy = CurStarDescPtr->star_pt.y - EncounterPtr->SD.star_pt.y; dx = (SIZE)square_root ((long)dx * dx + (long)dy * dy) + (FUEL_TANK_SCALE >> 1); LockMutex (GraphicsLock); DeltaSISGauges (0, -dx, 0); if (GLOBAL_SIS (FuelOnBoard) < 5 * FUEL_TANK_SCALE) { dx = ((5 + ((COUNT)TFB_Random () % 5)) * FUEL_TANK_SCALE) - (SIZE)GLOBAL_SIS (FuelOnBoard); DeltaSISGauges (0, dx, 0); } DrawSISMessage (NULL_PTR); DrawHyperCoords (EncounterPtr->SD.star_pt); UnlockMutex (GraphicsLock); UnlockEncounter (hEncounter); } } void GenerateTalkingPet (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i, which_node; DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = TELLURIC_WORLD; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 204L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0] && (GET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES) || !GET_GAME_STATE (TALKING_PET) || ActivateStarShip (UMGAH_SHIP, SPHERE_TRACKING))) { NotifyOthers (UMGAH_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); if (ActivateStarShip (UMGAH_SHIP, SPHERE_TRACKING)) { pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); if (!GET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES)) { CloneShipFragment (UMGAH_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); InitCommunication (UMGAH_CONVERSATION); } else { COUNT i; for (i = 0; i < 10; ++i) CloneShipFragment (UMGAH_SHIP, &GLOBAL (npc_built_ship_q), 0); InitCommunication (TALKING_PET_CONVERSATION); } pSolarSysState->MenuState.Initialized -= 2; } if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { BOOLEAN UmgahSurvivors; UmgahSurvivors = GetHeadLink ( &GLOBAL (npc_built_ship_q) ) != 0; GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; if (GET_GAME_STATE (PLAYER_HYPNOTIZED)) ZapToUrquanEncounter (); else if (GET_GAME_STATE (UMGAH_ZOMBIE_BLOBBIES) && !UmgahSurvivors) { // Defeated the zombie fleet. InitCommunication (TALKING_PET_CONVERSATION); } else if (!(ActivateStarShip (UMGAH_SHIP, SPHERE_TRACKING))) { // The Kohr-Ah have destroyed the Umgah, but the // talking pet survived. InitCommunication (TALKING_PET_CONVERSATION); } ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (RUINS_STRTAB) ); } GenerateRandomIP (GENERATE_ORBITAL); if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) pSolarSysState->SysInfo.PlanetInfo.Weather = 0; break; default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/genchmmr.c0000600000175000017500000001065210543202100017210 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "lander.h" #include "nameref.h" #include "resinst.h" #include "setup.h" #include "state.h" #include "sounds.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateChmmr (BYTE control) { switch (control) { case GENERATE_MOONS: GenerateRandomIP (GENERATE_MOONS); if (pSolarSysState->pBaseDesc == &pSolarSysState->PlanetDesc[1]) { COUNT angle; DWORD rand_val; pSolarSysState->MoonDesc[0].data_index = (BYTE)~0; pSolarSysState->MoonDesc[0].radius = MIN_MOON_RADIUS; rand_val = TFB_Random (); angle = NORMALIZE_ANGLE (LOWORD (rand_val)); pSolarSysState->MoonDesc[0].location.x = COSINE (angle, pSolarSysState->MoonDesc[0].radius); pSolarSysState->MoonDesc[0].location.y = SINE (angle, pSolarSysState->MoonDesc[0].radius); } break; case GENERATE_PLANETS: GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[1].data_index = SAPPHIRE_WORLD; if (!GET_GAME_STATE (CHMMR_UNLEASHED)) pSolarSysState->PlanetDesc[1].data_index |= PLANET_SHIELDED; pSolarSysState->PlanetDesc[1].NumPlanets = 1; break; case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[1]) { if (GET_GAME_STATE (CHMMR_UNLEASHED)) { pSolarSysState->MenuState.Initialized += 2; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); InitCommunication (CHMMR_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (GET_GAME_STATE (CHMMR_BOMB_STATE) == 2) { GLOBAL (CurrentActivity) |= END_INTERPLANETARY; } break; } else if (GET_GAME_STATE (SUN_DEVICE_ON_SHIP) && !GET_GAME_STATE (ILWRATH_DECEIVED) && ActivateStarShip (ILWRATH_SHIP, SPHERE_TRACKING)) { PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (ILWRATH_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 6); GLOBAL (CurrentActivity) |= START_INTERPLANETARY; InitCommunication (ILWRATH_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } } /* Starbase */ else if (pSolarSysState->pOrbitalDesc->pPrevDesc == &pSolarSysState->PlanetDesc[1] && pSolarSysState->pOrbitalDesc == &pSolarSysState->MoonDesc[0]) { RECT r; LockMutex (GraphicsLock); LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (CHMMR_BASE_STRTAB)); ScanContext = CaptureContext (CreateContext ()); SetContext (ScanContext); SetContextFGFrame (Screen); r.corner.x = (SIS_ORG_X + SIS_SCREEN_WIDTH) - MAP_WIDTH; r.corner.y = (SIS_ORG_Y + SIS_SCREEN_HEIGHT) - MAP_HEIGHT; r.extent.width = MAP_WIDTH; r.extent.height = MAP_HEIGHT; SetContextClipRect (&r); DoDiscoveryReport (MenuSounds); SetContext (SpaceContext); DestroyContext (ReleaseContext (ScanContext)); ScanContext = 0; DestroyStringTable (ReleaseStringTable ( pSolarSysState->SysInfo.PlanetInfo.DiscoveryString )); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = 0; FreeLanderFont (&pSolarSysState->SysInfo.PlanetInfo); UnlockMutex (GraphicsLock); break; } default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/gentopo.c0000600000175000017500000001057410543202100017066 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // See doc/devel/planettopo for details. #include "gfxlib.h" #include "mathlib.h" #include "planets.h" void DeltaTopography (COUNT num_iterations, PSBYTE DepthArray, PRECT pRect, SIZE depth_delta) { SIZE width, height, delta_y; struct { COORD x_top, x_bot; SIZE x_incr, delta_x, error_term; } LineDDA0, LineDDA1; width = pRect->extent.width; height = pRect->extent.height; delta_y = (height - 1) << 1; do { SIZE d; COUNT h, w1, w2; DWORD rand_val; PSBYTE lpDst; depth_delta = ((((SIZE)TFB_Random () & 1) << 1) - 1) * depth_delta; rand_val = TFB_Random (); w1 = LOWORD (rand_val); w2 = HIWORD (rand_val); LineDDA0.x_top = LOBYTE (w1) % width; LineDDA0.x_bot = HIBYTE (w1) % width; LineDDA0.delta_x = (LineDDA0.x_bot - LineDDA0.x_top) << 1; if (LineDDA0.delta_x >= 0) LineDDA0.x_incr = 1; else { LineDDA0.x_incr = -1; LineDDA0.delta_x = -LineDDA0.delta_x; } if (LineDDA0.delta_x > delta_y) LineDDA0.error_term = -(LineDDA0.delta_x >> 1); else LineDDA0.error_term = -(delta_y >> 1); LineDDA1.x_top = (LOBYTE (w2) % (width - 1)) + LineDDA0.x_top + 1; LineDDA1.x_bot = (HIBYTE (w2) % (width - 1)) + LineDDA0.x_bot + 1; LineDDA1.delta_x = (LineDDA1.x_bot - LineDDA1.x_top) << 1; if (LineDDA1.delta_x >= 0) LineDDA1.x_incr = 1; else { LineDDA1.x_incr = -1; LineDDA1.delta_x = -LineDDA1.delta_x; } if (LineDDA1.delta_x > delta_y) LineDDA1.error_term = -(LineDDA1.delta_x >> 1); else LineDDA1.error_term = -(delta_y >> 1); lpDst = &DepthArray[LineDDA0.x_top]; h = height; do { COUNT w; w1 = LineDDA1.x_top - LineDDA0.x_top; w2 = width - w1; if ((int)(LineDDA0.x_top + w1) > (int)width) w = width - LineDDA0.x_top; else { w = w1; LineDDA0.x_top += w1; } w1 -= w; while (w--) { d = *lpDst + depth_delta; if (d >= -128 && d <= 127) *lpDst = (SBYTE)d; ++lpDst; } if (w1 == 0) { if (LineDDA0.x_top == width) { LineDDA0.x_top = 0; lpDst -= width; } } else { LineDDA0.x_top = w1; lpDst -= width; do { d = *lpDst + depth_delta; if (d >= -128 && d <= 127) *lpDst = (SBYTE)d; ++lpDst; } while (--w1); } if ((int)(LineDDA0.x_top + w2) > (int)width) w = width - LineDDA0.x_top; else { w = w2; LineDDA0.x_top += w2; } w2 -= w; while (w--) { d = *lpDst - depth_delta; if (d >= -128 && d <= 127) *lpDst = (SBYTE)d; ++lpDst; } if (w2 == 0) { if (LineDDA0.x_top == width) { LineDDA0.x_top = 0; lpDst -= width; } } else { LineDDA0.x_top = w2; lpDst -= width; do { d = *lpDst - depth_delta; if (d >= -128 && d <= 127) *lpDst = (SBYTE)d; ++lpDst; } while (--w2); } lpDst += pRect->extent.width; if (delta_y >= LineDDA0.delta_x) { if ((LineDDA0.error_term += LineDDA0.delta_x) >= 0) { lpDst += LineDDA0.x_incr; LineDDA0.x_top += LineDDA0.x_incr; LineDDA0.error_term -= delta_y; } } else { do { lpDst += LineDDA0.x_incr; LineDDA0.x_top += LineDDA0.x_incr; } while ((LineDDA0.error_term += delta_y) < 0); LineDDA0.error_term -= LineDDA0.delta_x; } if (delta_y >= LineDDA1.delta_x) { if ((LineDDA1.error_term += LineDDA1.delta_x) >= 0) { LineDDA1.x_top += LineDDA1.x_incr; LineDDA1.error_term -= delta_y; } } else { do { LineDDA1.x_top += LineDDA1.x_incr; } while ((LineDDA1.error_term += delta_y) < 0); LineDDA1.error_term -= LineDDA1.delta_x; } } while (--h); } while (--num_iterations); } uqm-0.6.2/sc2/src/sc2code/planets/lander.h0000600000175000017500000000333710543202100016664 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _LANDER_H #define _LANDER_H #include "planets/elemdata.h" #include "libs/compiler.h" #include "libs/gfxlib.h" #include "libs/sndlib.h" #include "menustat.h" #define NUM_TEXT_FRAMES 32 typedef struct { BOOLEAN InTransit; // Landing on or taking of from a planet. // Setting it while landed will initiate takeoff. SOUND OldMenuSounds; COUNT ElementLevel, MaxElementLevel, BiologicalLevel; COUNT ElementAmounts[NUM_ELEMENT_CATEGORIES]; COUNT NumFrames; UNICODE AmountBuf[40]; TEXT MineralText[3]; COLOR ColorCycle[NUM_TEXT_FRAMES >> 1]; BYTE TectonicsChance, WeatherChance, FireChance; } PLANETSIDE_DESC; typedef PLANETSIDE_DESC *PPLANETSIDE_DESC; extern CONTEXT ScanContext; extern MUSIC_REF LanderMusic; extern void PlanetSide (PMENU_STATE pMS); extern void DoDiscoveryReport (SOUND ReadOutSounds); extern void SetPlanetMusic (BYTE planet_type); extern void LoadLanderData (void); extern void FreeLanderData (void); #endif /* _LANDER_H */ uqm-0.6.2/sc2/src/sc2code/planets/genmel.c0000600000175000017500000000477310543202077016703 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "state.h" #include "planets/genall.h" #include "libs/log.h" static int SelectMelnormeRefVar (void) { int RefVar; switch (CurStarDescPtr->Index) { case MELNORME0_DEFINED: RefVar = MELNORME0_GRPOFFS0; break; case MELNORME1_DEFINED: RefVar = MELNORME1_GRPOFFS0; break; case MELNORME2_DEFINED: RefVar = MELNORME2_GRPOFFS0; break; case MELNORME3_DEFINED: RefVar = MELNORME3_GRPOFFS0; break; case MELNORME4_DEFINED: RefVar = MELNORME4_GRPOFFS0; break; case MELNORME5_DEFINED: RefVar = MELNORME5_GRPOFFS0; break; case MELNORME6_DEFINED: RefVar = MELNORME6_GRPOFFS0; break; case MELNORME7_DEFINED: RefVar = MELNORME7_GRPOFFS0; break; case MELNORME8_DEFINED: RefVar = MELNORME8_GRPOFFS0; break; default: RefVar = -1; } return RefVar; } static DWORD GetMelnormeRef (void) { int RefVar = SelectMelnormeRefVar (); if (RefVar < 0) { log_add (log_Warning, "GetMelnormeRef(): reference unknown"); return 0; } return GET_GAME_STATE_32 (RefVar); } static void SetMelnormeRef (DWORD Ref) { int RefVar = SelectMelnormeRefVar (); if (RefVar < 0) { log_add (log_Warning, "SetMelnormeRef(): reference unknown"); return; } SET_GAME_STATE_32 (RefVar, Ref); } void GenerateMelnorme (BYTE control) { switch (control) { case INIT_NPCS: GLOBAL (BattleGroupRef) = GetMelnormeRef (); if (GLOBAL (BattleGroupRef) == 0) { CloneShipFragment (MELNORME_SHIP, &GLOBAL (npc_built_ship_q), 0); GLOBAL (BattleGroupRef) = PutGroupInfo (GROUPS_ADD_NEW, 1); SetMelnormeRef (GLOBAL (BattleGroupRef)); } GenerateRandomIP (INIT_NPCS); break; default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/planets/plandata.h0000600000175000017500000002061210543202100017176 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _PLANDATA_H #define _PLANDATA_H #include "libs/reslib.h" /*------------------------------ Type Defines ----------------------------- */ #define NUMBER_OF_ORBITS 16 #define VACANT 0xFF enum { SMALL_ROCKY_WORLD = 0, LARGE_ROCKY_WORLD, GAS_GIANT, NUM_PLANET_TYPES }; enum { DWARF_STAR = 0, GIANT_STAR, SUPER_GIANT_STAR, NUM_STAR_TYPES }; enum { BLUE_BODY = 0, GREEN_BODY, ORANGE_BODY, RED_BODY, WHITE_BODY, GRAY_BODY = WHITE_BODY, YELLOW_BODY, NUM_STAR_COLORS, CYAN_BODY = NUM_STAR_COLORS, PURPLE_BODY, VIOLET_BODY }; enum { OWNER_NOBODY = 0, OWNER_NEUTRAL, OWNER_HIERARCHY, OWNER_PLAYER = (1 << 2) }; #define STAR_OWNER_SHIFT 0 #define STAR_TYPE_SHIFT 3 /* STAR_OWNER_SHIFT + 3 */ #define STAR_COLOR_SHIFT 5 /* STAR_TYPE_SHIFT + 2 */ #define STAR_COLOR_MASK (BYTE)(0xFF << STAR_COLOR_SHIFT) #define STAR_TYPE_MASK (BYTE)((0xFF << STAR_TYPE_SHIFT) \ & ~STAR_COLOR_MASK) #define STAR_OWNER_MASK (BYTE)((0xFF << STAR_OWNER_SHIFT) \ & ~(STAR_COLOR_MASK \ | STAR_TYPE_MASK)) #define STAR_UNKNOWN_MASK (STAR_OWNER_MASK & ~OWNER_PLAYER) #define MAKE_STAR(t,c,o) \ (BYTE)((((BYTE)(t) << STAR_TYPE_SHIFT) & STAR_TYPE_MASK) \ | (((BYTE)(c) << STAR_COLOR_SHIFT) & STAR_COLOR_MASK) \ | (((BYTE)(o) << STAR_OWNER_SHIFT) & STAR_OWNER_MASK)) #define STAR_TYPE(f) (BYTE)(((f) & STAR_TYPE_MASK) >> STAR_TYPE_SHIFT) #define STAR_COLOR(f) (BYTE)(((f) & STAR_COLOR_MASK) >> STAR_COLOR_SHIFT) #define STAR_OWNER(f) (BYTE)(((f) & STAR_OWNER_MASK) >> STAR_OWNER_SHIFT) #define STAR_UNKNOWN(f) (BOOLEAN)((STAR_OWNER(f) \ & STAR_UNKNOWN_MASK) == STAR_UNKNOWN_MASK) #define PLAN_SIZE_MASK 0x03 #define TOPO_ALGO (0 << 2) #define CRATERED_ALGO (1 << 2) #define GAS_GIANT_ALGO (2 << 2) #define PLAN_ALGO_MASK 0x0C #define PLANSIZE(type) ((BYTE)((type) & PLAN_SIZE_MASK)) #define PLANALGO(type) ((BYTE)((type) & PLAN_ALGO_MASK)) #define PLANCOLOR(type) HINIBBLE (type) #define THIN_ATMOSPHERE 10 #define NORMAL_ATMOSPHERE 75 #define THICK_ATMOSPHERE 200 #define SUPER_THICK_ATMOSPHERE 2500 #define GAS_GIANT_ATMOSPHERE 0xFFFF enum { FIRST_ROCKY_WORLD = 0, FIRST_SMALL_ROCKY_WORLD = FIRST_ROCKY_WORLD, OOLITE_WORLD = FIRST_SMALL_ROCKY_WORLD, YTTRIC_WORLD, QUASI_DEGENERATE_WORLD, LANTHANIDE_WORLD, TREASURE_WORLD, UREA_WORLD, METAL_WORLD, RADIOACTIVE_WORLD, OPALESCENT_WORLD, CYANIC_WORLD, ACID_WORLD, ALKALI_WORLD, HALIDE_WORLD, GREEN_WORLD, COPPER_WORLD, CARBIDE_WORLD, ULTRAMARINE_WORLD, NOBLE_WORLD, AZURE_WORLD, CHONDRITE_WORLD, PURPLE_WORLD, SUPER_DENSE_WORLD, PELLUCID_WORLD, DUST_WORLD, CRIMSON_WORLD, CIMMERIAN_WORLD, INFRARED_WORLD, SELENIC_WORLD, AURIC_WORLD, LAST_SMALL_ROCKY_WORLD = AURIC_WORLD, FIRST_LARGE_ROCKY_WORLD, FLUORESCENT_WORLD = FIRST_LARGE_ROCKY_WORLD, ULTRAVIOLET_WORLD, PLUTONIC_WORLD, RAINBOW_WORLD, CRACKED_WORLD, SAPPHIRE_WORLD, ORGANIC_WORLD, XENOLITHIC_WORLD, REDUX_WORLD, PRIMORDIAL_WORLD, EMERALD_WORLD, CHLORINE_WORLD, MAGNETIC_WORLD, WATER_WORLD, TELLURIC_WORLD, HYDROCARBON_WORLD, IODINE_WORLD, VINYLOGOUS_WORLD, RUBY_WORLD, MAGMA_WORLD, MAROON_WORLD, LAST_LARGE_ROCKY_WORLD = MAROON_WORLD, FIRST_GAS_GIANT, BLU_GAS_GIANT = FIRST_GAS_GIANT, /* Gas Giants */ CYA_GAS_GIANT, GRN_GAS_GIANT, GRY_GAS_GIANT, ORA_GAS_GIANT, PUR_GAS_GIANT, RED_GAS_GIANT, VIO_GAS_GIANT, YEL_GAS_GIANT, LAST_GAS_GIANT = YEL_GAS_GIANT, NUMBER_OF_PLANET_TYPES }; #define NUMBER_OF_SMALL_ROCKY_WORLDS (LAST_SMALL_ROCKY_WORLD - FIRST_SMALL_ROCKY_WORLD + 1) #define NUMBER_OF_LARGE_ROCKY_WORLDS (LAST_LARGE_ROCKY_WORLD - FIRST_LARGE_ROCKY_WORLD + 1) #define NUMBER_OF_ROCKY_WORLDS (NUMBER_OF_SMALL_ROCKY_WORLDS + NUMBER_OF_LARGE_ROCKY_WORLDS) #define NUMBER_OF_GAS_GIANTS (LAST_GAS_GIANT - FIRST_GAS_GIANT + 1) typedef struct { const SIZE level_tab[3]; const BYTE xlat_tab[256]; } XLAT_DESC; typedef const XLAT_DESC *PXLAT_DESC; typedef struct { BYTE ElementType; /* Index of this element in element_array */ BYTE Density; /* bits 0-3: quantity of the deposits (maximum number of * deposits), one of FEW, MODERATE, or NUMEROUS * bits 4-7: quality of the deposit, one of LOW, MEDIUM, or HEAVY */ } ElementEntry; // PlanetFrame describes a type of planet. It is not used to describe // individual planets. typedef struct { BYTE Type; /* bits 0-1: size, one of SMALL_ROCKY_WORLD, LARGE_ROCKY_WORLD, or * GAS_GIANT * bits 2-3: map creation algoritm, one of TOPO_ALGO, * CRATERED_ALGO, or GAS_GIANT_ALGO * bits 4-7: interplanetary color, one of BLUE_BODY, GREEN_BODY, * ORANGE_BODY, RED_BODY, WHITE_BODY (same as * GRAY_BODY), YELLOW_BODY, CYAN_BODY, PURPLE_BODY, * VIOLET_BODY) */ BYTE BaseTectonics; /* Base constant for calculation of tectonic activity, * relative to Earth at 100. * One of: NO_TECTONICS, LOW_TECTONICS, MED_TECTONICS, * HIGH_TECTONICS, or SUPER_TECTONICS */ BYTE AtmoAndDensity; /* bits 0-3: planet density, one of GAS_DENSITY, LIGHT_DENSITY, * LOW_DENSITY, NORMAL_DENSITY, HIGH_DENSITY, * SUPER_DENSITY * bits 4-7: atmosphere, one of LIGHT, MEDIUM, HEAVY, or * (no define for this) super thick. */ #define NUM_USEFUL_ELEMENTS 8 ElementEntry UsefulElements[NUM_USEFUL_ELEMENTS]; /* Minerals on the planet */ RESOURCE CMapInstance; /* Color map */ RESOURCE XlatTabInstance; /* Color translation map */ // Parameters for map-generation algoritms: COUNT num_faults; SIZE fault_depth; COUNT num_blemishes; SIZE base_elevation; } PlanetFrame; typedef const PlanetFrame *PPLANDATA; typedef const ElementEntry *PELEMENT_ENTRY; #define XLAT_DESCPTR PXLAT_DESC #define PLANDATAPTR PPLANDATA #define ELEMENT_ENTRYPTR PELEMENT_ENTRY typedef struct { SIZE AxialTilt; UWORD Tectonics; UWORD Weather; UWORD PlanetDensity; UWORD PlanetRadius; UWORD SurfaceGravity; SIZE SurfaceTemperature; UWORD RotationPeriod; UWORD AtmoDensity; SIZE LifeChance; UWORD PlanetToSunDist; PLANDATAPTR PlanDataPtr; DWORD ScanSeed[NUM_SCAN_TYPES]; DWORD ScanRetrieveMask[NUM_SCAN_TYPES]; // The CurPt, CurDensity and CurType fields are filled in // when a GENERATE_MINERAL, GENERATE_ENERGY, or GENERATE_LIFE // call is made. POINT CurPt; // Position of the mineral/bio/energy node on the planet. COUNT CurDensity; // For bio and energy: undefined // For minerals the low byte is the gross size of the // deposit (this determines the image), and the high // byte is the fine size (the actual quantity). COUNT CurType; // For minerals: the type of element // For bio: the type of the creature. // 0 through NUM_CREATURE_TYPES - 1 are normal creatures, // NUM_CREATURE_TYPES is an Evil One // NUM_CREATURE_TYPES + 1 is a Brainbox Bulldozer // NUM_CREATURE_TYPES + 2 is Zex' Beauty // For energy: 0 - Liftoff on collision // 1 - No liftoff on collision // 2 - (special case) Fwiffo STRING DiscoveryString; FONT LanderFont; FRAME LanderFontEff; } PLANET_INFO; typedef PLANET_INFO *PPLANET_INFO; enum { GAS_DENSITY, LIGHT_DENSITY, LOW_DENSITY, NORMAL_DENSITY, HIGH_DENSITY, SUPER_DENSITY }; #define CalcGravity(d,r) (UWORD)((DWORD)(d) * (r) / 100) #define CalcFromBase(b,v) ((UWORD)(b) + ((UWORD)TFB_Random () % (v))) #define PLANET_INFOPTR PPLANET_INFO #define EARTH_ATMOSPHERE 50 #define COLD_THRESHOLD -40 #define HOT_THRESHOLD 100 /*------------------------------ Global Data ------------------------------ */ #define NO_TECTONICS 0 #define LOW_TECTONICS 40 #define MED_TECTONICS 80 #define HIGH_TECTONICS 140 #define SUPER_TECTONICS 200 extern const PlanetFrame *PlanData; #endif /* _PLANDATA_H */ uqm-0.6.2/sc2/src/sc2code/planets/genall.h0000600000175000017500000000152410543202100016655 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _GENALL_H #define _GENALL_H #include "planets/planets.h" #include "libs/compiler.h" #endif /* _GENALL_H */ uqm-0.6.2/sc2/src/sc2code/planets/genilw.c0000600000175000017500000001004310543202100016667 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "globdata.h" #include "nameref.h" #include "resinst.h" #include "state.h" #include "planets/genall.h" #include "libs/mathlib.h" void GenerateIlwrath (BYTE control) { switch (control) { case GENERATE_ENERGY: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { COUNT i, which_node; DWORD rand_val, old_rand; old_rand = TFB_SeedRandom ( pSolarSysState->SysInfo.PlanetInfo.ScanSeed[ENERGY_SCAN] ); which_node = i = 0; do { rand_val = TFB_Random (); pSolarSysState->SysInfo.PlanetInfo.CurPt.x = (LOBYTE (LOWORD (rand_val)) % (MAP_WIDTH - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurPt.y = (HIBYTE (LOWORD (rand_val)) % (MAP_HEIGHT - (8 << 1))) + 8; pSolarSysState->SysInfo.PlanetInfo.CurType = 1; pSolarSysState->SysInfo.PlanetInfo.CurDensity = 0; if (which_node >= pSolarSysState->CurNode && !(pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] & (1L << i))) break; ++which_node; } while (++i < 16); pSolarSysState->CurNode = which_node; TFB_SeedRandom (old_rand); break; } pSolarSysState->CurNode = 0; break; case GENERATE_PLANETS: { COUNT angle; GenerateRandomIP (GENERATE_PLANETS); pSolarSysState->PlanetDesc[0].data_index = PRIMORDIAL_WORLD; pSolarSysState->PlanetDesc[0].radius = EARTH_RADIUS * 204L / 100; angle = ARCTAN ( pSolarSysState->PlanetDesc[0].location.x, pSolarSysState->PlanetDesc[0].location.y ); pSolarSysState->PlanetDesc[0].location.x = COSINE (angle, pSolarSysState->PlanetDesc[0].radius); pSolarSysState->PlanetDesc[0].location.y = SINE (angle, pSolarSysState->PlanetDesc[0].radius); break; } case GENERATE_ORBITAL: if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { if (ActivateStarShip (ILWRATH_SHIP, SPHERE_TRACKING)) { NotifyOthers (ILWRATH_SHIP, (BYTE)~0); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); ReinitQueue (&GLOBAL (npc_built_ship_q)); CloneShipFragment (ILWRATH_SHIP, &GLOBAL (npc_built_ship_q), INFINITE_FLEET); pSolarSysState->MenuState.Initialized += 2; GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (GLOBAL_FLAGS_AND_DATA, 1 << 7); InitCommunication (ILWRATH_CONVERSATION); pSolarSysState->MenuState.Initialized -= 2; if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { GLOBAL (CurrentActivity) &= ~START_INTERPLANETARY; ReinitQueue (&GLOBAL (npc_built_ship_q)); GetGroupInfo (GROUPS_RANDOM, GROUP_LOAD_IP); } break; } else { LoadStdLanderFont (&pSolarSysState->SysInfo.PlanetInfo); pSolarSysState->PlanetSideFrame[1] = CaptureDrawable ( LoadGraphic (RUINS_MASK_PMAP_ANIM) ); pSolarSysState->SysInfo.PlanetInfo.DiscoveryString = CaptureStringTable ( LoadStringTable (RUINS_STRTAB) ); } } GenerateRandomIP (GENERATE_ORBITAL); if (pSolarSysState->pOrbitalDesc == &pSolarSysState->PlanetDesc[0]) { pSolarSysState->SysInfo.PlanetInfo.Weather = 2; pSolarSysState->SysInfo.PlanetInfo.Tectonics = 3; } break; default: GenerateRandomIP (control); break; } } uqm-0.6.2/sc2/src/sc2code/dummy.c0000600000175000017500000001537710543202101015107 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * This file seems to be a collection of functions that don't do * much. */ #include "coderes.h" #include "globdata.h" #include "races.h" #include "libs/compiler.h" #include "libs/log.h" #include typedef struct { MEM_HANDLE handle _ALIGNED_ON(sizeof (MEM_HANDLE)); RACE_DESC data _ALIGNED_ANY; } CODERES_STRUCT; MEM_HANDLE LoadCodeResFile (PSTR pStr) { (void) pStr; /* Satisfying compiler (unused parameter) */ return (0); } static MEM_HANDLE GetCodeResData (uio_Stream *fp, DWORD length) { enum { ANDROSYN_CODE_RES, ARILOU_CODE_RES, BLACKURQ_CODE_RES, CHENJESU_CODE_RES, CHMMR_CODE_RES, DRUUGE_CODE_RES, HUMAN_CODE_RES, ILWRATH_CODE_RES, MELNORME_CODE_RES, MMRNMHRM_CODE_RES, MYCON_CODE_RES, ORZ_CODE_RES, PKUNK_CODE_RES, SHOFIXTI_CODE_RES, SLYLANDR_CODE_RES, SPATHI_CODE_RES, SUPOX_CODE_RES, SYREEN_CODE_RES, THRADD_CODE_RES, UMGAH_CODE_RES, URQUAN_CODE_RES, UTWIG_CODE_RES, VUX_CODE_RES, YEHAT_CODE_RES, ZOQFOT_CODE_RES, SAMATRA_CODE_RES, SIS_CODE_RES, PROBE_CODE_RES }; BYTE which_res; MEM_HANDLE hData; which_res = GetResFileChar (fp); hData = mem_request (sizeof (CODERES_STRUCT)); if (hData) { RACE_DESCPTR RDPtr; RDPtr = 0; switch (which_res) { case ANDROSYN_CODE_RES: { extern RACE_DESCPTR init_androsynth (void); RDPtr = init_androsynth (); break; } case ARILOU_CODE_RES: { extern RACE_DESCPTR init_arilou (void); RDPtr = init_arilou (); break; } case BLACKURQ_CODE_RES: { extern RACE_DESCPTR init_black_urquan (void); RDPtr = init_black_urquan (); break; } case CHENJESU_CODE_RES: { extern RACE_DESCPTR init_chenjesu (void); RDPtr = init_chenjesu (); break; } case CHMMR_CODE_RES: { extern RACE_DESCPTR init_chmmr (void); RDPtr = init_chmmr (); break; } case DRUUGE_CODE_RES: { extern RACE_DESCPTR init_druuge (void); RDPtr = init_druuge (); break; } case HUMAN_CODE_RES: { extern RACE_DESCPTR init_human (void); RDPtr = init_human (); break; } case ILWRATH_CODE_RES: { extern RACE_DESCPTR init_ilwrath (void); RDPtr = init_ilwrath (); break; } case MELNORME_CODE_RES: { extern RACE_DESCPTR init_melnorme (void); RDPtr = init_melnorme (); break; } case MMRNMHRM_CODE_RES: { extern RACE_DESCPTR init_mmrnmhrm (void); RDPtr = init_mmrnmhrm (); break; } case MYCON_CODE_RES: { extern RACE_DESCPTR init_mycon (void); RDPtr = init_mycon (); break; } case ORZ_CODE_RES: { extern RACE_DESCPTR init_orz (void); RDPtr = init_orz (); break; } case PKUNK_CODE_RES: { extern RACE_DESCPTR init_pkunk (void); RDPtr = init_pkunk (); break; } case SHOFIXTI_CODE_RES: { extern RACE_DESCPTR init_shofixti (void); RDPtr = init_shofixti (); break; } case SLYLANDR_CODE_RES: { extern RACE_DESCPTR init_slylandro (void); RDPtr = init_slylandro (); break; } case SPATHI_CODE_RES: { extern RACE_DESCPTR init_spathi (void); RDPtr = init_spathi (); break; } case SUPOX_CODE_RES: { extern RACE_DESCPTR init_supox (void); RDPtr = init_supox (); break; } case SYREEN_CODE_RES: { extern RACE_DESCPTR init_syreen (void); RDPtr = init_syreen (); break; } case THRADD_CODE_RES: { extern RACE_DESCPTR init_thraddash (void); RDPtr = init_thraddash (); break; } case UMGAH_CODE_RES: { extern RACE_DESCPTR init_umgah (void); RDPtr = init_umgah (); break; } case URQUAN_CODE_RES: { extern RACE_DESCPTR init_urquan (void); RDPtr = init_urquan (); break; } case UTWIG_CODE_RES: { extern RACE_DESCPTR init_utwig (void); RDPtr = init_utwig (); break; } case VUX_CODE_RES: { extern RACE_DESCPTR init_vux (void); RDPtr = init_vux (); break; } case YEHAT_CODE_RES: { extern RACE_DESCPTR init_yehat (void); RDPtr = init_yehat (); break; } case ZOQFOT_CODE_RES: { extern RACE_DESCPTR init_zoqfotpik (void); RDPtr = init_zoqfotpik (); break; } case SAMATRA_CODE_RES: { extern RACE_DESCPTR init_samatra (void); RDPtr = init_samatra (); break; } case SIS_CODE_RES: { extern RACE_DESCPTR init_sis (void); RDPtr = init_sis (); break; } case PROBE_CODE_RES: { extern RACE_DESCPTR init_probe (void); RDPtr = init_probe (); break; } } if (RDPtr == 0) { mem_release (hData); hData = 0; } else { CODERES_STRUCT *cs; cs = (CODERES_STRUCT *) mem_lock (hData); cs->data = *RDPtr; // Structure assignment. mem_unlock (hData); } } (void) length; /* Satisfying compiler (unused parameter) */ return (hData); } BOOLEAN InstallCodeResType (COUNT code_type) { return (InstallResTypeVectors (code_type, GetCodeResData, mem_release)); } MEM_HANDLE LoadCodeResInstance (DWORD res) { MEM_HANDLE hData; hData = res_GetResource (res); if (hData) res_DetachResource (res); return (hData); } BOOLEAN DestroyCodeRes (MEM_HANDLE hCode) { return (mem_release (hCode)); } PVOID CaptureCodeRes (MEM_HANDLE hCode, PVOID pData, PVOID *ppLocData) { CODERES_STRUCT *cs; if (hCode == 0) { log_add (log_Fatal, "dummy.c::CaptureCodeRes() hCode==0! FATAL!"); return(0); } cs = (CODERES_STRUCT *) mem_lock (hCode); cs->handle = hCode; *ppLocData = (void *) &cs->data; (void) pData; /* Satisfying compiler (unused parameter) */ return (void *) cs; } MEM_HANDLE ReleaseCodeRes (PVOID CodeRef) { if (CodeRef) { MEM_HANDLE hCode; mem_unlock (hCode = *(MEM_HANDLE *)CodeRef); return (hCode); } return (0); } DRAWABLE CreatePixmapRegion (FRAME Frame, PPOINT lpOrg, SIZE width, SIZE height) { (void) lpOrg; /* Satisfying compiler (unused parameter) */ (void) width; /* Satisfying compiler (unused parameter) */ (void) height; /* Satisfying compiler (unused parameter) */ return (GetFrameHandle (Frame)); } uqm-0.6.2/sc2/src/sc2code/displist.h0000600000175000017500000000667610543202100015615 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _DISPLIST_H #define _DISPLIST_H #include "memlib.h" #define QUEUE_TABLE #ifdef QUEUE_TABLE typedef PVOID QUEUE_HANDLE; #else /* !QUEUE_TABLE */ typedef MEM_HANDLE QUEUE_HANDLE; #endif /* QUEUE_TABLE */ typedef UWORD OBJ_SIZE; typedef QUEUE_HANDLE HLINK; typedef struct link { HLINK pred; HLINK succ; } LINK; typedef LINK *PLINK; typedef PBYTE BYTEPTR; typedef PUWORD WORDPTR; typedef PVOID VOIDPTR; typedef PLINK LINKPTR; #ifdef QUEUE_TABLE #define LockLink(pq, h) (LINKPTR)(h) #define UnlockLink(pq, h) #define GetFreeList(pq) (pq)->free_list #define SetFreeList(pq, h) (pq)->free_list = (h) #define AllocQueueTab(pq,n) \ ((pq)->hq_tab = mem_allocate ((MEM_SIZE)((COUNT)(pq)->object_size * \ (COUNT)((pq)->num_objects = (BYTE)(n))), \ MEM_PRIMARY, DEFAULT_MEM_PRIORITY, MEM_SIMPLE)) #define LockQueueTab(pq) ((pq)->pq_tab = (BYTEPTR)mem_lock ((pq)->hq_tab)) #define UnlockQueueTab(pq) mem_unlock ((pq)->hq_tab) #define FreeQueueTab(pq) mem_release ((pq)->hq_tab); (pq)->hq_tab = 0 #define SizeQueueTab(pq) (COUNT)((pq)->num_objects) #define GetLinkAddr(pq,i) (HLINK)((pq)->pq_tab + ((pq)->object_size * ((i) - 1))) #else /* !QUEUE_TABLE */ #define AllocLink(pq) (HLINK)mem_request ((pq)->object_size) #define LockLink(pq, h) (LINKPTR)mem_lock (h) #define UnlockLink(pq, h) mem_unlock (h) #define FreeLink(pq,h) mem_release (h) #endif /* QUEUE_TABLE */ typedef struct queue { HLINK head; HLINK tail; #ifdef QUEUE_TABLE BYTEPTR pq_tab; HLINK free_list; MEM_HANDLE hq_tab; #endif // BYTE object_size; COUNT object_size; #ifdef QUEUE_TABLE BYTE num_objects; #endif /* QUEUE_TABLE */ } QUEUE; typedef QUEUE *PQUEUE; // #define SetLinkSize(pq,s) ((pq)->object_size = (BYTE)(s)) #define SetLinkSize(pq,s) ((pq)->object_size = (COUNT)(s)) #define GetLinkSize(pq) (COUNT)((pq)->object_size) #define GetHeadLink(pq) ((pq)->head) #define SetHeadLink(pq,h) ((pq)->head = (h)) #define GetTailLink(pq) ((pq)->tail) #define SetTailLink(pq,h) ((pq)->tail = (h)) #define _GetPredLink(lpE) ((lpE)->pred) #define _SetPredLink(lpE,h) ((lpE)->pred = (h)) #define _GetSuccLink(lpE) ((lpE)->succ) #define _SetSuccLink(lpE,h) ((lpE)->succ = (h)) extern BOOLEAN InitQueue (PQUEUE pq, COUNT num_elements, OBJ_SIZE size); extern BOOLEAN UninitQueue (PQUEUE pq); extern void ReinitQueue (PQUEUE pq); extern void PutQueue (PQUEUE pq, HLINK hLink); extern void InsertQueue (PQUEUE pq, HLINK hLink, HLINK hRefLink); extern void RemoveQueue (PQUEUE pq, HLINK hLink); extern COUNT CountLinks (PQUEUE pq); void ForAllLinks(PQUEUE pq, void (*callback)(LINKPTR, void *), void *arg); #ifdef QUEUE_TABLE extern HLINK AllocLink (PQUEUE pq); extern void FreeLink (PQUEUE pq, HLINK hLink); #endif /* QUEUE_TABLE */ #endif /* _DISPLIST_H */ uqm-0.6.2/sc2/src/sc2code/gravwell.c0000600000175000017500000000365010543202101015566 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "element.h" #include "resinst.h" #include "nameref.h" #include "setup.h" FRAME planet[NUM_VIEWS]; void load_gravity_well (BYTE selector) { COUNT i; RES_TYPE rt; RES_INSTANCE ri; RES_PACKAGE rp; MEM_HANDLE hLastIndex; hLastIndex = SetResourceIndex (hResIndex); if (selector == NUMBER_OF_PLANET_TYPES) { planet[0] = CaptureDrawable ( LoadGraphic (SAMATRA_BIG_MASK_PMAP_ANIM) ); planet[1] = planet[2] = 0; } else { if (selector & PLANET_SHIELDED) { rt = GET_TYPE (SHIELDED_BIG_MASK_PMAP_ANIM); ri = GET_INSTANCE (SHIELDED_BIG_MASK_PMAP_ANIM); rp = GET_PACKAGE (SHIELDED_BIG_MASK_PMAP_ANIM); } else { rt = GET_TYPE (PLANET00_BIG_MASK_PMAP_ANIM); ri = GET_INSTANCE (PLANET00_BIG_MASK_PMAP_ANIM) + (selector * NUM_VIEWS); rp = GET_PACKAGE (PLANET00_BIG_MASK_PMAP_ANIM) + selector; } for (i = 0; i < NUM_VIEWS; ++i, ++ri) { planet[i] = CaptureDrawable ( LoadGraphic (MAKE_RESOURCE (rp, rt, ri)) ); } } SetResourceIndex (hLastIndex); } void free_gravity_well (void) { COUNT i; for (i = 0; i < NUM_VIEWS; ++i) { DestroyDrawable (ReleaseDrawable (planet[i])); planet[i] = 0; } } uqm-0.6.2/sc2/src/sc2code/collide.c0000600000175000017500000001407610543202100015361 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "collide.h" #include "element.h" #include "races.h" #include "units.h" #include "libs/mathlib.h" #include "libs/log.h" //#define DEBUG_COLLIDE void collide (ELEMENTPTR ElementPtr0, ELEMENTPTR ElementPtr1) { SIZE speed; SIZE dx0, dy0, dx1, dy1, dx_rel, dy_rel; SIZE TravelAngle0, TravelAngle1, ImpactAngle0, ImpactAngle1; SIZE RelTravelAngle, Directness; dx_rel = ElementPtr0->next.location.x - ElementPtr1->next.location.x; dy_rel = ElementPtr0->next.location.y - ElementPtr1->next.location.y; ImpactAngle0 = ARCTAN (dx_rel, dy_rel); ImpactAngle1 = NORMALIZE_ANGLE (ImpactAngle0 + HALF_CIRCLE); GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx0, &dy0); TravelAngle0 = GetVelocityTravelAngle (&ElementPtr0->velocity); GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx1, &dy1); TravelAngle1 = GetVelocityTravelAngle (&ElementPtr1->velocity); dx_rel = dx0 - dx1; dy_rel = dy0 - dy1; RelTravelAngle = ARCTAN (dx_rel, dy_rel); speed = square_root ((long)dx_rel * dx_rel + (long)dy_rel * dy_rel); Directness = NORMALIZE_ANGLE (RelTravelAngle - ImpactAngle0); if (Directness <= QUADRANT || Directness >= HALF_CIRCLE + QUADRANT) /* shapes just scraped each other but still collided, * they will collide again unless we fudge it. */ { Directness = HALF_CIRCLE; ImpactAngle0 = TravelAngle0 + HALF_CIRCLE; ImpactAngle1 = TravelAngle1 + HALF_CIRCLE; } #ifdef DEBUG_COLLIDE log_add (log_Debug, "Centers: <%d, %d> <%d, %d>", ElementPtr0->next.location.x, ElementPtr0->next.location.y, ElementPtr1->next.location.x, ElementPtr1->next.location.y); log_add (log_Debug, "RelTravelAngle : %d, ImpactAngles <%d, %d>", RelTravelAngle, ImpactAngle0, ImpactAngle1); #endif /* DEBUG_COLLIDE */ if (ElementPtr0->next.location.x == ElementPtr0->current.location.x && ElementPtr0->next.location.y == ElementPtr0->current.location.y && ElementPtr1->next.location.x == ElementPtr1->current.location.x && ElementPtr1->next.location.y == ElementPtr1->current.location.y) { if (ElementPtr0->state_flags & ElementPtr1->state_flags & DEFY_PHYSICS) { ImpactAngle0 = TravelAngle0 + (HALF_CIRCLE - OCTANT); ImpactAngle1 = TravelAngle1 + (HALF_CIRCLE - OCTANT); ZeroVelocityComponents (&ElementPtr0->velocity); ZeroVelocityComponents (&ElementPtr1->velocity); } ElementPtr0->state_flags |= (DEFY_PHYSICS | COLLISION); ElementPtr1->state_flags |= (DEFY_PHYSICS | COLLISION); #ifdef DEBUG_COLLIDE log_add (log_Debug, "No movement before collision -- " "<(%d, %d) = %d, (%d, %d) = %d>", dx0, dy0, ImpactAngle0 - OCTANT, dx1, dy1, ImpactAngle1 - OCTANT); #endif /* DEBUG_COLLIDE */ } { SIZE mass0, mass1; long scalar; mass0 = ElementPtr0->mass_points /* << 2 */; mass1 = ElementPtr1->mass_points /* << 2 */; scalar = (long)SINE (Directness, speed << 1) * (mass0 * mass1); if (!GRAVITY_MASS (ElementPtr0->mass_points + 1)) { if (ElementPtr0->state_flags & PLAYER_SHIP) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr0, &StarShipPtr); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); if (!(ElementPtr0->state_flags & DEFY_PHYSICS)) { if (ElementPtr0->turn_wait < COLLISION_TURN_WAIT) ElementPtr0->turn_wait += COLLISION_TURN_WAIT; if (ElementPtr0->thrust_wait < COLLISION_THRUST_WAIT) ElementPtr0->thrust_wait += COLLISION_THRUST_WAIT; } } speed = (SIZE)(scalar / ((long)mass0 * (mass0 + mass1))); DeltaVelocityComponents (&ElementPtr0->velocity, COSINE (ImpactAngle0, speed), SINE (ImpactAngle0, speed)); GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx0, &dy0); if (dx0 < 0) dx0 = -dx0; if (dy0 < 0) dy0 = -dy0; if (VELOCITY_TO_WORLD (dx0 + dy0) < SCALED_ONE) SetVelocityComponents (&ElementPtr0->velocity, COSINE (ImpactAngle0, WORLD_TO_VELOCITY (SCALED_ONE) - 1), SINE (ImpactAngle0, WORLD_TO_VELOCITY (SCALED_ONE) - 1)); } if (!GRAVITY_MASS (ElementPtr1->mass_points + 1)) { if (ElementPtr1->state_flags & PLAYER_SHIP) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr1, &StarShipPtr); StarShipPtr->cur_status_flags &= ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED); if (!(ElementPtr1->state_flags & DEFY_PHYSICS)) { if (ElementPtr1->turn_wait < COLLISION_TURN_WAIT) ElementPtr1->turn_wait += COLLISION_TURN_WAIT; if (ElementPtr1->thrust_wait < COLLISION_THRUST_WAIT) ElementPtr1->thrust_wait += COLLISION_THRUST_WAIT; } } speed = (SIZE)(scalar / ((long)mass1 * (mass0 + mass1))); DeltaVelocityComponents (&ElementPtr1->velocity, COSINE (ImpactAngle1, speed), SINE (ImpactAngle1, speed)); GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx1, &dy1); if (dx1 < 0) dx1 = -dx1; if (dy1 < 0) dy1 = -dy1; if (VELOCITY_TO_WORLD (dx1 + dy1) < SCALED_ONE) SetVelocityComponents (&ElementPtr1->velocity, COSINE (ImpactAngle1, WORLD_TO_VELOCITY (SCALED_ONE) - 1), SINE (ImpactAngle1, WORLD_TO_VELOCITY (SCALED_ONE) - 1)); } #ifdef DEBUG_COLLIDE GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx0, &dy0); GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx1, &dy1); log_add (log_Debug, "After: <%d, %d> <%d, %d>\n", dx0, dy0, dx1, dy1); #endif /* DEBUG_COLLIDE */ } } uqm-0.6.2/sc2/src/sc2code/trans.c0000600000175000017500000000603710543202101015074 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "units.h" #include "libs/compiler.h" SIZE sinetab[] = { -FLT_ADJUST (1.000000), -FLT_ADJUST (0.995185), -FLT_ADJUST (0.980785), -FLT_ADJUST (0.956940), -FLT_ADJUST (0.923880), -FLT_ADJUST (0.881921), -FLT_ADJUST (0.831470), -FLT_ADJUST (0.773010), -FLT_ADJUST (0.707107), -FLT_ADJUST (0.634393), -FLT_ADJUST (0.555570), -FLT_ADJUST (0.471397), -FLT_ADJUST (0.382683), -FLT_ADJUST (0.290285), -FLT_ADJUST (0.195090), -FLT_ADJUST (0.098017), FLT_ADJUST (0.000000), FLT_ADJUST (0.098017), FLT_ADJUST (0.195090), FLT_ADJUST (0.290285), FLT_ADJUST (0.382683), FLT_ADJUST (0.471397), FLT_ADJUST (0.555570), FLT_ADJUST (0.634393), FLT_ADJUST (0.707107), FLT_ADJUST (0.773010), FLT_ADJUST (0.831470), FLT_ADJUST (0.881921), FLT_ADJUST (0.923880), FLT_ADJUST (0.956940), FLT_ADJUST (0.980785), FLT_ADJUST (0.995185), FLT_ADJUST (1.000000), FLT_ADJUST (0.995185), FLT_ADJUST (0.980785), FLT_ADJUST (0.956940), FLT_ADJUST (0.923880), FLT_ADJUST (0.881921), FLT_ADJUST (0.831470), FLT_ADJUST (0.773010), FLT_ADJUST (0.707107), FLT_ADJUST (0.634393), FLT_ADJUST (0.555570), FLT_ADJUST (0.471397), FLT_ADJUST (0.382683), FLT_ADJUST (0.290285), FLT_ADJUST (0.195090), FLT_ADJUST (0.098017), FLT_ADJUST (0.000000), -FLT_ADJUST (0.098017), -FLT_ADJUST (0.195090), -FLT_ADJUST (0.290285), -FLT_ADJUST (0.382683), -FLT_ADJUST (0.471397), -FLT_ADJUST (0.555570), -FLT_ADJUST (0.634393), -FLT_ADJUST (0.707107), -FLT_ADJUST (0.773010), -FLT_ADJUST (0.831470), -FLT_ADJUST (0.881921), -FLT_ADJUST (0.923880), -FLT_ADJUST (0.956940), -FLT_ADJUST (0.980785), -FLT_ADJUST (0.995185), }; COUNT ARCTAN (SIZE delta_x, SIZE delta_y) { SIZE v1, v2; static COUNT atantab[] = { 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, }; v1 = delta_x; v2 = delta_y; if (v1 == 0 && v2 == 0) return (FULL_CIRCLE); if (v1 < 0) v1 = -v1; if (v2 < 0) v2 = -v2; if (v1 > v2) v1 = QUADRANT - atantab[(((DWORD)v2 << (CIRCLE_SHIFT - 1)) + (v1 >> 1)) / v1]; else v1 = atantab[(((DWORD)v1 << (CIRCLE_SHIFT - 1)) + (v2 >> 1)) / v2]; if (delta_x < 0) v1 = FULL_CIRCLE - v1; if (delta_y > 0) v1 = HALF_CIRCLE - v1; return (NORMALIZE_ANGLE (v1)); } uqm-0.6.2/sc2/src/sc2code/settings.c0000600000175000017500000000412310543202103015601 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "settings.h" #include "globdata.h" #include "libs/compiler.h" static MUSIC_REF LastMusicRef; static BOOLEAN LastContinuous; static BYTE LastPriority; void ToggleMusic (void) { GLOBAL (glob_flags) ^= MUSIC_DISABLED; if (LastPriority <= 1) { if (GLOBAL (glob_flags) & MUSIC_DISABLED) PLRStop (LastMusicRef); else if (LastMusicRef) PLRPlaySong (LastMusicRef, LastContinuous, LastPriority); } } void PlayMusic (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority) { LastMusicRef = MusicRef; LastContinuous = Continuous; LastPriority = Priority; if ( #ifdef NEVER Priority > 1 || #endif /* NEVER */ !(GLOBAL (glob_flags) & MUSIC_DISABLED) ) { PLRPlaySong (MusicRef, Continuous, Priority); } } void StopMusic (void) { PLRStop (LastMusicRef); LastMusicRef = 0; } void ResumeMusic (void) { PLRResume (LastMusicRef); } void PauseMusic (void) { PLRPause (LastMusicRef); } void ToggleSoundEffect (void) { GLOBAL (glob_flags) ^= SOUND_DISABLED; } void PlaySoundEffect (SOUND S, COUNT Channel, SoundPosition Pos, void *PositionalObject, BYTE Priority) { if (!(GLOBAL (glob_flags) & SOUND_DISABLED)) { SetChannelVolume (Channel, MAX_VOLUME >> 1, Priority); SetChannelRate (Channel, GetSampleRate (S), Priority); PlayChannel (Channel, GetSampleAddress (S), Pos, PositionalObject, Priority); } } uqm-0.6.2/sc2/src/sc2code/gravity.c0000600000175000017500000001357510543202103015441 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "collide.h" #include "races.h" #include "units.h" #include "libs/log.h" //#define DEBUG_GRAVITY BOOLEAN CalculateGravity (PELEMENT ElementPtr) { BOOLEAN retval, HasGravity; HELEMENT hTestElement, hSuccElement; retval = FALSE; HasGravity = (BOOLEAN)(CollidingElement (ElementPtr) && GRAVITY_MASS (ElementPtr->mass_points + 1)); for (hTestElement = GetHeadElement (); hTestElement != 0; hTestElement = hSuccElement) { BOOLEAN TestHasGravity; ELEMENTPTR TestElementPtr; LockElement (hTestElement, &TestElementPtr); if (TestElementPtr != ElementPtr && CollidingElement (TestElementPtr) && (TestHasGravity = GRAVITY_MASS (TestElementPtr->mass_points + 1)) != HasGravity) { COUNT abs_dx, abs_dy; SIZE dx, dy; if (!(ElementPtr->state_flags & PRE_PROCESS)) { dx = ElementPtr->current.location.x - TestElementPtr->current.location.x; dy = ElementPtr->current.location.y - TestElementPtr->current.location.y; } else { dx = ElementPtr->next.location.x - TestElementPtr->next.location.x; dy = ElementPtr->next.location.y - TestElementPtr->next.location.y; } #ifdef DEBUG_GRAVITY if (TestElementPtr->state_flags & PLAYER_SHIP) { log_add (log_Debug, "CalculateGravity:"); log_add (log_Debug, "\tdx = %d, dy = %d", dx, dy); } #endif /* DEBUG_GRAVITY */ dx = WRAP_DELTA_X (dx); dy = WRAP_DELTA_Y (dy); #ifdef DEBUG_GRAVITY if (TestElementPtr->state_flags & PLAYER_SHIP) log_add (log_Debug, "\twrap_dx = %d, wrap_dy = %d", dx, dy); #endif /* DEBUG_GRAVITY */ abs_dx = dx >= 0 ? dx : -dx; abs_dy = dy >= 0 ? dy : -dy; abs_dx = WORLD_TO_DISPLAY (abs_dx); abs_dy = WORLD_TO_DISPLAY (abs_dy); #ifdef DEBUG_GRAVITY if (TestElementPtr->state_flags & PLAYER_SHIP) log_add (log_Debug, "\tdisplay_dx = %d, display_dy = %d", abs_dx, abs_dy); #endif /* DEBUG_GRAVITY */ if (abs_dx <= GRAVITY_THRESHOLD && abs_dy <= GRAVITY_THRESHOLD) { DWORD dist_squared; dist_squared = (DWORD)(abs_dx * abs_dx) + (DWORD)(abs_dy * abs_dy); if (dist_squared <= (DWORD)(GRAVITY_THRESHOLD * GRAVITY_THRESHOLD)) { #ifdef NEVER COUNT magnitude; #define DIFUSE_GRAVITY 175 dist_squared += (DWORD)abs_dx * (DIFUSE_GRAVITY << 1) + (DWORD)abs_dy * (DIFUSE_GRAVITY << 1) + ((DWORD)(DIFUSE_GRAVITY * DIFUSE_GRAVITY) << 1); if ((magnitude = (COUNT)((DWORD)(GRAVITY_THRESHOLD * GRAVITY_THRESHOLD) / dist_squared)) == 0) magnitude = 1; #define MAX_MAGNITUDE 6 else if (magnitude > MAX_MAGNITUDE) magnitude = MAX_MAGNITUDE; log_add (log_Debug, "magnitude = %u", magnitude); #endif /* NEVER */ #ifdef DEBUG_GRAVITY if (TestElementPtr->state_flags & PLAYER_SHIP) log_add (log_Debug, "dist_squared = %lu", dist_squared); #endif /* DEBUG_GRAVITY */ if (TestHasGravity) { retval = TRUE; UnlockElement (hTestElement); break; } else { COUNT angle; angle = ARCTAN (dx, dy); DeltaVelocityComponents (&TestElementPtr->velocity, COSINE (angle, WORLD_TO_VELOCITY (1)), SINE (angle, WORLD_TO_VELOCITY (1))); if (TestElementPtr->state_flags & PLAYER_SHIP) { STARSHIPPTR StarShipPtr; GetElementStarShip (TestElementPtr, &StarShipPtr); StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; StarShipPtr->cur_status_flags |= SHIP_IN_GRAVITY_WELL; } } } } } hSuccElement = GetSuccElement (TestElementPtr); UnlockElement (hTestElement); } return (retval); } BOOLEAN TimeSpaceMatterConflict (ELEMENTPTR ElementPtr) { HELEMENT hTestElement, hSuccElement; INTERSECT_CONTROL ElementControl; ElementControl.IntersectStamp.origin.x = WORLD_TO_DISPLAY (ElementPtr->current.location.x); ElementControl.IntersectStamp.origin.y = WORLD_TO_DISPLAY (ElementPtr->current.location.y); ElementControl.IntersectStamp.frame = SetEquFrameIndex (ElementPtr->current.image.farray[0], ElementPtr->current.image.frame); ElementControl.EndPoint = ElementControl.IntersectStamp.origin; for (hTestElement = GetHeadElement (); hTestElement != 0; hTestElement = hSuccElement) { ELEMENTPTR TestElementPtr; LockElement (hTestElement, &TestElementPtr); hSuccElement = GetSuccElement (TestElementPtr); if (TestElementPtr != ElementPtr && (CollidingElement (TestElementPtr) /* ship in transition */ || (TestElementPtr->state_flags & PLAYER_SHIP))) { INTERSECT_CONTROL TestElementControl; TestElementControl.IntersectStamp.origin.x = WORLD_TO_DISPLAY (TestElementPtr->current.location.x); TestElementControl.IntersectStamp.origin.y = WORLD_TO_DISPLAY (TestElementPtr->current.location.y); TestElementControl.IntersectStamp.frame = SetEquFrameIndex (TestElementPtr->current.image.farray[0], TestElementPtr->current.image.frame); TestElementControl.EndPoint = TestElementControl.IntersectStamp.origin; if (DrawablesIntersect (&ElementControl, &TestElementControl, MAX_TIME_VALUE)) { UnlockElement (hTestElement); break; } } UnlockElement (hTestElement); } return (hTestElement != 0 ? TRUE : FALSE); } uqm-0.6.2/sc2/src/sc2code/resinst.h0000600000175000017500000000164310543202103015441 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ikey_con.h" #include "igfxres.h" #include "ifontres.h" #include "istrtab.h" #include "isndres.h" #include "imusicre.h" #include "ires_ind.h" uqm-0.6.2/sc2/src/sc2code/build.h0000600000175000017500000000535510543202100015052 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _BUILD_H #define _BUILD_H #include "races.h" #include "displist.h" #include "libs/compiler.h" #define CREW_XOFFS 4 #define ENERGY_XOFFS 52 #define GAUGE_YOFFS (SHIP_INFO_HEIGHT - 10) #define UNIT_WIDTH 2 #define UNIT_HEIGHT 1 #define STAT_WIDTH (1 + UNIT_WIDTH + 1 + UNIT_WIDTH + 1) #define NAME_OFFSET 5 #define NUM_CAPTAINS_NAMES 16 #define OwnStarShip(S,p,n) \ (S)->s.Player = (p); \ (S)->s.Captain = (n); #define StarShipCaptain(S) \ (S)->s.Captain #define StarShipPlayer(S) \ (S)->s.Player #define PickCaptainName() (((COUNT)TFB_Random () \ & (NUM_CAPTAINS_NAMES - 1)) \ + NAME_OFFSET) extern HSTARSHIP Build (PQUEUE pQueue, DWORD RaceResIndex, COUNT which_player, BYTE captains_name_index); extern HSTARSHIP CloneShipFragment (COUNT shipIndex, PQUEUE pDstQueue, COUNT crew_level); extern HSTARSHIP GetStarShipFromIndex (PQUEUE pShipQ, COUNT Index); extern BYTE NameCaptain (PQUEUE pQueue, STARSHIPPTR StarShipPtr); /* Possible values for the 'state' argument of * COUNT ActivateStarShip (COUNT which_ship, SIZE state) * See that function for more information. */ #define CHECK_ALLIANCE -2 #define ESCORT_WORTH 9995 #define SPHERE_KNOWN 9996 #define SPHERE_TRACKING 9997 #define ESCORTING_FLAGSHIP 9998 #define FEASIBILITY_STUDY 9999 /* Check for how many escort ships there's still space */ extern COUNT ActivateStarShip (COUNT which_ship, SIZE state); extern COUNT GetIndexFromStarShip (PQUEUE pShipQ, HSTARSHIP hStarShip); extern MEM_HANDLE load_ship (STARSHIPPTR StarShipPtr, BOOLEAN LoadBattleData); extern void free_ship (STARSHIPPTR StarShipPtr, BOOLEAN FreeBattleData); extern void DrawCrewFuelString (COORD y, SIZE state); extern void ClearShipStatus (COORD y); extern void OutlineShipStatus (COORD y); extern void InitShipStatus (STARSHIPPTR StarShipPtr, PRECT pClipRect); extern void DeltaStatistics (STARSHIPPTR StarShipPtr, SIZE crew_delta, SIZE energy_delta); extern void DrawBattleCrewAmount (STARSHIPPTR StarShipPtr); #endif /* _BUILD_H */ uqm-0.6.2/sc2/src/sc2code/encount.c0000600000175000017500000004757710543202103015440 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "encount.h" #include "battle.h" #include "build.h" #include "colors.h" #include "controls.h" #include "gameopt.h" #include "gamestr.h" #include "globdata.h" #include "init.h" #include "intel.h" #include "nameref.h" #include "resinst.h" #include "settings.h" #include "setup.h" #include "sounds.h" #include "libs/graphics/gfx_common.h" #include "libs/mathlib.h" #include "libs/inplib.h" static void DrawFadeText (const UNICODE *str1, const UNICODE *str2, BOOLEAN fade_in, PRECT pRect); static BOOLEAN DoSelectAction (PMENU_STATE pMS) { SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); if (GLOBAL (CurrentActivity) & CHECK_ABORT) { pMS->CurState = ATTACK + 1; return (FALSE); } if (!pMS->Initialized) { pMS->Initialized = TRUE; pMS->InputFunc = DoSelectAction; } else if (PulsedInputState.menu[KEY_MENU_SELECT]) { switch (pMS->CurState) { case HAIL: case ATTACK: if (LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE) pMS->CurState = HAIL; return (FALSE); case ATTACK + 1: pMS->Initialized = GameOptions (); if (pMS->Initialized) { DrawMenuStateStrings (PM_CONVERSE, pMS->CurState); LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); } return ((BOOLEAN)pMS->Initialized); default: printf ("Unknown option: %d\n", pMS->CurState); } } DoMenuChooser (pMS, PM_CONVERSE); return (TRUE); } void BuildBattle (COUNT which_player) { PQUEUE pQueue; HSTARSHIP hStarShip, hNextShip; HSTARSHIP hBuiltShip; STARSHIPPTR BuiltShipPtr; EncounterRace = -1; if (GetHeadLink (&GLOBAL (npc_built_ship_q)) == 0) { SET_GAME_STATE (BATTLE_SEGUE, 0); return; } if (which_player == 0) pQueue = &GLOBAL (built_ship_q); else { switch (LOBYTE (GLOBAL (CurrentActivity))) { case IN_LAST_BATTLE: load_gravity_well (NUMBER_OF_PLANET_TYPES); break; case IN_HYPERSPACE: load_gravity_well ((BYTE)((COUNT)TFB_Random () % NUMBER_OF_PLANET_TYPES)); break; default: SET_GAME_STATE (ESCAPE_COUNTER, 110); load_gravity_well (GET_GAME_STATE (BATTLE_PLANET)); break; } pQueue = &GLOBAL (npc_built_ship_q); } ReinitQueue (&race_q[which_player]); for (hStarShip = GetHeadLink (pQueue); hStarShip != 0; hStarShip = hNextShip) { SHIP_FRAGMENTPTR FragPtr; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); hNextShip = _GetSuccLink (FragPtr); hBuiltShip = Build (&race_q[which_player], GET_RACE_ID (FragPtr) == SAMATRA_SHIP ? SAMATRA_RES_INDEX : FragPtr->RaceResIndex, 1 << which_player, StarShipCaptain (FragPtr)); if (hBuiltShip) { BuiltShipPtr = LockStarShip (&race_q[which_player], hBuiltShip); BuiltShipPtr->captains_name_index = StarShipCaptain (BuiltShipPtr); BuiltShipPtr->cur_status_flags = StarShipPlayer (BuiltShipPtr); if (FragPtr->ShipInfo.crew_level != INFINITE_FLEET) BuiltShipPtr->special_counter = FragPtr->ShipInfo.crew_level; else /* if infinite ships */ BuiltShipPtr->special_counter = FragPtr->ShipInfo.max_crew; BuiltShipPtr->RaceDescPtr = (RACE_DESCPTR)&FragPtr->ShipInfo; UnlockStarShip (&race_q[which_player], hBuiltShip); } UnlockStarShip (pQueue, hStarShip); } if (which_player == 0 && (hBuiltShip = Build (&race_q[0], SIS_RES_INDEX, GOOD_GUY, 0))) { BuiltShipPtr = LockStarShip (&race_q[0], hBuiltShip); BuiltShipPtr->captains_name_index = StarShipCaptain (BuiltShipPtr); BuiltShipPtr->cur_status_flags = StarShipPlayer (BuiltShipPtr); BuiltShipPtr->special_counter = 0; // Crew will be copied directly from // GLOBAL_SIS (CrewEnlisted) later. BuiltShipPtr->energy_counter = MAX_ENERGY_SIZE; UnlockStarShip (&race_q[0], hBuiltShip); } } /* * Encountering an alien. * Draws the encounter screen, plays the red alert music, and * waits for a decision of the player on how to handle the situation. * Returns either HAIL or ATTACK. */ COUNT InitEncounter (void) { COUNT i; MEM_HANDLE hOldIndex; FRAME SegueFrame; STAMP s; TEXT t; extern FRAME planet[]; MUSIC_REF MR; LockMutex (GraphicsLock); hOldIndex = SetResourceIndex (hResIndex); SetContext (SpaceContext); SetContextFont (TinyFont); MR = LoadMusic (REDALERT_MUSIC); PlayMusic (MR, FALSE, 1); SegueFrame = CaptureDrawable (LoadGraphic (SEGUE_PMAP_ANIM)); UnlockMutex (GraphicsLock); while (PLRPlaying (MR)) TaskSwitch (); StopMusic (); DestroyMusic (MR); LockMutex (GraphicsLock); s.origin.x = s.origin.y = 0; SetTransitionSource (NULL); BatchGraphics (); SetContextBackGroundColor (BLACK_COLOR); ClearDrawable (); s.frame = SegueFrame; DrawStamp (&s); // t.baseline.x = SIS_SCREEN_WIDTH >> 1; t.baseline.x = (SIS_SCREEN_WIDTH >> 1) + 1; t.baseline.y = 10; t.align = ALIGN_CENTER; SetContextFont (MicroFont); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) { t.pStr = GAME_STRING (ENCOUNTER_STRING_BASE + 0); t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += 12; t.pStr = GAME_STRING (ENCOUNTER_STRING_BASE + 1); t.CharCount = (COUNT)~0; font_DrawText (&t); } else { UNICODE buf[256]; t.pStr = GAME_STRING (ENCOUNTER_STRING_BASE + 2); t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += 12; GetClusterName (CurStarDescPtr, buf); t.pStr = buf; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += 12; t.pStr = GLOBAL_SIS (PlanetName); t.CharCount = (COUNT)~0; font_DrawText (&t); } s.origin.x = SIS_SCREEN_WIDTH >> 1; s.origin.y = SIS_SCREEN_HEIGHT >> 1; s.frame = planet[0]; DrawStamp (&s); if (LOBYTE (GLOBAL (CurrentActivity)) != IN_LAST_BATTLE) { #define NUM_DISPLAY_PTS (sizeof (display_pt) / sizeof (display_pt[0])) HSTARSHIP hStarShip, hNextShip; POINT display_pt[] = { { 10, 51}, {-10, 51}, { 33, 40}, {-33, 40}, { 49, 18}, {-49, 18}, { 52, -6}, {-52, -6}, { 44, -27}, {-44, -27}, }; for (hStarShip = GetHeadLink (&race_q[1]), i = 0; hStarShip && i < 60; hStarShip = hNextShip, ++i) { RECT r; STARSHIPPTR StarShipPtr; StarShipPtr = LockStarShip (&race_q[1], hStarShip); if (StarShipPtr->RaceDescPtr->ship_info.crew_level != INFINITE_FLEET) hNextShip = _GetSuccLink (StarShipPtr); else /* if infinite ships */ hNextShip = hStarShip; s.origin = display_pt[i % NUM_DISPLAY_PTS]; if (i >= NUM_DISPLAY_PTS) { COUNT angle, radius; radius = square_root ((long)s.origin.x * s.origin.x + (long)s.origin.y * s.origin.y) + ((i / NUM_DISPLAY_PTS) * 18); angle = ARCTAN (s.origin.x, s.origin.y); s.origin.x = COSINE (angle, radius); s.origin.y = SINE (angle, radius); } s.frame = SetAbsFrameIndex ( StarShipPtr->RaceDescPtr->ship_info.icons, 0); GetFrameRect (s.frame, &r); s.origin.x += (SIS_SCREEN_WIDTH >> 1) - (r.extent.width >> 1); s.origin.y += (SIS_SCREEN_HEIGHT >> 1) - (r.extent.height >> 1); DrawStamp (&s); UnlockStarShip (&race_q[1], hStarShip); } } UnbatchGraphics (); DestroyDrawable (ReleaseDrawable (SegueFrame)); ScreenTransition (3, NULL); SetResourceIndex (hOldIndex); UnlockMutex (GraphicsLock); { MENU_STATE MenuState; MenuState.InputFunc = DoSelectAction; MenuState.Initialized = FALSE; DrawMenuStateStrings (PM_CONVERSE, MenuState.CurState = HAIL); LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); DoInput ((PVOID)&MenuState, TRUE); LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); UnlockMutex (GraphicsLock); return (MenuState.CurState); } } static void DrawFadeText (const UNICODE *str1, const UNICODE *str2, BOOLEAN fade_in, PRECT pRect) { SIZE i; DWORD TimeIn; TEXT t1, t2; static const COLOR fade_cycle[] = { BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x1D), BUILD_COLOR (MAKE_RGB15 (0x09, 0x09, 0x09), 0x1E), BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F), BUILD_COLOR (MAKE_RGB15 (0x06, 0x06, 0x06), 0x20), BUILD_COLOR (MAKE_RGB15 (0x05, 0x05, 0x05), 0x21), BUILD_COLOR (MAKE_RGB15 (0x04, 0x04, 0x04), 0x22), BUILD_COLOR (MAKE_RGB15 (0x03, 0x03, 0x03), 0x23), }; #define NUM_FADES (sizeof (fade_cycle) / sizeof (fade_cycle[0])) t1.baseline.x = pRect->corner.x + 100; t1.baseline.y = pRect->corner.y + 45; t1.align = ALIGN_CENTER; t1.pStr = str1; t1.CharCount = (COUNT)~0; t2 = t1; t2.baseline.y += 11; t2.pStr = str2; FlushInput (); TimeIn = GetTimeCounter (); if (fade_in) { for (i = 0; i < (SIZE) NUM_FADES; ++i) { UnlockMutex (GraphicsLock); if (AnyButtonPress (TRUE)) i = NUM_FADES - 1; LockMutex (GraphicsLock); SetContextForeGroundColor (fade_cycle[i]); font_DrawText (&t1); font_DrawText (&t2); SleepThreadUntil (TimeIn + (ONE_SECOND / 20)); TimeIn = GetTimeCounter (); } } else { for (i = NUM_FADES - 1; i >= 0; --i) { UnlockMutex (GraphicsLock); if (AnyButtonPress (TRUE)) i = 0; LockMutex (GraphicsLock); SetContextForeGroundColor (fade_cycle[i]); font_DrawText (&t1); font_DrawText (&t2); SleepThreadUntil (TimeIn + (ONE_SECOND / 20)); TimeIn = GetTimeCounter (); } SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x0A, 0x0A), 0x08)); font_DrawText (&t1); font_DrawText (&t2); } } COUNT UninitEncounter (void) { COUNT ships_killed; ships_killed = 0; LockMutex (GraphicsLock); free_gravity_well (); if ((GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD)) || GLOBAL_SIS (CrewEnlisted) == (COUNT)~0 || LOBYTE (GLOBAL (CurrentActivity)) == IN_LAST_BATTLE || LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) goto ExitUninitEncounter; if (GET_GAME_STATE (BATTLE_SEGUE) == 0) { ReinitQueue (&race_q[0]); ReinitQueue (&race_q[1]); } else { BOOLEAN Sleepy; DWORD Time; SIZE VictoryState; COUNT RecycleAmount = 0; SIZE i; RECT r, scavenge_r; TEXT t; STAMP ship_s; const UNICODE *str1 = NULL; const UNICODE *str2 = NULL; UNICODE buf[80]; HSTARSHIP hStarShip; SHIP_FRAGMENTPTR FragPtr; static const COLOR fade_ship_cycle[] = { BUILD_COLOR (MAKE_RGB15 (0x07, 0x00, 0x00), 0x2F), BUILD_COLOR (MAKE_RGB15 (0x0F, 0x00, 0x00), 0x2D), BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x27), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x14, 0x14), 0x25), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x14, 0x14), 0x25), BUILD_COLOR (MAKE_RGB15 (0x1F, 0x0A, 0x0A), 0x27), BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x00), 0x2A), BUILD_COLOR (MAKE_RGB15 (0x17, 0x00, 0x00), 0x2B), }; #define NUM_SHIP_FADES (sizeof (fade_ship_cycle) / \ sizeof (fade_ship_cycle[0])) COUNT race_bounty[] = { RACE_SHIP_COST }; SET_GAME_STATE (BATTLE_SEGUE, 0); SET_GAME_STATE (BOMB_CARRIER, 0); VictoryState = ( HIBYTE (battle_counter) || !LOBYTE (battle_counter) || GET_GAME_STATE (URQUAN_PROTECTING_SAMATRA) ) ? 0 : 1; hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); EncounterRace = GET_RACE_ID (FragPtr); if (GetStarShipFromIndex (&GLOBAL (avail_race_q), EncounterRace) == 0) { VictoryState = -1; InitSISContexts (); } UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); Sleepy = TRUE; for (i = 0; i < NUM_SIDES; ++i) { PQUEUE pQueue; HSTARSHIP hNextShip; if (i == 0) pQueue = &GLOBAL (built_ship_q); else { if (VictoryState < 0) VictoryState = 0; else { DrawSISFrame (); DrawSISMessage (NULL_PTR); if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE) DrawHyperCoords (GLOBAL (ShipStamp.origin)); else if (HIWORD (GLOBAL (ShipStamp.frame)) == 0) DrawHyperCoords (CurStarDescPtr->star_pt); else DrawSISTitle(GLOBAL_SIS (PlanetName)); SetContext (SpaceContext); if (VictoryState) DrawArmadaPickShip (TRUE, &scavenge_r); } pQueue = &GLOBAL (npc_built_ship_q); } ReinitQueue (&race_q[(NUM_SIDES - 1) - i]); for (hStarShip = GetHeadLink (pQueue); hStarShip; hStarShip = hNextShip) { FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); hNextShip = _GetSuccLink (FragPtr); if (FragPtr->ShipInfo.crew_level == 0 || (VictoryState && i == NUM_SIDES - 1)) { if (i == NUM_SIDES - 1) { ++ships_killed; if (VictoryState) { #define MAX_DEAD_DISPLAYED 5 COUNT j; if (ships_killed == 1) { RecycleAmount = 0; DrawStatusMessage ((UNICODE *)~0); ship_s.origin.x = scavenge_r.corner.x + 32; ship_s.origin.y = scavenge_r.corner.y + 56; ship_s.frame = IncFrameIndex ( FragPtr->ShipInfo.icons); DrawStamp (&ship_s); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F)); SetContextFont (TinyFont); GetStringContents ( FragPtr->ShipInfo.race_strings, (STRINGPTR)buf, FALSE); // XXX: this will not work with UTF-8 strings strupr (buf); t.baseline.x = scavenge_r.corner.x + 100; t.baseline.y = scavenge_r.corner.y + 68; t.align = ALIGN_CENTER; t.pStr = buf; t.CharCount = (COUNT)~0; font_DrawText (&t); t.baseline.y += 6; t.pStr = GAME_STRING ( ENCOUNTER_STRING_BASE + 3); t.CharCount = (COUNT)~0; font_DrawText (&t); ship_s.frame = FragPtr->ShipInfo.icons; SetContextFont (MicroFont); str1 = GAME_STRING ( ENCOUNTER_STRING_BASE + 4); str2 = GAME_STRING ( ENCOUNTER_STRING_BASE + 5), DrawFadeText (str1, str2, TRUE, &scavenge_r); } r.corner.y = scavenge_r.corner.y + 9; r.extent.height = 22; SetContextForeGroundColor (BLACK_COLOR); r.extent.width = 34; r.corner.x = scavenge_r.corner.x + scavenge_r.extent.width - (10 + r.extent.width); DrawFilledRectangle (&r); /* collect bounty ResUnits */ j = race_bounty[EncounterRace] >> 3; RecycleAmount += j; sprintf (buf, "%u", RecycleAmount); t.baseline.x = r.corner.x + r.extent.width - 1; t.baseline.y = r.corner.y + 14; t.align = ALIGN_RIGHT; t.pStr = buf; t.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x18), 0x50)); font_DrawText (&t); DeltaSISGauges (0, 0, j); if ((VictoryState++ - 1) % MAX_DEAD_DISPLAYED) ship_s.origin.x += 17; else { SetContextForeGroundColor (BLACK_COLOR); r.corner.x = scavenge_r.corner.x + 10; r.extent.width = 104; DrawFilledRectangle (&r); ship_s.origin.x = r.corner.x + 2; ship_s.origin.y = scavenge_r.corner.y + 12; } if (Sleepy) { Time = GetTimeCounter (); for (j = 0; j < NUM_SHIP_FADES; ++j) { UnlockMutex (GraphicsLock); Sleepy = (BOOLEAN)!AnyButtonPress (TRUE); LockMutex (GraphicsLock); if (!Sleepy) break; SetContextForeGroundColor (fade_ship_cycle[j]); DrawFilledStamp (&ship_s); SleepThreadUntil (Time + (ONE_SECOND / 15)); Time = GetTimeCounter (); } } DrawStamp (&ship_s); } } UnlockStarShip (pQueue, hStarShip); RemoveQueue (pQueue, hStarShip); FreeStarShip (pQueue, hStarShip); continue; } UnlockStarShip (pQueue, hStarShip); } } if (VictoryState) { #ifdef NEVER DestroyDrawable (ReleaseDrawable (s.frame)); #endif /* NEVER */ FlushInput (); Time = GetTimeCounter () + (ONE_SECOND * 3); UnlockMutex (GraphicsLock); while (!(AnyButtonPress (TRUE)) && GetTimeCounter () < Time) TaskSwitch (); LockMutex (GraphicsLock); if (!CurrentInputState.key[PlayerOne][KEY_ESCAPE]) { DrawFadeText (str1, str2, FALSE, &scavenge_r); if (!CurrentInputState.key[PlayerOne][KEY_ESCAPE]) { SetContextForeGroundColor (BLACK_COLOR); r.corner.x = scavenge_r.corner.x + 10; r.extent.width = 132; DrawFilledRectangle (&r); sprintf (buf, "%u %s", RecycleAmount, GAME_STRING (STATUS_STRING_BASE + 1)); // "RU" t.baseline.x = r.corner.x + (r.extent.width >> 1); t.baseline.y = r.corner.y + 14; t.align = ALIGN_CENTER; t.pStr = buf; t.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x18), 0x50)); font_DrawText (&t); str1 = GAME_STRING (ENCOUNTER_STRING_BASE + 6); str2 = GAME_STRING (ENCOUNTER_STRING_BASE + 7); DrawFadeText (str1, str2, TRUE, &scavenge_r); Time = GetTimeCounter () + ONE_SECOND * 2; UnlockMutex (GraphicsLock); while (!(AnyButtonPress (TRUE)) && GetTimeCounter () < Time) TaskSwitch (); LockMutex (GraphicsLock); if (!CurrentInputState.key[PlayerOne][KEY_ESCAPE]) DrawFadeText (str1, str2, FALSE, &scavenge_r); } } DrawStatusMessage (NULL_PTR); } if (ships_killed && EncounterRace == THRADDASH_SHIP && !GET_GAME_STATE (THRADD_MANNER)) { if ((ships_killed += GET_GAME_STATE (THRADDASH_BODY_COUNT)) > THRADDASH_BODY_THRESHOLD) ships_killed = THRADDASH_BODY_THRESHOLD; SET_GAME_STATE (THRADDASH_BODY_COUNT, ships_killed); } } ExitUninitEncounter: UnlockMutex (GraphicsLock); return (ships_killed); } void EncounterBattle (void) { MEM_HANDLE hLastIndex; ACTIVITY OldActivity; extern UWORD nth_frame; LockMutex (GraphicsLock); SET_GAME_STATE (BATTLE_SEGUE, 1); hLastIndex = SetResourceIndex (hResIndex); OldActivity = GLOBAL (CurrentActivity); if (LOBYTE (OldActivity) == IN_LAST_BATTLE) GLOBAL (CurrentActivity) = MAKE_WORD (IN_LAST_BATTLE, 0); else GLOBAL (CurrentActivity) = MAKE_WORD (IN_ENCOUNTER, 0); // FreeSC2Data (); // DestroyFont (ReleaseFont (MicroFont)); WaitForSoundEnd (TFBSOUND_WAIT_ALL); // DestroySound (ReleaseSound (MenuSounds)); if (GLOBAL (glob_flags) & CYBORG_ENABLED) { BYTE cur_speed; cur_speed = (BYTE)(GLOBAL (glob_flags) & COMBAT_SPEED_MASK) >> COMBAT_SPEED_SHIFT; if (cur_speed == 1) cur_speed = 0; /* normal speed */ else if (cur_speed == 2) ++cur_speed; /* 4x speed, 3 of 4 frames skipped */ else /* if (cur_speed == 3) */ cur_speed = (BYTE)~0; /* maximum speed - no rendering */ nth_frame = MAKE_WORD (1, cur_speed); PlayerControl[0] = CYBORG_CONTROL | AWESOME_RATING; PlayerInput[0] = ComputerInput; } GameSounds = CaptureSound (LoadSound (GAME_SOUNDS)); UnlockMutex (GraphicsLock); Battle (); LockMutex (GraphicsLock); DestroySound (ReleaseSound (GameSounds)); GameSounds = 0; if (GLOBAL (CurrentActivity) & CHECK_ABORT) GLOBAL_SIS (CrewEnlisted) = (COUNT)~0; if (GLOBAL (glob_flags) & CYBORG_ENABLED) { nth_frame = MAKE_WORD (0, 0); PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING; PlayerInput[0] = HumanInput[0]; } SetResourceIndex (hResIndex); // MicroFont = CaptureFont ( // LoadFont (MICRO_FONT) // ); // MenuSounds = CaptureSound (LoadSound (MENU_SOUNDS)); // LoadSC2Data (); GLOBAL (CurrentActivity) = OldActivity; SetResourceIndex (hLastIndex); UnlockMutex (GraphicsLock); } uqm-0.6.2/sc2/src/sc2code/pickmele.h0000600000175000017500000000203410543202103015536 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _PICKMELE_H #define _PICKMELE_H #include "races.h" #include "libs/compiler.h" HSTARSHIP GetMeleeStarShip (STARSHIPPTR LastStarShipPtr, COUNT which_player); typedef struct getmelee_struct GETMELEE_STATE; bool updateMeleeSelection (GETMELEE_STATE *gms, COUNT player, COUNT ship); #endif /* _PICKMELE_H */ uqm-0.6.2/sc2/src/sc2code/gameev.h0000600000175000017500000000301110543202103015205 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _GAMEEV_H #define _GAMEEV_H #include "libs/compiler.h" #include "libs/gfxlib.h" enum { ARILOU_ENTRANCE_EVENT = 0, ARILOU_EXIT_EVENT, HYPERSPACE_ENCOUNTER_EVENT, KOHR_AH_VICTORIOUS_EVENT, ADVANCE_PKUNK_MISSION, ADVANCE_THRADD_MISSION, ZOQFOT_DISTRESS_EVENT, ZOQFOT_DEATH_EVENT, SHOFIXTI_RETURN_EVENT, ADVANCE_UTWIG_SUPOX_MISSION, KOHR_AH_GENOCIDE_EVENT, SPATHI_SHIELD_EVENT, ADVANCE_ILWRATH_MISSION, ADVANCE_MYCON_MISSION, ARILOU_UMGAH_CHECK, YEHAT_REBEL_EVENT, SLYLANDRO_RAMP_UP, SLYLANDRO_RAMP_DOWN, NUM_EVENTS }; typedef enum { CLOSING = 0, OPENING } ARILOU_GATE_STATE; extern void AddInitialGameEvents (void); extern void EventHandler (BYTE selector); extern void SetRaceDest (BYTE which_race, COORD x, COORD y, BYTE days_left, BYTE func_index); #endif /* _GAMEEV_H */ uqm-0.6.2/sc2/src/sc2code/cleanup.c0000600000175000017500000000507210543202103015374 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "battle.h" #include "master.h" #include "nameref.h" #include "reslib.h" #include "gamestr.h" #include "init.h" #include "hyper.h" #include "planets/lander.h" #include "starcon.h" #include "setup.h" #include "sounds.h" #include "libs/sndlib.h" #include "libs/vidlib.h" // XXX: we do not current have a header for this prototype to live in // should be something like solarsys.h extern void FreeIPData (void); static void UninitContexts (void); static void UninitKernel (BOOLEAN ships); static void UninitGameKernel (void); void FreeKernel (void) { UninitKernel (TRUE); UninitContexts (); UNINIT_INSTANCES (); UninitResourceSystem (); UninitPlayerInput (); DestroyDrawable (ReleaseDrawable (Screen)); DestroyContext (ReleaseContext (ScreenContext)); UninitVideo (); UninitSound (); UninitGraphics (); } static void UninitContexts (void) { UninitQueue (&disp_q); DestroyContext (ReleaseContext (OffScreenContext)); DestroyContext (ReleaseContext (SpaceContext)); DestroyContext (ReleaseContext (StatusContext)); } static void UninitKernel (BOOLEAN ships) { UninitSpace (); DestroySound (ReleaseSound (MenuSounds)); DestroyFont (ReleaseFont (MicroFont)); DestroyStringTable (ReleaseStringTable (GameStrings)); DestroyDrawable (ReleaseDrawable (StatusFrame)); DestroyDrawable (ReleaseDrawable (ActivityFrame)); DestroyFont (ReleaseFont (TinyFont)); DestroyFont (ReleaseFont (StarConFont)); UninitQueue (&race_q[0]); UninitQueue (&race_q[1]); if (ships) FreeMasterShipList (); ActivityFrame = 0; } void FreeGameData (void) { FreeSC2Data (); FreeLanderData (); FreeIPData (); FreeHyperData (); } static void UninitGameKernel (void) { // XXX: this function is never called. Why not? (BUG?) if (ActivityFrame) { FreeGameData (); UninitKernel (FALSE); UninitContexts (); } } uqm-0.6.2/sc2/src/sc2code/grpinfo.c0000600000175000017500000005060010543202103015406 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "build.h" #include "encount.h" #include "file.h" #include "globdata.h" #include "intel.h" #include "sis.h" #include "state.h" #include "libs/mathlib.h" #include "libs/log.h" #ifdef HAVE_UNISTD_H #include #endif static BYTE LastEncGroup; // Last encountered group, saved into state files //#define DEBUG_GROUPS typedef struct { BYTE NumGroups; BYTE day_index, month_index; COUNT star_index, year_index; // day_index, month_index, year_index specify when // random groups expire (if you were to leave the system // by going to HSpace and stay there till such time) // star_index is the index of a star this group header // applies to; ~0 means uninited DWORD GroupOffset[MAX_BATTLE_GROUPS + 1]; // Absolute offsets of group definitions in a state file // Group 0 is actually a list of groups present in solarsys // Groups 1..max are definitions of actual battle groups // containing ships composition and status // Each group has the following format: // 1 byte, RaceType (LastEncGroup in Group 0) // 1 byte, NumShips // Ships follow: // 1 byte, RaceType // 16 bytes, part of SHIP_FRAGMENT struct } GROUP_HEADER; static void ReadGroupHeader (PVOID fp, GROUP_HEADER* pGH) { sread_8 (fp, &pGH->NumGroups); sread_8 (fp, &pGH->day_index); sread_8 (fp, &pGH->month_index); sread_8 (fp, NULL); /* padding */ sread_16 (fp, &pGH->star_index); sread_16 (fp, &pGH->year_index); sread_a32 (fp, pGH->GroupOffset, MAX_BATTLE_GROUPS + 1); } static void WriteGroupHeader (PVOID fp, GROUP_HEADER* pGH) { swrite_8 (fp, pGH->NumGroups); swrite_8 (fp, pGH->day_index); swrite_8 (fp, pGH->month_index); swrite_8 (fp, 0); /* padding */ swrite_16 (fp, pGH->star_index); swrite_16 (fp, pGH->year_index); swrite_a32 (fp, pGH->GroupOffset, MAX_BATTLE_GROUPS + 1); } static void ReadShipFragment (PVOID fp, SHIP_FRAGMENTPTR FragPtr) { BYTE tmpb; // Read SHIP_FRAGMENT elements sread_16 (fp, &FragPtr->s.Player); sread_8 (fp, &FragPtr->s.Captain); sread_8 (fp, NULL); /* padding */ // Read SHIP_INFO elements sread_16 (fp, &FragPtr->ShipInfo.ship_flags); sread_8 (fp, &FragPtr->ShipInfo.var1); sread_8 (fp, &FragPtr->ShipInfo.var2); sread_8 (fp, &tmpb); FragPtr->ShipInfo.crew_level = tmpb; sread_8 (fp, &tmpb); FragPtr->ShipInfo.max_crew = tmpb; sread_8 (fp, &FragPtr->ShipInfo.energy_level); sread_8 (fp, &FragPtr->ShipInfo.max_energy); sread_16 (fp, &FragPtr->ShipInfo.loc.x); sread_16 (fp, &FragPtr->ShipInfo.loc.y); } static void WriteShipFragment (PVOID fp, SHIP_FRAGMENTPTR FragPtr) { // Write SHIP_FRAGMENT elements swrite_16 (fp, FragPtr->s.Player); swrite_8 (fp, FragPtr->s.Captain); swrite_8 (fp, 0); /* padding */ // Write SHIP_INFO elements swrite_16 (fp, FragPtr->ShipInfo.ship_flags); swrite_8 (fp, FragPtr->ShipInfo.var1); swrite_8 (fp, FragPtr->ShipInfo.var2); swrite_8 (fp, FragPtr->ShipInfo.crew_level); swrite_8 (fp, FragPtr->ShipInfo.max_crew); swrite_8 (fp, FragPtr->ShipInfo.energy_level); swrite_8 (fp, FragPtr->ShipInfo.max_energy); swrite_16 (fp, FragPtr->ShipInfo.loc.x); swrite_16 (fp, FragPtr->ShipInfo.loc.y); } void InitGroupInfo (BOOLEAN FirstTime) { PVOID fp; fp = OpenStateFile (RANDGRPINFO_FILE, "wb"); if (fp) { GROUP_HEADER GH; GH.NumGroups = 0; GH.star_index = (COUNT)~0; GH.GroupOffset[0] = 0; WriteGroupHeader (fp, &GH); CloseStateFile (fp); } if (FirstTime && (fp = OpenStateFile (DEFGRPINFO_FILE, "wb"))) { // Group headers cannot start with offset 0 in // defined group info file, so bump it swrite_8 (fp, 0); CloseStateFile (fp); } } void UninitGroupInfo (void) { DeleteStateFile (DEFGRPINFO_FILE); DeleteStateFile (RANDGRPINFO_FILE); } void BuildGroups (void) { BYTE Index, BestIndex; COUNT BestPercent; POINT universe; HSTARSHIP hTemplate, hNextShip; BYTE HomeWorld[] = { 0, /* ARILOU_SHIP */ 0, /* CHMMR_SHIP */ 0, /* HUMAN_SHIP */ ORZ_DEFINED, /* ORZ_SHIP */ PKUNK_DEFINED, /* PKUNK_SHIP */ 0, /* SHOFIXTI_SHIP */ SPATHI_DEFINED, /* SPATHI_SHIP */ SUPOX_DEFINED, /* SUPOX_SHIP */ THRADD_DEFINED, /* THRADDASH_SHIP */ UTWIG_DEFINED, /* UTWIG_SHIP */ VUX_DEFINED, /* VUX_SHIP */ YEHAT_DEFINED, /* YEHAT_SHIP */ 0, /* MELNORME_SHIP */ DRUUGE_DEFINED, /* DRUUGE_SHIP */ ILWRATH_DEFINED, /* ILWRATH_SHIP */ MYCON_DEFINED, /* MYCON_SHIP */ 0, /* SLYLANDRO_SHIP */ UMGAH_DEFINED, /* UMGAH_SHIP */ 0, /* URQUAN_SHIP */ ZOQFOT_DEFINED, /* ZOQFOTPIK_SHIP */ 0, /* SYREEN_SHIP */ 0, /* BLACK_URQUAN_SHIP */ 0, /* YEHAT_REBEL_SHIP */ }; BYTE EncounterPercent[] = { RACE_INTERPLANETARY_PERCENT }; EncounterPercent[SLYLANDRO_SHIP] *= GET_GAME_STATE (SLYLANDRO_MULTIPLIER); Index = GET_GAME_STATE (UTWIG_SUPOX_MISSION); if (Index > 1 && Index < 5) HomeWorld[UTWIG_SHIP] = HomeWorld[SUPOX_SHIP] = 0; BestPercent = 0; universe = CurStarDescPtr->star_pt; for (hTemplate = GetHeadLink (&GLOBAL (avail_race_q)), Index = 0; hTemplate; hTemplate = hNextShip, ++Index) { COUNT i, encounter_radius; EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hTemplate); hNextShip = _GetSuccLink (TemplatePtr); if ((encounter_radius = TemplatePtr->ShipInfo.actual_strength) && (i = EncounterPercent[Index])) { SIZE dx, dy; DWORD d_squared; BYTE race_enc; race_enc = HomeWorld[Index]; if (race_enc && CurStarDescPtr->Index == race_enc) { // In general, there are always ships at the Homeworld for // the races specified in HomeWorld[] array. // XXX: This code is somewhat broken and the intent is not // 100% clear. Finding a Homeworld does not break you out // of the loop, so another race could override with its // ships when another race's SoI covers the Homeworld. // However, only a race later in the order can do that, so // for example, there will *always* be Yehat Rebel ships // at the Rebel Homeworld, but the same is not true for the // regular Yehat. BestIndex = Index; BestPercent = 70; if (race_enc == SPATHI_DEFINED || race_enc == SUPOX_DEFINED) BestPercent = 2; hNextShip = 0; goto FoundHome; } if (encounter_radius == (COUNT)~0) encounter_radius = (MAX_X_UNIVERSE + 1) << 1; else encounter_radius = (encounter_radius * SPHERE_RADIUS_INCREMENT) >> 1; if ((dx = universe.x - TemplatePtr->ShipInfo.loc.x) < 0) dx = -dx; if ((dy = universe.y - TemplatePtr->ShipInfo.loc.y) < 0) dy = -dy; if ((COUNT)dx < encounter_radius && (COUNT)dy < encounter_radius && (d_squared = (DWORD)dx * dx + (DWORD)dy * dy) < (DWORD)encounter_radius * encounter_radius) { DWORD rand_val; // EncounterPercent is only used in practice for the Slylandro // Probes, for the rest of races the chance of encounter is // calced directly below from the distance to the Homeworld if (TemplatePtr->ShipInfo.actual_strength != (COUNT)~0) { i = 70 - (COUNT)((DWORD)square_root (d_squared) * 60L / encounter_radius); } rand_val = TFB_Random (); if ((int)(LOWORD (rand_val) % 100) < (int)i && (BestPercent == 0 || (HIWORD (rand_val) % (i + BestPercent)) < i)) { if (TemplatePtr->ShipInfo.actual_strength == (COUNT)~0) { // The prevailing encounter chance is hereby limitted // to 4% for races with infinite SoI (currently, it // is only the Slylandro Probes) i = 4; } BestPercent = i; BestIndex = Index; } } } FoundHome: UnlockStarShip (&GLOBAL (avail_race_q), hTemplate); } if (BestPercent) { BYTE which_group, num_groups; BYTE EncounterMakeup[] = { RACE_ENCOUNTER_MAKEUP }; which_group = 0; num_groups = ((COUNT)TFB_Random () % (BestPercent >> 1)) + 1; if (num_groups > (MAX_BATTLE_GROUPS >> 1)) num_groups = (MAX_BATTLE_GROUPS >> 1); else if (num_groups < 5 && (Index = HomeWorld[BestIndex]) && CurStarDescPtr->Index == Index) num_groups = 5; do { for (Index = HINIBBLE (EncounterMakeup[BestIndex]); Index; --Index) { if (Index <= LONIBBLE (EncounterMakeup[BestIndex]) || (COUNT)TFB_Random () % 100 < 50) CloneShipFragment (BestIndex, &GLOBAL (npc_built_ship_q), 0); } PutGroupInfo (GROUPS_RANDOM, ++which_group); ReinitQueue (&GLOBAL (npc_built_ship_q)); } while (--num_groups); } GetGroupInfo (GROUPS_RANDOM, GROUP_INIT_IP); } static void FlushGroupInfo (GROUP_HEADER *pGH, DWORD offset, BYTE which_group, PVOID fp) { BYTE RaceType, NumShips; HSTARSHIP hStarShip; SHIP_FRAGMENTPTR FragPtr; if (which_group == GROUP_LIST) { QUEUE temp_q; HSTARSHIP hNextShip; if (pGH->GroupOffset[0] == 0) pGH->GroupOffset[0] = LengthStateFile (fp); temp_q = GLOBAL (npc_built_ship_q); SetHeadLink (&GLOBAL (npc_built_ship_q), 0); SetTailLink (&GLOBAL (npc_built_ship_q), 0); for (hStarShip = GetHeadLink (&temp_q); hStarShip; hStarShip = hNextShip) { COUNT crew_level; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &temp_q, hStarShip); hNextShip = _GetSuccLink (FragPtr); crew_level = FragPtr->ShipInfo.crew_level; which_group = GET_GROUP_ID (FragPtr); UnlockStarShip (&temp_q, hStarShip); if (crew_level == 0) { if (GLOBAL (BattleGroupRef)) PutGroupInfo (GLOBAL (BattleGroupRef), which_group); else FlushGroupInfo (pGH, GROUPS_RANDOM, which_group, fp); pGH->GroupOffset[which_group] = 0; RemoveQueue (&temp_q, hStarShip); FreeStarShip (&temp_q, hStarShip); } } GLOBAL (npc_built_ship_q) = temp_q; which_group = GROUP_LIST; } else if (which_group > pGH->NumGroups) { pGH->NumGroups = which_group; pGH->GroupOffset[which_group] = LengthStateFile (fp); hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); RaceType = GET_RACE_ID (FragPtr); SeekStateFile (fp, pGH->GroupOffset[which_group], SEEK_SET); swrite_8 (fp, RaceType); UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } SeekStateFile (fp, offset, SEEK_SET); WriteGroupHeader (fp, pGH); #ifdef DEBUG_GROUPS log_add (log_Debug, "1)FlushGroupInfo(%lu): WG = %u(%lu), NG = %u, " "SI = %u", offset, which_group, pGH->GroupOffset[which_group], pGH->NumGroups, pGH->star_index); #endif /* DEBUG_GROUPS */ NumShips = (BYTE)CountLinks (&GLOBAL (npc_built_ship_q)); if (which_group != GROUP_LIST) { // skip RaceType SeekStateFile (fp, pGH->GroupOffset[which_group] + 1, SEEK_SET); } else { SeekStateFile (fp, pGH->GroupOffset[0], SEEK_SET); swrite_8 (fp, LastEncGroup); } swrite_8 (fp, NumShips); hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); while (NumShips--) { HSTARSHIP hNextShip; FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip ); hNextShip = _GetSuccLink (FragPtr); RaceType = GET_RACE_ID (FragPtr); swrite_8 (fp, RaceType); #ifdef DEBUG_GROUPS if (which_group == GROUP_LIST) log_add (log_Debug, "F) type %u, loc %u<%d, %d>, task 0x%02x:%u", RaceType, GET_GROUP_LOC (FragPtr), FragPtr->ShipInfo.loc.x, FragPtr->ShipInfo.loc.y, GET_GROUP_MISSION (FragPtr), GET_GROUP_DEST (FragPtr)); #endif /* DEBUG_GROUPS */ WriteShipFragment (fp, FragPtr); UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); hStarShip = hNextShip; } } BOOLEAN GetGroupInfo (DWORD offset, BYTE which_group) { PVOID fp; if (offset != GROUPS_RANDOM && which_group != GROUP_LIST) fp = OpenStateFile (DEFGRPINFO_FILE, "r+b"); else fp = OpenStateFile (RANDGRPINFO_FILE, "r+b"); if (fp) { BYTE RaceType, NumShips; GROUP_HEADER GH; HSTARSHIP hStarShip; SHIP_FRAGMENTPTR FragPtr; SeekStateFile (fp, offset, SEEK_SET); ReadGroupHeader (fp, &GH); #ifdef DEBUG_GROUPS log_add (log_Debug, "GetGroupInfo(%lu): %u(%lu) out of %u", offset, which_group, GH.GroupOffset[which_group], GH.NumGroups); #endif /* DEBUG_GROUPS */ if (which_group == GROUP_INIT_IP) { COUNT month_index, day_index, year_index; ReinitQueue (&GLOBAL (npc_built_ship_q)); #ifdef DEBUG_GROUPS log_add (log_Debug, "%u == %u", GH.star_index, (COUNT)(CurStarDescPtr - star_array)); #endif /* DEBUG_GROUPS */ day_index = GH.day_index; month_index = GH.month_index; year_index = GH.year_index; if (offset == GROUPS_RANDOM && (GH.star_index != (COUNT)(CurStarDescPtr - star_array) || !ValidateEvent (ABSOLUTE_EVENT, &month_index, &day_index, &year_index))) { CloseStateFile (fp); #ifdef DEBUG_GROUPS if (GH.star_index == (COUNT)(CurStarDescPtr - star_array)) log_add (log_Debug, "GetGroupInfo: battle groups out of " "date %u/%u/%u!", month_index, day_index, year_index); #endif /* DEBUG_GROUPS */ // Erase random groups (out of date) fp = OpenStateFile (RANDGRPINFO_FILE, "wb"); GH.NumGroups = 0; GH.star_index = (COUNT)~0; GH.GroupOffset[0] = 0; WriteGroupHeader (fp, &GH); } else { for (which_group = 1; which_group <= GH.NumGroups; ++which_group) { if (GH.GroupOffset[which_group] == 0) continue; SeekStateFile (fp, GH.GroupOffset[which_group], SEEK_SET); sread_8 (fp, &RaceType); sread_8 (fp, &NumShips); if (NumShips) { BYTE task, group_loc; DWORD rand_val; hStarShip = CloneShipFragment (RaceType, &GLOBAL (npc_built_ship_q), 0); FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); OwnStarShip (FragPtr, BAD_GUY, 0); SET_GROUP_ID (FragPtr, which_group); rand_val = TFB_Random (); task = (BYTE)(LOBYTE (LOWORD (rand_val)) % ON_STATION); if (task == FLEE) task = ON_STATION; SET_ORBIT_LOC (FragPtr, NORMALIZE_FACING ( LOBYTE (HIWORD (rand_val)))); group_loc = pSolarSysState->SunDesc[0].NumPlanets; if (group_loc == 1 && task == EXPLORE) task = IN_ORBIT; else group_loc = (BYTE)(( HIBYTE (LOWORD (rand_val)) % group_loc ) + 1); SET_GROUP_DEST (FragPtr, group_loc); rand_val = TFB_Random (); FragPtr->ShipInfo.loc.x = (LOWORD (rand_val) % 10000) - 5000; FragPtr->ShipInfo.loc.y = (HIWORD (rand_val) % 10000) - 5000; if (task == EXPLORE) FragPtr->ShipInfo.group_counter = ((COUNT)TFB_Random () % MAX_REVOLUTIONS) << FACING_SHIFT; else { FragPtr->ShipInfo.group_counter = 0; if (task == ON_STATION) { COUNT angle; POINT org; XFormIPLoc (&pSolarSysState->PlanetDesc[ group_loc - 1].image.origin, &org, FALSE); angle = FACING_TO_ANGLE (GET_ORBIT_LOC ( FragPtr) + 1); FragPtr->ShipInfo.loc.x = org.x + COSINE (angle, STATION_RADIUS); FragPtr->ShipInfo.loc.y = org.y + SINE (angle, STATION_RADIUS); group_loc = 0; } } SET_GROUP_MISSION (FragPtr, task); SET_GROUP_LOC (FragPtr, group_loc); #ifdef DEBUG_GROUPS log_add (log_Debug, "battle group %u(0x%04x) strength " "%u, type %u, loc %u<%d, %d>, task %u", which_group, hStarShip, NumShips, RaceType, group_loc, FragPtr->ShipInfo.loc.x, FragPtr->ShipInfo.loc.y, task); #endif /* DEBUG_GROUPS */ UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } } if (offset != GROUPS_RANDOM) InitGroupInfo (FALSE); /* Wipe out random battle groups */ else if (ValidateEvent (ABSOLUTE_EVENT, /* still fresh */ &month_index, &day_index, &year_index)) { CloseStateFile (fp); return (TRUE); } } } else if (GH.GroupOffset[which_group]) { COUNT ShipsLeft; ShipsLeft = CountLinks (&GLOBAL (npc_built_ship_q)); if (which_group == GROUP_LIST) { SeekStateFile (fp, GH.GroupOffset[0], SEEK_SET); sread_8 (fp, &LastEncGroup); if (LastEncGroup) { if (GLOBAL (BattleGroupRef)) PutGroupInfo (GLOBAL (BattleGroupRef), LastEncGroup); else FlushGroupInfo (&GH, offset, LastEncGroup, fp); } } else { LastEncGroup = which_group; if (offset != GROUPS_RANDOM) PutGroupInfo (GROUPS_RANDOM, GROUP_LIST); else FlushGroupInfo (&GH, GROUPS_RANDOM, GROUP_LIST, fp); } ReinitQueue (&GLOBAL (npc_built_ship_q)); // skip RaceType SeekStateFile (fp, GH.GroupOffset[which_group] + 1, SEEK_SET); sread_8 (fp, &NumShips); while (NumShips--) { sread_8 (fp, &RaceType); hStarShip = CloneShipFragment (RaceType, &GLOBAL (npc_built_ship_q), 0); FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (npc_built_ship_q), hStarShip); ReadShipFragment (fp, FragPtr); #ifdef DEBUG_GROUPS if (which_group == GROUP_LIST) log_add (log_Debug, "G) type %u, loc %u<%d, %d>, " "task 0x%02x:%u", RaceType, GET_GROUP_LOC (FragPtr), FragPtr->ShipInfo.loc.x, FragPtr->ShipInfo.loc.y, GET_GROUP_MISSION (FragPtr), GET_GROUP_DEST (FragPtr)); #endif /* DEBUG_GROUPS */ if (GET_GROUP_ID (FragPtr) != LastEncGroup || which_group != GROUP_LIST || ShipsLeft) { #ifdef DEBUG_GROUPS log_add (log_Debug, "\n"); #endif /* DEBUG_GROUPS */ if (RaceType == SHOFIXTI_SHIP && which_group != GROUP_LIST && !GET_GAME_STATE (SHOFIXTI_RECRUITED)) { BYTE captains_name_index; if (!GET_GAME_STATE (SHOFIXTI_KIA)) captains_name_index = NAME_OFFSET + NUM_CAPTAINS_NAMES; else captains_name_index = NAME_OFFSET + NUM_CAPTAINS_NAMES + 1; OwnStarShip (FragPtr, BAD_GUY, captains_name_index); } UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } else { #ifdef DEBUG_GROUPS log_add (log_Debug, " -- REMOVING"); #endif /* DEBUG_GROUPS */ UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); RemoveQueue (&GLOBAL (npc_built_ship_q), hStarShip); FreeStarShip (&GLOBAL (npc_built_ship_q), hStarShip); } } } CloseStateFile (fp); } return (GetHeadLink (&GLOBAL (npc_built_ship_q)) != 0); } DWORD PutGroupInfo (DWORD offset, BYTE which_group) { PVOID fp; if (offset != GROUPS_RANDOM && which_group != GROUP_LIST) fp = OpenStateFile (DEFGRPINFO_FILE, "r+b"); else fp = OpenStateFile (RANDGRPINFO_FILE, "r+b"); if (fp) { GROUP_HEADER GH; if (offset == GROUPS_ADD_NEW) { offset = LengthStateFile (fp); SeekStateFile (fp, offset, SEEK_SET); // XXX: All important fields are inited here, and the // rest are inited below GH.NumGroups = 0; GH.star_index = (COUNT)~0; GH.GroupOffset[0] = 0; WriteGroupHeader (fp, &GH); } if (which_group != GROUP_LIST) { SeekStateFile (fp, offset, SEEK_SET); if (which_group == GROUP_SAVE_IP) { LastEncGroup = 0; which_group = GROUP_LIST; } } ReadGroupHeader (fp, &GH); #ifdef NEVER if (GetHeadLink (&GLOBAL (npc_built_ship_q)) || GH.GroupOffset[0] == 0) #endif /* NEVER */ { COUNT month_index, day_index, year_index; month_index = 0; day_index = 7; year_index = 0; ValidateEvent (RELATIVE_EVENT, &month_index, &day_index, &year_index); GH.day_index = (BYTE)day_index; GH.month_index = (BYTE)month_index; GH.year_index = year_index; } GH.star_index = CurStarDescPtr - star_array; #ifdef DEBUG_GROUPS log_add (log_Debug, "PutGroupInfo(%lu): %u out of %u -- %u/%u/%u", offset, which_group, GH.NumGroups, GH.month_index, GH.day_index, GH.year_index); #endif /* DEBUG_GROUPS */ FlushGroupInfo (&GH, offset, which_group, fp); CloseStateFile (fp); } return (offset); } uqm-0.6.2/sc2/src/sc2code/gendef.c0000600000175000017500000000577610543202103015210 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "encount.h" PLAN_GEN_FUNC GenerateIP (BYTE Index) { PLAN_GEN_FUNC GenFunc; switch (Index) { case SOL_DEFINED: GenFunc = GenerateSOL; break; case SHOFIXTI_DEFINED: GenFunc = GenerateShofixti; break; case START_COLONY_DEFINED: GenFunc = GenerateColony; break; case SPATHI_DEFINED: GenFunc = GenerateSpathi; break; case MELNORME0_DEFINED: case MELNORME1_DEFINED: case MELNORME2_DEFINED: case MELNORME3_DEFINED: case MELNORME4_DEFINED: case MELNORME5_DEFINED: case MELNORME6_DEFINED: case MELNORME7_DEFINED: case MELNORME8_DEFINED: GenFunc = GenerateMelnorme; break; case TALKING_PET_DEFINED: GenFunc = GenerateTalkingPet; break; case CHMMR_DEFINED: GenFunc = GenerateChmmr; break; case SYREEN_DEFINED: case MYCON_TRAP_DEFINED: GenFunc = GenerateSyreen; break; case BURVIXESE_DEFINED: GenFunc = GenerateBurvixes; break; case SLYLANDRO_DEFINED: GenFunc = GenerateSlylandro; break; case DRUUGE_DEFINED: GenFunc = GenerateDruuge; break; case BOMB_DEFINED: case UTWIG_DEFINED: GenFunc = GenerateUtwig; break; case AQUA_HELIX_DEFINED: case THRADD_DEFINED: GenFunc = GenerateThradd; break; case SUN_DEVICE_DEFINED: case MYCON_DEFINED: case EGG_CASE0_DEFINED: case EGG_CASE1_DEFINED: case EGG_CASE2_DEFINED: GenFunc = GenerateMycon; break; case ANDROSYNTH_DEFINED: case TAALO_PROTECTOR_DEFINED: case ORZ_DEFINED: GenFunc = GenerateOrz; break; case SHIP_VAULT_DEFINED: GenFunc = GenerateShipVault; break; case URQUAN_WRECK_DEFINED: GenFunc = GenerateUrquanWreck; break; case MAIDENS_DEFINED: case VUX_BEAST_DEFINED: case VUX_DEFINED: GenFunc = GenerateVUX; break; case SAMATRA_DEFINED: GenFunc = GenerateSamatra; break; case ZOQFOT_DEFINED: case ZOQ_SCOUT_DEFINED: GenFunc = GenerateZoqFotPik; break; case YEHAT_DEFINED: GenFunc = GenerateYehat; break; case PKUNK_DEFINED: GenFunc = GeneratePkunk; break; case SUPOX_DEFINED: GenFunc = GenerateSupox; break; case RAINBOW_DEFINED: GenFunc = GenerateRainbow; break; case ILWRATH_DEFINED: GenFunc = GenerateIlwrath; break; default: GenFunc = GenerateRandomIP; break; } return (GenFunc); } uqm-0.6.2/sc2/src/sc2code/controls.h0000600000175000017500000001135310543202101015612 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _CONTROLS_H_ #define _CONTROLS_H_ #include "races.h" // For STARSHIPPTR #include "libs/compiler.h" #include "libs/strlib.h" // Enumerated type for controls enum { KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_WEAPON, KEY_SPECIAL, KEY_ESCAPE, NUM_KEYS }; enum { KEY_PAUSE, KEY_EXIT, KEY_ABORT, KEY_DEBUG, KEY_MENU_UP, KEY_MENU_DOWN, KEY_MENU_LEFT, KEY_MENU_RIGHT, KEY_MENU_SELECT, KEY_MENU_CANCEL, KEY_MENU_SPECIAL, KEY_MENU_PAGE_UP, KEY_MENU_PAGE_DOWN, KEY_MENU_HOME, KEY_MENU_END, KEY_MENU_ZOOM_IN, KEY_MENU_ZOOM_OUT, KEY_MENU_DELETE, KEY_MENU_BACKSPACE, KEY_MENU_EDIT_CANCEL, KEY_MENU_SEARCH, KEY_MENU_NEXT, KEY_MENU_ANY, /* abstract char key */ NUM_MENU_KEYS }; typedef enum { CONTROL_TEMPLATE_KB_1, CONTROL_TEMPLATE_KB_2, CONTROL_TEMPLATE_KB_3, CONTROL_TEMPLATE_JOY_1, CONTROL_TEMPLATE_JOY_2, CONTROL_TEMPLATE_JOY_3, NUM_TEMPLATES } CONTROL_TEMPLATE; typedef struct _controller_input_state { int key[NUM_TEMPLATES][NUM_KEYS]; int menu[NUM_MENU_KEYS]; } CONTROLLER_INPUT_STATE; typedef UBYTE BATTLE_INPUT_STATE; #define BATTLE_LEFT ((BATTLE_INPUT_STATE)(1 << 0)) #define BATTLE_RIGHT ((BATTLE_INPUT_STATE)(1 << 1)) #define BATTLE_THRUST ((BATTLE_INPUT_STATE)(1 << 2)) #define BATTLE_WEAPON ((BATTLE_INPUT_STATE)(1 << 3)) #define BATTLE_SPECIAL ((BATTLE_INPUT_STATE)(1 << 4)) #define BATTLE_ESCAPE ((BATTLE_INPUT_STATE)(1 << 5)) #define BATTLE_DOWN ((BATTLE_INPUT_STATE)(1 << 6)) typedef BATTLE_INPUT_STATE (*battle_summary_func) (COUNT player, STARSHIPPTR StarShipPtr); extern battle_summary_func ComputerInput, HumanInput[], NetworkInput; extern battle_summary_func PlayerInput[]; extern CONTROLLER_INPUT_STATE CurrentInputState, PulsedInputState; extern volatile CONTROLLER_INPUT_STATE ImmediateInputState; extern CONTROL_TEMPLATE PlayerOne, PlayerTwo; void UpdateInputState (void); void FlushInputState (void); void TFB_ResetControls (void); void SetMenuRepeatDelay (DWORD min, DWORD max, DWORD step, BOOLEAN gestalt); void SetDefaultMenuRepeatDelay (void); void ResetKeyRepeat (void); BOOLEAN PauseGame (void); BOOLEAN DoConfirmExit (void); void TFB_Abort (void); BOOLEAN WaitAnyButtonOrQuit (BOOLEAN CheckSpecial); void WaitForNoInput (SIZE Duration); BOOLEAN ConfirmExit (void); void DoPopupWindow(const char *msg); void DoInput (PVOID pInputState, BOOLEAN resetInput); BATTLE_INPUT_STATE p1_combat_summary (COUNT player, STARSHIPPTR StarShipPtr); BATTLE_INPUT_STATE p2_combat_summary (COUNT player, STARSHIPPTR StarShipPtr); extern volatile BOOLEAN GamePaused, ExitRequested; typedef struct joy_char joy_char_t; typedef struct textentry_state { // standard state required by DoInput BOOLEAN (*InputFunc) (struct textentry_state *pTES); COUNT MenuRepeatDelay; // these are semi-private read-only BOOLEAN Initialized; DWORD NextTime; // use this for input frame timing BOOLEAN Success; // edit confirmed or canceled UNICODE *CacheStr; // cached copy to revert immediate changes STRING JoyAlphaString; // joystick alphabet definition BOOLEAN JoystickMode; // TRUE when doing joystick input BOOLEAN UpperRegister; // TRUE when entering Caps joy_char_t *JoyAlpha; // joystick alphabet int JoyAlphaLength; joy_char_t *JoyUpper; // joystick upper register joy_char_t *JoyLower; // joystick lower register int JoyRegLength; UNICODE *InsPt; // set to current pos of insertion point // these are public and must be set before calling DoTextEntry UNICODE *BaseStr; // set to string to edit int CursorPos; // set to current cursor pos in chars int MaxSize; // set to max size of edited string BOOLEAN (*ChangeCallback) (struct textentry_state *pTES); // returns TRUE if last change is OK BOOLEAN (*FrameCallback) (struct textentry_state *pTES); // called on every input frame; do whatever; // returns TRUE to continue processing void *CbParam; // callback parameter, use as you like } TEXTENTRY_STATE; typedef TEXTENTRY_STATE *PTEXTENTRY_STATE; BOOLEAN DoTextEntry (PTEXTENTRY_STATE pTES); #endif uqm-0.6.2/sc2/src/sc2code/hyper.c0000600000175000017500000012011310543202101015064 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "hyper.h" #include "build.h" #include "collide.h" #include "colors.h" #include "controls.h" #include "encount.h" #include "globdata.h" #include "init.h" #include "nameref.h" #include "resinst.h" #include "setup.h" #include "sounds.h" #include "libs/graphics/gfx_common.h" #include "libs/mathlib.h" #define XOFFS ((RADAR_SCAN_WIDTH + (UNIT_SCREEN_WIDTH << 2)) >> 1) #define YOFFS ((RADAR_SCAN_HEIGHT + (UNIT_SCREEN_HEIGHT << 2)) >> 1) static FRAME hyperstars[3]; static COLORMAP hypercmaps[2]; static BYTE fuel_ticks; static COUNT hyper_dx, hyper_dy, hyper_extra; void MoveSIS (PSIZE pdx, PSIZE pdy) { SIZE new_dx, new_dy; new_dx = *pdx; if ((GLOBAL_SIS (log_x) -= new_dx) < 0) { new_dx += (SIZE)GLOBAL_SIS (log_x); GLOBAL_SIS (log_x) = 0; } else if (GLOBAL_SIS (log_x) > MAX_X_LOGICAL) { new_dx += (SIZE)(GLOBAL_SIS (log_x) - MAX_X_LOGICAL); GLOBAL_SIS (log_x) = MAX_X_LOGICAL; } new_dy = *pdy; if ((GLOBAL_SIS (log_y) -= new_dy) < 0) { new_dy += (SIZE)GLOBAL_SIS (log_y); GLOBAL_SIS (log_y) = 0; } else if (GLOBAL_SIS (log_y) > MAX_Y_LOGICAL) { new_dy += (SIZE)(GLOBAL_SIS (log_y) - MAX_Y_LOGICAL); GLOBAL_SIS (log_y) = MAX_Y_LOGICAL; } if (new_dx != *pdx || new_dy != *pdy) { HELEMENT hElement, hNextElement; *pdx = new_dx; *pdy = new_dy; for (hElement = GetTailElement (); hElement != 0; hElement = hNextElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); if (!(ElementPtr->state_flags & PLAYER_SHIP)) hNextElement = GetPredElement (ElementPtr); else { ElementPtr->next.location.x = (LOG_SPACE_WIDTH >> 1) - new_dx; ElementPtr->next.location.y = (LOG_SPACE_HEIGHT >> 1) - new_dy; hNextElement = 0; } UnlockElement (hElement); } } if (GLOBAL_SIS (FuelOnBoard) && GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { COUNT cur_fuel_ticks; COUNT hyper_dist; DWORD adj_dx, adj_dy; if (new_dx < 0) new_dx = -new_dx; hyper_dx += new_dx; if (new_dy < 0) new_dy = -new_dy; hyper_dy += new_dy; /* These macros are also used in the fuel estimate on the starmap. */ adj_dx = LOGX_TO_UNIVERSE(16 * hyper_dx); adj_dy = MAX_Y_UNIVERSE - LOGY_TO_UNIVERSE(16 * hyper_dy); hyper_dist = square_root (adj_dx * adj_dx + adj_dy * adj_dy) + hyper_extra; cur_fuel_ticks = hyper_dist >> 4; if (cur_fuel_ticks > (COUNT)fuel_ticks) { #ifndef TESTING DeltaSISGauges (0, fuel_ticks - cur_fuel_ticks, 0); #endif /* TESTING */ if (cur_fuel_ticks > 0x00FF) { hyper_dx = 0; hyper_extra = hyper_dist & ((1 << 4) - 1); hyper_dy = 0; cur_fuel_ticks = 0; } fuel_ticks = (BYTE)cur_fuel_ticks; } } } void check_hyperspace_encounter (void) { BYTE Type; POINT universe; HSTARSHIP hStarShip, hNextShip; COUNT EncounterPercent[] = { RACE_HYPERSPACE_PERCENT }; universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)), Type = 0; hStarShip && (GLOBAL (CurrentActivity) & IN_BATTLE); hStarShip = hNextShip, ++Type) { COUNT encounter_radius; EXTENDED_SHIP_FRAGMENTPTR TemplatePtr; TemplatePtr = (EXTENDED_SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip ); hNextShip = _GetSuccLink (TemplatePtr); encounter_radius = TemplatePtr->ShipInfo.actual_strength; if (encounter_radius) { BYTE encounter_flags; SIZE dx, dy; COUNT percent; HENCOUNTER hEncounter; ENCOUNTERPTR EncounterPtr; encounter_flags = 0; percent = EncounterPercent[Type]; if (encounter_radius != (COUNT)~0) encounter_radius = (encounter_radius * SPHERE_RADIUS_INCREMENT) >> 1; else { HENCOUNTER hNextEncounter; encounter_radius = (MAX_X_UNIVERSE + 1) << 1; if (Type == SLYLANDRO_SHIP) { encounter_flags = ONE_SHOT_ENCOUNTER; if (!GET_GAME_STATE (STARBASE_AVAILABLE)) percent = 100; else percent *= GET_GAME_STATE (SLYLANDRO_MULTIPLIER); } else if (Type == MELNORME_SHIP && (GLOBAL_SIS (FuelOnBoard) == 0 || GET_GAME_STATE (USED_BROADCASTER)) && GET_GAME_STATE (MELNORME_ANGER) < 3) { if (!GET_GAME_STATE (USED_BROADCASTER)) percent = 30; else percent = 100; encounter_flags = ONE_SHOT_ENCOUNTER; } for (hEncounter = GetHeadEncounter (); hEncounter; hEncounter = hNextEncounter) { LockEncounter (hEncounter, &EncounterPtr); hNextEncounter = GetSuccEncounter (EncounterPtr); if (EncounterPtr->SD.Type == Type) { percent = 0; hNextEncounter = 0; } UnlockEncounter (hEncounter); } if (percent == 100 && Type == MELNORME_SHIP) { SET_GAME_STATE (BROADCASTER_RESPONSE, 1); } } if ((dx = universe.x - TemplatePtr->ShipInfo.loc.x) < 0) dx = -dx; if ((dy = universe.y - TemplatePtr->ShipInfo.loc.y) < 0) dy = -dy; if ((COUNT)dx < encounter_radius && (COUNT)dy < encounter_radius && (DWORD)dx * dx + (DWORD)dy * dy < (DWORD)encounter_radius * encounter_radius && ((COUNT)TFB_Random () % 100) < percent) { // Ship spawned for encounter. hEncounter = AllocEncounter (); if (hEncounter) { LockEncounter (hEncounter, &EncounterPtr); memset (EncounterPtr, 0, sizeof (*EncounterPtr)); EncounterPtr->origin = TemplatePtr->ShipInfo.loc; EncounterPtr->radius = encounter_radius; EncounterPtr->SD.Index = encounter_flags; EncounterPtr->SD.Type = Type; UnlockEncounter (hEncounter); PutEncounter (hEncounter); } } } UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } SET_GAME_STATE (USED_BROADCASTER, 0); } void FreeHyperData (void) { DestroyDrawable (ReleaseDrawable (hyperstars[0])); hyperstars[0] = 0; DestroyDrawable (ReleaseDrawable (hyperstars[1])); hyperstars[1] = 0; DestroyDrawable (ReleaseDrawable (hyperstars[2])); hyperstars[2] = 0; DestroyColorMap (ReleaseColorMap (hypercmaps[0])); hypercmaps[0] = 0; DestroyColorMap (ReleaseColorMap (hypercmaps[1])); hypercmaps[1] = 0; } static void LoadHyperData (void) { if (hyperstars[0] == 0) { hyperstars[0] = CaptureDrawable ( LoadGraphic (AMBIENT_MASK_PMAP_ANIM)); hyperstars[1] = CaptureDrawable ( LoadGraphic (HYPERSTARS_MASK_PMAP_ANIM)); hypercmaps[0] = CaptureColorMap (LoadColorMap (HYPER_COLOR_TAB)); hyperstars[2] = CaptureDrawable ( LoadGraphic (ARISPACE_MASK_PMAP_ANIM)); hypercmaps[1] = CaptureColorMap (LoadColorMap (ARISPACE_COLOR_TAB)); } } BOOLEAN LoadHyperspace (void) { hyper_dx = hyper_dy = hyper_extra = 0; fuel_ticks = 1; GLOBAL (ShipStamp.origin.x) = -MAX_X_UNIVERSE; GLOBAL (ShipStamp.origin.y) = -MAX_Y_UNIVERSE; LoadHyperData (); { FRAME F; F = hyperstars[0]; hyperstars[0] = stars_in_space; stars_in_space = F; } if (!(LastActivity & CHECK_LOAD)) RepairSISBorder (); else { if (LOBYTE (LastActivity) == 0) { DrawSISFrame (); } else { ClearSISRect (DRAW_SIS_DISPLAY); RepairSISBorder (); } } DrawSISMessage (NULL_PTR); SetContext (RadarContext); SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x0E, 0x00), 0x6C)); SetContext (SpaceContext); if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x07, 0x00, 0x00), 0x2F)); SetColorMap (GetColorMapAddress (hypercmaps[0])); } else { SetContextBackGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x1A, 0x00), 0x2F)); SetColorMap (GetColorMapAddress (hypercmaps[1])); SET_GAME_STATE (USED_BROADCASTER, 0); SET_GAME_STATE (BROADCASTER_RESPONSE, 0); } // ClearDrawable (); ClearSISRect (CLEAR_SIS_RADAR); return (TRUE); } BOOLEAN FreeHyperspace (void) { UnlockMutex (GraphicsLock); SuspendGameClock (); LockMutex (GraphicsLock); { FRAME F; F = hyperstars[0]; hyperstars[0] = stars_in_space; stars_in_space = F; } // FreeHyperData (); return (TRUE); } static void ElementToUniverse (ELEMENTPTR ElementPtr, PPOINT pPt) { SDWORD log_x, log_y; log_x = GLOBAL_SIS (log_x) + (ElementPtr->next.location.x - (LOG_SPACE_WIDTH >> 1)); log_y = GLOBAL_SIS (log_y) + (ElementPtr->next.location.y - (LOG_SPACE_HEIGHT >> 1)); pPt->x = LOGX_TO_UNIVERSE (log_x); pPt->y = LOGY_TO_UNIVERSE (log_y); } static void cleanup_hyperspace (void) { HENCOUNTER hEncounter, hNextEncounter; for (hEncounter = GetHeadEncounter (); hEncounter != 0; hEncounter = hNextEncounter) { ENCOUNTERPTR EncounterPtr; LockEncounter (hEncounter, &EncounterPtr); hNextEncounter = GetSuccEncounter (EncounterPtr); if (EncounterPtr->hElement) { ELEMENTPTR ElementPtr; LockElement (EncounterPtr->hElement, &ElementPtr); if (ElementPtr->state_flags & BAD_GUY) { RemoveEncounter (hEncounter); InsertEncounter (hEncounter, GetHeadEncounter ()); } UnlockElement (EncounterPtr->hElement); } EncounterPtr->hElement = 0; UnlockEncounter (hEncounter); } } typedef enum { RANDOM_ENCOUNTER_TRANSITION, INTERPLANETARY_TRANSITION, ARILOU_SPACE_TRANSITION } TRANSITION_TYPE; static void unhyper_transition (PELEMENT ElementPtr) { COUNT frame_index; ElementPtr->state_flags |= CHANGING; frame_index = GetFrameIndex (ElementPtr->current.image.frame); if (frame_index == 0) frame_index += ANGLE_TO_FACING (FULL_CIRCLE); else if (frame_index < ANGLE_TO_FACING (FULL_CIRCLE)) frame_index = NORMALIZE_FACING (frame_index + 1); else if (++frame_index == GetFrameCount (ElementPtr->current.image.frame)) { cleanup_hyperspace (); GLOBAL (CurrentActivity) &= ~IN_BATTLE; switch ((TRANSITION_TYPE) ElementPtr->turn_wait) { case RANDOM_ENCOUNTER_TRANSITION: SaveFlagshipState (); GLOBAL (CurrentActivity) |= START_ENCOUNTER; break; case INTERPLANETARY_TRANSITION: GLOBAL (ShipStamp.frame) = 0; SET_GAME_STATE (USED_BROADCASTER, 0); if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { GLOBAL (CurrentActivity) |= START_INTERPLANETARY; SET_GAME_STATE (ESCAPE_COUNTER, 0); } else { POINT pt; GLOBAL (autopilot.x) = GLOBAL (autopilot.y) = ~0; ElementToUniverse (ElementPtr, &pt); CurStarDescPtr = FindStar (NULL_PTR, &pt, 5, 5); if (CurStarDescPtr->star_pt.x == ARILOU_HOME_X && CurStarDescPtr->star_pt.y == ARILOU_HOME_Y) { GLOBAL (CurrentActivity) |= START_ENCOUNTER; } else { COUNT index; POINT portal_pt[] = { {4091, 7748}, {3184, 4906}, {9211, 6104}, {5673, 1207}, {1910, 926}, {8607, 151}, { 50, 1647}, {6117, 4131}, {5658, 9712}, {2302, 3988}, { 112, 9409}, {7752, 8906}, { 368, 6332}, {9735, 3153}, {5850, 6213}, }; index = CurStarDescPtr - ((STAR_DESCPTR)&star_array[NUM_SOLAR_SYSTEMS + 1]); GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (portal_pt[index].x); GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (portal_pt[index].y); SET_GAME_STATE (ARILOU_SPACE_SIDE, 0); } } break; case ARILOU_SPACE_TRANSITION: /* Enter QuasiSpace from HyperSpace by any portal, * or HyperSpace from QuasiSpace through the periodically * opening portal. */ GLOBAL (ShipStamp.frame) = 0; SET_GAME_STATE (USED_BROADCASTER, 0); GLOBAL (autopilot.x) = GLOBAL (autopilot.y) = ~0; if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { // From HyperSpace to QuasiSpace. GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (QUASI_SPACE_X); GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (QUASI_SPACE_Y); if (GET_GAME_STATE (PORTAL_COUNTER) == 0) { // Periodically appearing portal. SET_GAME_STATE (ARILOU_SPACE_SIDE, 3); } else { // Player-induced portal. SET_GAME_STATE (PORTAL_COUNTER, 0); SET_GAME_STATE (ARILOU_SPACE_SIDE, 3); } } else { // From QuasiSpace to HyperSpace through the // periodically appearing portal. GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX (ARILOU_SPACE_X); GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY (ARILOU_SPACE_Y); SET_GAME_STATE (ARILOU_SPACE_SIDE, 0); } break; } ZeroVelocityComponents (&ElementPtr->velocity); SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); return; } ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, frame_index); } static void init_transition (ELEMENTPTR ElementPtr0, ELEMENTPTR ElementPtr1, TRANSITION_TYPE which_transition) { SIZE dx, dy, num_turns; STARSHIPPTR StarShipPtr; dx = WORLD_TO_VELOCITY (ElementPtr0->next.location.x - ElementPtr1->next.location.x); dy = WORLD_TO_VELOCITY (ElementPtr0->next.location.y - ElementPtr1->next.location.y); ElementPtr1->state_flags |= NONSOLID; ElementPtr1->preprocess_func = unhyper_transition; ElementPtr1->postprocess_func = NULL_PTR; ElementPtr1->turn_wait = (BYTE) which_transition; GetElementStarShip (ElementPtr1, &StarShipPtr); if ((num_turns = GetFrameCount (ElementPtr1->next.image.frame) - ANGLE_TO_FACING (FULL_CIRCLE) + NORMALIZE_FACING (ANGLE_TO_FACING (FULL_CIRCLE) - StarShipPtr->ShipFacing)) == 0) num_turns = 1; SetVelocityComponents (&ElementPtr1->velocity, dx / num_turns, dy / num_turns); } BOOLEAN hyper_transition (PELEMENT ElementPtr) { if (ElementPtr->state_flags & APPEARING) { if (LastActivity & CHECK_LOAD) { LastActivity &= ~CHECK_LOAD; ElementPtr->current = ElementPtr->next; SetUpElement (ElementPtr); ElementPtr->state_flags |= DEFY_PHYSICS; return (FALSE); } else { ElementPtr->preprocess_func = (void (*) (struct element *ElementPtr))hyper_transition; ElementPtr->postprocess_func = NULL_PTR; ElementPtr->state_flags |= NONSOLID; ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, GetFrameCount (ElementPtr->current.image.frame) - 1); } } else { COUNT frame_index; frame_index = GetFrameIndex (ElementPtr->current.image.frame); if (frame_index-- <= ANGLE_TO_FACING (FULL_CIRCLE)) { STARSHIPPTR StarShipPtr; if (frame_index == ANGLE_TO_FACING (FULL_CIRCLE) - 1) frame_index = 0; else frame_index = NORMALIZE_FACING (frame_index); GetElementStarShip (ElementPtr, &StarShipPtr); if (frame_index == StarShipPtr->ShipFacing) { ElementPtr->preprocess_func = ship_preprocess; ElementPtr->postprocess_func = ship_postprocess; ElementPtr->state_flags &= ~NONSOLID; } } ElementPtr->state_flags |= CHANGING; ElementPtr->next.image.frame = SetAbsFrameIndex (ElementPtr->current.image.frame, frame_index); if (!(ElementPtr->state_flags & NONSOLID)) { ElementPtr->current = ElementPtr->next; SetUpElement (ElementPtr); ElementPtr->state_flags |= DEFY_PHYSICS; } } return (TRUE); } static void hyper_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if ((ElementPtr1->state_flags & PLAYER_SHIP) && GET_GAME_STATE (PORTAL_COUNTER) == 0) { SIZE dx, dy; POINT pt; STAR_DESCPTR SDPtr; STARSHIPPTR StarShipPtr; ElementToUniverse (ElementPtr0, &pt); SDPtr = FindStar (NULL_PTR, &pt, 5, 5); GetElementStarShip (ElementPtr1, &StarShipPtr); GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx, &dy); if (SDPtr == CurStarDescPtr || (ElementPtr1->state_flags & APPEARING) || !(dx || dy || (StarShipPtr->cur_status_flags & (LEFT | RIGHT | THRUST | WEAPON | SPECIAL)))) { CurStarDescPtr = SDPtr; ElementPtr0->state_flags |= DEFY_PHYSICS | COLLISION; } else if ((GLOBAL (CurrentActivity) & IN_BATTLE) && (GLOBAL (autopilot.x) == ~0 || GLOBAL (autopilot.y) == ~0 || (GLOBAL (autopilot.x) == SDPtr->star_pt.x && GLOBAL (autopilot.y) == SDPtr->star_pt.y))) { CurStarDescPtr = SDPtr; ElementPtr0->state_flags |= COLLISION; init_transition (ElementPtr0, ElementPtr1, INTERPLANETARY_TRANSITION); } } (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } static void hyper_death (PELEMENT ElementPtr) { if (!(ElementPtr->state_flags & DEFY_PHYSICS) && (GLOBAL (CurrentActivity) & IN_BATTLE)) CurStarDescPtr = 0; } static void arilou_space_death (PELEMENT ElementPtr) { if (!(ElementPtr->state_flags & DEFY_PHYSICS) || GET_GAME_STATE (ARILOU_SPACE_COUNTER) == 0) { if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { SET_GAME_STATE (ARILOU_SPACE_SIDE, 0); } else { SET_GAME_STATE (ARILOU_SPACE_SIDE, 3); } } } static void arilou_space_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { COUNT which_side; if (!(ElementPtr1->state_flags & PLAYER_SHIP)) return; which_side = GET_GAME_STATE (ARILOU_SPACE_SIDE); if (which_side == 0 || which_side == 3) { if (ElementPtr1->state_flags & DEFY_PHYSICS) { SET_GAME_STATE (ARILOU_SPACE_SIDE, which_side ^ 1); } else { init_transition (ElementPtr0, ElementPtr1, ARILOU_SPACE_TRANSITION); } } ElementPtr0->state_flags |= DEFY_PHYSICS | COLLISION; (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } static HELEMENT AllocHyperElement (STAR_DESCPTR SDPtr) { HELEMENT hHyperSpaceElement; hHyperSpaceElement = AllocElement (); if (hHyperSpaceElement) { ELEMENTPTR HyperSpaceElementPtr; LockElement (hHyperSpaceElement, &HyperSpaceElementPtr); HyperSpaceElementPtr->state_flags = CHANGING | FINITE_LIFE; HyperSpaceElementPtr->life_span = 1; HyperSpaceElementPtr->mass_points = 1; { long lx, ly; lx = UNIVERSE_TO_LOGX (SDPtr->star_pt.x) + (LOG_SPACE_WIDTH >> 1) - GLOBAL_SIS (log_x); HyperSpaceElementPtr->current.location.x = WRAP_X (lx); ly = UNIVERSE_TO_LOGY (SDPtr->star_pt.y) + (LOG_SPACE_HEIGHT >> 1) - GLOBAL_SIS (log_y); HyperSpaceElementPtr->current.location.y = WRAP_Y (ly); } SetPrimType (&DisplayArray[HyperSpaceElementPtr->PrimIndex], STAMP_PRIM); HyperSpaceElementPtr->current.image.farray = &hyperstars[1 + (GET_GAME_STATE (ARILOU_SPACE_SIDE) >> 1)]; UnlockElement (hHyperSpaceElement); } return (hHyperSpaceElement); } static void AddAmbientElement (void) { HELEMENT hHyperSpaceElement; hHyperSpaceElement = AllocElement (); if (hHyperSpaceElement) { SIZE dx, dy; DWORD rand_val; ELEMENTPTR HyperSpaceElementPtr; LockElement (hHyperSpaceElement, &HyperSpaceElementPtr); HyperSpaceElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID; SetPrimType (&DisplayArray[HyperSpaceElementPtr->PrimIndex], STAMP_PRIM); HyperSpaceElementPtr->preprocess_func = animation_preprocess; rand_val = TFB_Random (); dy = LOWORD (rand_val); dx = (SIZE)(LOBYTE (dy) % SPACE_WIDTH) - (SPACE_WIDTH >> 1); dy = (SIZE)(HIBYTE (dy) % SPACE_HEIGHT) - (SPACE_HEIGHT >> 1); HyperSpaceElementPtr->current.location.x = (LOG_SPACE_WIDTH >> 1) + DISPLAY_TO_WORLD (dx); HyperSpaceElementPtr->current.location.y = (LOG_SPACE_HEIGHT >> 1) + DISPLAY_TO_WORLD (dy); HyperSpaceElementPtr->current.image.farray = &stars_in_space; if (HIWORD (rand_val) & 7) { HyperSpaceElementPtr->life_span = 14; HyperSpaceElementPtr->current.image.frame = stars_in_space; } else { HyperSpaceElementPtr->life_span = 12; HyperSpaceElementPtr->current.image.frame = SetAbsFrameIndex (stars_in_space, 14); } UnlockElement (hHyperSpaceElement); InsertElement (hHyperSpaceElement, GetHeadElement ()); } } #define NUM_VORTEX_TRANSITIONS 9 #define VORTEX_WAIT 1 static void encounter_transition (PELEMENT ElementPtr) { ElementPtr->state_flags &= ~DISAPPEARING; ElementPtr->life_span = 1; if (ElementPtr->turn_wait) { --ElementPtr->turn_wait; } else { FRAME f; if (ElementPtr->hit_points) { f = DecFrameIndex (ElementPtr->current.image.frame); ElementPtr->next.image.frame = f; } else { f = IncFrameIndex (ElementPtr->current.image.frame); if (f != ElementPtr->current.image.farray[0]) ElementPtr->next.image.frame = f; else ElementPtr->death_func = NULL_PTR; } ElementPtr->turn_wait = VORTEX_WAIT; } } static void encounter_collision (PELEMENT ElementPtr0, PPOINT pPt0, PELEMENT ElementPtr1, PPOINT pPt1) { if ((ElementPtr1->state_flags & PLAYER_SHIP) && (GLOBAL (CurrentActivity) & IN_BATTLE)) { HENCOUNTER hEncounter, hNextEncounter; init_transition (ElementPtr0, ElementPtr1, RANDOM_ENCOUNTER_TRANSITION); for (hEncounter = GetHeadEncounter (); hEncounter != 0; hEncounter = hNextEncounter) { ENCOUNTERPTR EncounterPtr; LockEncounter (hEncounter, &EncounterPtr); hNextEncounter = GetSuccEncounter (EncounterPtr); if (EncounterPtr->hElement) { ELEMENTPTR ElementPtr; LockElement (EncounterPtr->hElement, &ElementPtr); ElementPtr->state_flags |= NONSOLID | IGNORE_SIMILAR; UnlockElement (EncounterPtr->hElement); } UnlockEncounter (hEncounter); } ElementPtr0->state_flags |= BAD_GUY; ZeroVelocityComponents (&ElementPtr0->velocity); } (void) pPt0; /* Satisfying compiler (unused parameter) */ (void) pPt1; /* Satisfying compiler (unused parameter) */ } static HELEMENT AddEncounterElement (ENCOUNTERPTR EncounterPtr, PPOINT puniverse) { BOOLEAN NewEncounter; HELEMENT hElement; STAR_DESC SD; if (GET_GAME_STATE (ARILOU_SPACE_SIDE) >= 2) return (0); if (EncounterPtr->SD.Index & ENCOUNTER_REFORMING) { EncounterPtr->SD.Index &= ~ENCOUNTER_REFORMING; EncounterPtr->transition_state = 100; if ((EncounterPtr->SD.Index & ONE_SHOT_ENCOUNTER) || LONIBBLE (EncounterPtr->SD.Index) == 0) return (0); } if (LONIBBLE (EncounterPtr->SD.Index)) { NewEncounter = FALSE; SD.star_pt = EncounterPtr->SD.star_pt; } else { BYTE Type; SIZE dx, dy; COUNT i, NumShips; DWORD radius_squared; BYTE EncounterMakeup[] = { RACE_ENCOUNTER_MAKEUP }; NewEncounter = TRUE; radius_squared = (DWORD)EncounterPtr->radius * EncounterPtr->radius; Type = EncounterPtr->SD.Type; NumShips = LONIBBLE (EncounterMakeup[Type]); for (i = HINIBBLE (EncounterMakeup[Type]) - NumShips; i; --i) { if ((COUNT)TFB_Random () % 100 < 50) ++NumShips; } if (NumShips > MAX_HYPER_SHIPS) NumShips = MAX_HYPER_SHIPS; EncounterPtr->SD.Index = MAKE_BYTE ( NumShips, HINIBBLE (EncounterPtr->SD.Index)); for (i = 0; i < NumShips; ++i) { HSTARSHIP hStarShip; SHIP_FRAGMENTPTR TemplatePtr; hStarShip = GetStarShipFromIndex (&GLOBAL (avail_race_q), Type); TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip ( &GLOBAL (avail_race_q), hStarShip); EncounterPtr->SD.ShipList[i] = TemplatePtr->ShipInfo; EncounterPtr->SD.ShipList[i].var1 = Type; UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } do { DWORD rand_val; rand_val = TFB_Random (); SD.star_pt.x = puniverse->x + (LOWORD (rand_val) % (XOFFS << 1)) - XOFFS; if (SD.star_pt.x < 0) SD.star_pt.x = 0; else if (SD.star_pt.x > MAX_X_UNIVERSE) SD.star_pt.x = MAX_X_UNIVERSE; SD.star_pt.y = puniverse->y + (HIWORD (rand_val) % (YOFFS << 1)) - YOFFS; if (SD.star_pt.y < 0) SD.star_pt.y = 0; else if (SD.star_pt.y > MAX_Y_UNIVERSE) SD.star_pt.y = MAX_Y_UNIVERSE; dx = SD.star_pt.x - EncounterPtr->origin.x; dy = SD.star_pt.y - EncounterPtr->origin.y; } while ((DWORD)((long)dx * dx + (long)dy * dy) > radius_squared); EncounterPtr->SD.star_pt = SD.star_pt; EncounterPtr->log_x = UNIVERSE_TO_LOGX (SD.star_pt.x); EncounterPtr->log_y = UNIVERSE_TO_LOGY (SD.star_pt.y); } hElement = AllocHyperElement (&SD); if (hElement) { SIZE i; ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); if ((i = EncounterPtr->transition_state) || NewEncounter) { if (i < 0) { i = -i; ElementPtr->hit_points = 1; } if (i == 0 || i > NUM_VORTEX_TRANSITIONS) i = NUM_VORTEX_TRANSITIONS; ElementPtr->current.image.frame = SetRelFrameIndex ( ElementPtr->current.image.farray[0], -i); ElementPtr->death_func = encounter_transition; } else { ElementPtr->current.image.frame = DecFrameIndex (ElementPtr->current.image.farray[0]); } ElementPtr->turn_wait = VORTEX_WAIT; ElementPtr->preprocess_func = NULL_PTR; ElementPtr->postprocess_func = NULL_PTR; ElementPtr->collision_func = encounter_collision; SetUpElement (ElementPtr); ElementPtr->IntersectControl.IntersectStamp.frame = DecFrameIndex (stars_in_space); SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); ElementPtr->state_flags |= NONSOLID | IGNORE_VELOCITY; UnlockElement (hElement); InsertElement (hElement, GetTailElement ()); } return (EncounterPtr->hElement = hElement); } #define GRID_OFFSET 200 static void DrawHyperGrid (COORD ux, COORD uy, COORD ox, COORD oy) { COORD sx, sy, ex, ey; RECT r; ClearDrawable (); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x10, 0x00), 0x6B)); if ((sx = ux - (RADAR_SCAN_WIDTH >> 1)) < 0) sx = 0; else sx -= sx % GRID_OFFSET; if ((ex = ux + (RADAR_SCAN_WIDTH >> 1)) > MAX_X_UNIVERSE + 1) ex = MAX_X_UNIVERSE + 1; if ((sy = uy - (RADAR_SCAN_HEIGHT >> 1)) < 0) sy = 0; else sy -= sy % GRID_OFFSET; if ((ey = uy + (RADAR_SCAN_HEIGHT >> 1)) > MAX_Y_UNIVERSE + 1) ey = MAX_Y_UNIVERSE + 1; r.corner.y = (COORD) ((long)(MAX_Y_UNIVERSE - ey) * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy; r.extent.width = 1; r.extent.height = ((COORD) ((long)(MAX_Y_UNIVERSE - sy) * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy) - r.corner.y + 1; for (ux = sx; ux <= ex; ux += GRID_OFFSET) { r.corner.x = (COORD) ((long)ux * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox; DrawFilledRectangle (&r); } while ((ux += GRID_OFFSET) < ex); r.corner.x = (COORD) ((long)sx * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox; r.extent.width = ((COORD) ((long)ex * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox) - r.corner.x + 1; r.extent.height = 1; for (uy = sy; uy <= ey; uy += GRID_OFFSET) { r.corner.y = (COORD)((long)(MAX_Y_UNIVERSE - uy) * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy; DrawFilledRectangle (&r); } while ((uy += GRID_OFFSET) < ey); } static void ProcessEncounters (PPOINT puniverse, COORD ox, COORD oy) { STAMP s; HENCOUNTER hEncounter, hNextEncounter; s.frame = SetAbsFrameIndex (stars_in_space, 91); for (hEncounter = GetHeadEncounter (); hEncounter; hEncounter = hNextEncounter) { COORD ex, ey; ENCOUNTERPTR EncounterPtr; LockEncounter (hEncounter, &EncounterPtr); hNextEncounter = GetSuccEncounter (EncounterPtr); if (EncounterPtr->hElement == 0 && AddEncounterElement (EncounterPtr, puniverse) == 0) { DeleteEncounter: UnlockEncounter (hEncounter); RemoveEncounter (hEncounter); FreeEncounter (hEncounter); continue; } { ELEMENTPTR ElementPtr; LockElement (EncounterPtr->hElement, &ElementPtr); if (ElementPtr->death_func) { if (EncounterPtr->transition_state && ElementPtr->turn_wait == 0) { --EncounterPtr->transition_state; if (EncounterPtr->transition_state >= NUM_VORTEX_TRANSITIONS) ++ElementPtr->turn_wait; else if (EncounterPtr->transition_state == -NUM_VORTEX_TRANSITIONS) { ElementPtr->death_func = NULL_PTR; UnlockElement (EncounterPtr->hElement); goto DeleteEncounter; } else SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM); } } else { SIZE delta_x, delta_y; COUNT encounter_radius; ElementPtr->life_span = 1; GetNextVelocityComponents (&ElementPtr->velocity, &delta_x, &delta_y, 1); if (ElementPtr->thrust_wait) --ElementPtr->thrust_wait; else if (!(ElementPtr->state_flags & BAD_GUY)) { COUNT cur_facing, delta_facing; cur_facing = ANGLE_TO_FACING ( GetVelocityTravelAngle (&ElementPtr->velocity)); delta_facing = NORMALIZE_FACING (cur_facing - ANGLE_TO_FACING (ARCTAN ( puniverse->x - EncounterPtr->SD.star_pt.x, puniverse->y - EncounterPtr->SD.star_pt.y))); if (delta_facing || (delta_x == 0 && delta_y == 0)) { SIZE s, RaceHyperSpeed[] = { RACE_HYPER_SPEED }; #define ENCOUNTER_TRACK_WAIT 3 s = RaceHyperSpeed[EncounterPtr->SD.Type]; if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) --cur_facing; else ++cur_facing; if (NORMALIZE_FACING (delta_facing + ANGLE_TO_FACING (OCTANT)) > ANGLE_TO_FACING (QUADRANT)) { if (delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) --cur_facing; else ++cur_facing; s >>= 1; } cur_facing = FACING_TO_ANGLE (cur_facing); SetVelocityComponents ( &ElementPtr->velocity, COSINE (cur_facing, s), SINE (cur_facing, s) ); GetNextVelocityComponents (&ElementPtr->velocity, &delta_x, &delta_y, 1); ElementPtr->thrust_wait = ENCOUNTER_TRACK_WAIT; } } EncounterPtr->log_x += delta_x; EncounterPtr->log_y -= delta_y; EncounterPtr->SD.star_pt.x = LOGX_TO_UNIVERSE (EncounterPtr->log_x); EncounterPtr->SD.star_pt.y = LOGY_TO_UNIVERSE (EncounterPtr->log_y); encounter_radius = EncounterPtr->radius + (GRID_OFFSET >> 1); if ((delta_x = EncounterPtr->SD.star_pt.x - EncounterPtr->origin.x) < 0) delta_x = -delta_x; if ((delta_y = EncounterPtr->SD.star_pt.y - EncounterPtr->origin.y) < 0) delta_y = -delta_y; if ((COUNT)delta_x >= encounter_radius || (COUNT)delta_y >= encounter_radius || (DWORD)delta_x * delta_x + (DWORD)delta_y * delta_y >= (DWORD)encounter_radius * encounter_radius) { ElementPtr->state_flags |= NONSOLID; ElementPtr->life_span = 0; if (EncounterPtr->transition_state == 0) { ElementPtr->death_func = encounter_transition; EncounterPtr->transition_state = -1; ElementPtr->hit_points = 1; } else { ElementPtr->death_func = NULL_PTR; UnlockElement (EncounterPtr->hElement); goto DeleteEncounter; } } } ex = EncounterPtr->SD.star_pt.x; ey = EncounterPtr->SD.star_pt.y; if (ex - puniverse->x >= -UNIT_SCREEN_WIDTH && ex - puniverse->x <= UNIT_SCREEN_WIDTH && ey - puniverse->y >= -UNIT_SCREEN_HEIGHT && ey - puniverse->y <= UNIT_SCREEN_HEIGHT) { ElementPtr->next.location.x = (SIZE)( EncounterPtr->log_x - GLOBAL_SIS (log_x) ) + (LOG_SPACE_WIDTH >> 1); ElementPtr->next.location.y = (SIZE)( EncounterPtr->log_y - GLOBAL_SIS (log_y) ) + (LOG_SPACE_HEIGHT >> 1); if ((ElementPtr->state_flags & NONSOLID) && EncounterPtr->transition_state == 0) { ElementPtr->current.location = ElementPtr->next.location; SetPrimType (&DisplayArray[ElementPtr->PrimIndex], STAMP_PRIM); if (ElementPtr->death_func == 0) { InitIntersectStartPoint (ElementPtr); ElementPtr->state_flags &= ~NONSOLID; } } } else { ElementPtr->state_flags |= NONSOLID; if (ex - puniverse->x < -XOFFS || ex - puniverse->x > XOFFS || ey - puniverse->y < -YOFFS || ey - puniverse->y > YOFFS) { ElementPtr->life_span = 0; ElementPtr->death_func = NULL_PTR; UnlockElement (EncounterPtr->hElement); goto DeleteEncounter; } SetPrimType (&DisplayArray[ElementPtr->PrimIndex], NO_PRIM); } UnlockElement (EncounterPtr->hElement); } s.origin.x = (COORD)((long)ex * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox; s.origin.y = (COORD)((long)(MAX_Y_UNIVERSE - ey) * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy; DrawStamp (&s); UnlockEncounter (hEncounter); } } void SeedUniverse (void) { COORD ox, oy; COORD sx, sy, ex, ey; SWORD portalCounter, arilouSpaceCounter, arilouSpaceSide; POINT universe; FRAME blip_frame; STAMP s; STAR_DESCPTR SDPtr; HELEMENT hHyperSpaceElement; ELEMENTPTR HyperSpaceElementPtr; ClockTick (); universe.x = LOGX_TO_UNIVERSE (GLOBAL_SIS (log_x)); universe.y = LOGY_TO_UNIVERSE (GLOBAL_SIS (log_y)); blip_frame = SetAbsFrameIndex (stars_in_space, 90); SetContext (RadarContext); BatchGraphics (); ox = (COORD)((long)universe.x * RADAR_WIDTH / RADAR_SCAN_WIDTH) - (RADAR_WIDTH >> 1); oy = (COORD)((long)(MAX_Y_UNIVERSE - universe.y) * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - (RADAR_HEIGHT >> 1); ex = (COORD)((long)GLOBAL (ShipStamp.origin.x) * RADAR_WIDTH / RADAR_SCAN_WIDTH) - (RADAR_WIDTH >> 1); ey = (COORD)((long)(MAX_Y_UNIVERSE - GLOBAL (ShipStamp.origin.y)) * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - (RADAR_HEIGHT >> 1); arilouSpaceCounter = GET_GAME_STATE (ARILOU_SPACE_COUNTER); arilouSpaceSide = GET_GAME_STATE (ARILOU_SPACE_SIDE); // if (ox != ex || oy != ey) { DrawHyperGrid (universe.x, universe.y, ox, oy); { SDPtr = 0; while ((SDPtr = FindStar (SDPtr, &universe, XOFFS, YOFFS))) { BYTE star_type; ex = SDPtr->star_pt.x; ey = SDPtr->star_pt.y; star_type = STAR_TYPE (SDPtr->Type); if (arilouSpaceSide >= 2 && ex == ARILOU_HOME_X && ey == ARILOU_HOME_Y) star_type = SUPER_GIANT_STAR; s.origin.x = (COORD)((long)ex * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox; s.origin.y = (COORD)((long)(MAX_Y_UNIVERSE - ey) * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy; s.frame = SetRelFrameIndex (blip_frame, star_type + 2); DrawStamp (&s); } } } portalCounter = GET_GAME_STATE (PORTAL_COUNTER); if (portalCounter || arilouSpaceCounter) { COUNT i; STAR_DESC SD[2]; // This array is filled with the STAR_DESC's of // QuasiSpace portals that need to be taken into account. // i is set to the number of active portals (max 2). i = 0; if (portalCounter) { // A player-created QuasiSpace portal is opening. static POINT portal_pt; SD[i].Index = ((portalCounter - 1) >> 1) + 18; if (portalCounter == 1) portal_pt = universe; SD[i].star_pt = portal_pt; ++i; if (++portalCounter == (10 + 1)) portalCounter = (9 + 1); SET_GAME_STATE (PORTAL_COUNTER, portalCounter); } if (arilouSpaceCounter) { // The periodically appearing QuasiSpace portal is open. SD[i].Index = arilouSpaceCounter >> 1; if (arilouSpaceSide <= 1) { // The player is in HyperSpace SD[i].Index += 18; SD[i].star_pt.x = ARILOU_SPACE_X; SD[i].star_pt.y = ARILOU_SPACE_Y; } else { // The player is in QuasiSpace SD[i].star_pt.x = QUASI_SPACE_X; SD[i].star_pt.y = QUASI_SPACE_Y; } ++i; } // Process the i portals from SD. do { --i; sx = SD[i].star_pt.x - universe.x + XOFFS; sy = SD[i].star_pt.y - universe.y + YOFFS; if (sx >= 0 && sy >= 0 && sx < (XOFFS << 1) && sy < (YOFFS << 1)) { ex = SD[i].star_pt.x; ey = SD[i].star_pt.y; s.origin.x = (COORD)((long)ex * RADAR_WIDTH / RADAR_SCAN_WIDTH) - ox; s.origin.y = (COORD)((long)(MAX_Y_UNIVERSE - ey) * RADAR_HEIGHT / RADAR_SCAN_HEIGHT) - oy; s.frame = SetAbsFrameIndex (stars_in_space, 95); DrawStamp (&s); if ((ex -= universe.x) < 0) ex = -ex; if ((ey -= universe.y) < 0) ey = -ey; if (ex <= (XOFFS / NUM_RADAR_SCREENS) && ey <= (YOFFS / NUM_RADAR_SCREENS) && (hHyperSpaceElement = AllocHyperElement ((STAR_DESCPTR)&SD[i])) != 0) { LockElement (hHyperSpaceElement, &HyperSpaceElementPtr); HyperSpaceElementPtr->current.image.frame = SetAbsFrameIndex ( hyperstars[1 + (GET_GAME_STATE (ARILOU_SPACE_SIDE) >> 1)], SD[i].Index ); HyperSpaceElementPtr->preprocess_func = HyperSpaceElementPtr->postprocess_func = NULL_PTR; HyperSpaceElementPtr->collision_func = arilou_space_collision; SetUpElement (HyperSpaceElementPtr); if (arilouSpaceSide == 1 || arilouSpaceSide == 2) HyperSpaceElementPtr->death_func = arilou_space_death; else { HyperSpaceElementPtr->death_func = NULL_PTR; HyperSpaceElementPtr->IntersectControl.IntersectStamp.frame = DecFrameIndex (stars_in_space); } UnlockElement (hHyperSpaceElement); InsertElement (hHyperSpaceElement, GetHeadElement ()); } } } while (i); } { SDPtr = 0; while ((SDPtr = FindStar (SDPtr, &universe, XOFFS, YOFFS))) { ex = SDPtr->star_pt.x; ey = SDPtr->star_pt.y; if ((ex -= universe.x) < 0) ex = -ex; if ((ey -= universe.y) < 0) ey = -ey; if (ex <= (XOFFS / NUM_RADAR_SCREENS) && ey <= (YOFFS / NUM_RADAR_SCREENS) && (hHyperSpaceElement = AllocHyperElement (SDPtr)) != 0) { BYTE star_type; star_type = SDPtr->Type; LockElement (hHyperSpaceElement, &HyperSpaceElementPtr); HyperSpaceElementPtr->current.image.frame = SetAbsFrameIndex ( hyperstars[1 + (GET_GAME_STATE (ARILOU_SPACE_SIDE) >> 1)], STAR_TYPE (star_type) * NUM_STAR_COLORS + STAR_COLOR (star_type) ); HyperSpaceElementPtr->preprocess_func = HyperSpaceElementPtr->postprocess_func = NULL_PTR; HyperSpaceElementPtr->collision_func = hyper_collision; SetUpElement (HyperSpaceElementPtr); if (SDPtr == CurStarDescPtr && GET_GAME_STATE (PORTAL_COUNTER) == 0) HyperSpaceElementPtr->death_func = hyper_death; else { HyperSpaceElementPtr->death_func = NULL_PTR; HyperSpaceElementPtr->IntersectControl.IntersectStamp.frame = DecFrameIndex (stars_in_space); } UnlockElement (hHyperSpaceElement); InsertElement (hHyperSpaceElement, GetHeadElement ()); } } ProcessEncounters (&universe, ox, oy); } s.origin.x = RADAR_WIDTH >> 1; s.origin.y = RADAR_HEIGHT >> 1; s.frame = blip_frame; DrawStamp (&s); { // draws borders to mini-map RECT r; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0E, 0x0E, 0x0E), 0x00)); r.corner.x = 0; r.corner.y = 0; r.extent.width = RADAR_WIDTH - 1; r.extent.height = 1; DrawFilledRectangle (&r); r.extent.width = 1; r.extent.height = RADAR_HEIGHT - 1; DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x06, 0x06, 0x06), 0x00)); r.corner.x = RADAR_WIDTH - 1; r.corner.y = 1; r.extent.height = RADAR_HEIGHT - 1; DrawFilledRectangle (&r); r.corner.x = 1; r.corner.y = RADAR_HEIGHT - 1; r.extent.width = RADAR_WIDTH - 2; r.extent.height = 1; DrawFilledRectangle (&r); SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x00)); r.corner.x = 0; DrawPoint (&r.corner); r.corner.x = RADAR_WIDTH - 1; r.corner.y = 0; DrawPoint (&r.corner); } UnbatchGraphics (); SetContext (StatusContext); if (!(LOWORD (TFB_Random ()) & 7)) AddAmbientElement (); if (universe.x != GLOBAL (ShipStamp.origin.x) || universe.y != GLOBAL (ShipStamp.origin.y)) { GLOBAL (ShipStamp.origin) = universe; DrawHyperCoords (universe); } } void DoMenuOptions (void) { COLOR OldColor; CONTEXT OldContext; MENU_STATE MenuState; UnbatchGraphics (); OldContext = SetContext (SpaceContext); OldColor = SetContextBackGroundColor (BLACK_COLOR); UnlockMutex (GraphicsLock); SuspendGameClock (); memset ((PMENU_STATE)&MenuState, 0, sizeof (MenuState)); MenuState.InputFunc = DoFlagshipCommands; MenuState.Initialized = 1; MenuState.CurState = STARMAP + 1; DrawMenuStateStrings (PM_STARMAP, STARMAP); LockMutex (GraphicsLock); SetFlashRect (SFR_MENU_3DO, (FRAME)0); UnlockMutex (GraphicsLock); SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); DoInput ((PVOID)&MenuState, TRUE); LockMutex (GraphicsLock); SetFlashRect (NULL_PTR, (FRAME)0); SetContext (SpaceContext); if (!(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD))) { ClearSISRect (CLEAR_SIS_RADAR); UnlockMutex (GraphicsLock); WaitForNoInput (ONE_SECOND / 2); ResumeGameClock (); LockMutex (GraphicsLock); } SetContextBackGroundColor (OldColor); SetContext (OldContext); if (!(GLOBAL (CurrentActivity) & IN_BATTLE)) cleanup_hyperspace (); BatchGraphics (); } uqm-0.6.2/sc2/src/sc2code/weapon.c0000600000175000017500000003044110543202101015232 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "weapon.h" #include "build.h" #include "colors.h" #include "globdata.h" #include "init.h" #include "races.h" #include "setup.h" #include "sounds.h" #include "units.h" #include "libs/mathlib.h" #include HELEMENT initialize_laser (PLASER_BLOCK pLaserBlock) { HELEMENT hLaserElement; hLaserElement = AllocElement (); if (hLaserElement) { #define LASER_LIFE 1 ELEMENTPTR LaserElementPtr; LockElement (hLaserElement, &LaserElementPtr); LaserElementPtr->hit_points = 1; LaserElementPtr->mass_points = 1; LaserElementPtr->state_flags = APPEARING | FINITE_LIFE | pLaserBlock->sender; LaserElementPtr->life_span = LASER_LIFE; LaserElementPtr->collision_func = (void (*) (struct element *ElementPtr0, PPOINT pPt0, struct element *ElementPtr1, PPOINT pPt1)) weapon_collision; LaserElementPtr->blast_offset = 1; LaserElementPtr->current.location.x = pLaserBlock->cx + COSINE (FACING_TO_ANGLE (pLaserBlock->face), DISPLAY_TO_WORLD (pLaserBlock->pixoffs)); LaserElementPtr->current.location.y = pLaserBlock->cy + SINE (FACING_TO_ANGLE (pLaserBlock->face), DISPLAY_TO_WORLD (pLaserBlock->pixoffs)); SetPrimType (&DisplayArray[LaserElementPtr->PrimIndex], LINE_PRIM); SetPrimColor (&DisplayArray[LaserElementPtr->PrimIndex], pLaserBlock->color); LaserElementPtr->current.image.frame = DecFrameIndex (stars_in_space); LaserElementPtr->current.image.farray = &stars_in_space; SetVelocityComponents (&LaserElementPtr->velocity, WORLD_TO_VELOCITY ((pLaserBlock->cx + pLaserBlock->ex) - LaserElementPtr->current.location.x), WORLD_TO_VELOCITY ((pLaserBlock->cy + pLaserBlock->ey) - LaserElementPtr->current.location.y)); UnlockElement (hLaserElement); } return (hLaserElement); } HELEMENT initialize_missile (PMISSILE_BLOCK pMissileBlock) { HELEMENT hMissileElement; hMissileElement = AllocElement (); if (hMissileElement) { SIZE delta_x, delta_y; COUNT angle; ELEMENTPTR MissileElementPtr; LockElement (hMissileElement, &MissileElementPtr); MissileElementPtr->hit_points = (BYTE)pMissileBlock->hit_points; MissileElementPtr->mass_points = (BYTE)pMissileBlock->damage; MissileElementPtr->state_flags = APPEARING | FINITE_LIFE | pMissileBlock->sender; MissileElementPtr->life_span = pMissileBlock->life; SetPrimType (&DisplayArray[MissileElementPtr->PrimIndex], STAMP_PRIM); MissileElementPtr->current.image.farray = pMissileBlock->farray; MissileElementPtr->current.image.frame = SetAbsFrameIndex (pMissileBlock->farray[0], pMissileBlock->index); MissileElementPtr->preprocess_func = pMissileBlock->preprocess_func; MissileElementPtr->collision_func = (void (*) (struct element *ElementPtr0, PPOINT pPt0, struct element *ElementPtr1, PPOINT pPt1)) weapon_collision; MissileElementPtr->blast_offset = (BYTE)pMissileBlock->blast_offs; angle = FACING_TO_ANGLE (pMissileBlock->face); MissileElementPtr->current.location.x = pMissileBlock->cx + COSINE (angle, DISPLAY_TO_WORLD (pMissileBlock->pixoffs)); MissileElementPtr->current.location.y = pMissileBlock->cy + SINE (angle, DISPLAY_TO_WORLD (pMissileBlock->pixoffs)); delta_x = COSINE (angle, WORLD_TO_VELOCITY (pMissileBlock->speed)); delta_y = SINE (angle, WORLD_TO_VELOCITY (pMissileBlock->speed)); SetVelocityComponents (&MissileElementPtr->velocity, delta_x, delta_y); MissileElementPtr->current.location.x -= VELOCITY_TO_WORLD (delta_x); MissileElementPtr->current.location.y -= VELOCITY_TO_WORLD (delta_y); UnlockElement (hMissileElement); } return (hMissileElement); } HELEMENT weapon_collision (PELEMENT WeaponElementPtr, PPOINT pWPt, PELEMENT HitElementPtr, PPOINT pHPt) { SIZE damage; HELEMENT hBlastElement; if (WeaponElementPtr->state_flags & COLLISION) /* if already did effect */ return ((HELEMENT)0); damage = (SIZE)WeaponElementPtr->mass_points; if (damage && ((HitElementPtr->state_flags & FINITE_LIFE) || HitElementPtr->life_span == NORMAL_LIFE)) #ifdef NEVER && /* lasers from the same ship can't hit each other */ (GetPrimType (&DisplayArray[HitElementPtr->PrimIndex]) != LINE_PRIM || GetPrimType (&DisplayArray[WeaponElementPtr->PrimIndex]) != LINE_PRIM || (HitElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) != (WeaponElementPtr->state_flags & (GOOD_GUY | BAD_GUY)))) #endif /* NEVER */ { do_damage ((ELEMENTPTR)HitElementPtr, damage); if (HitElementPtr->hit_points) WeaponElementPtr->state_flags |= COLLISION; } if (!(HitElementPtr->state_flags & FINITE_LIFE) || (!(/* WeaponElementPtr->state_flags & */ HitElementPtr->state_flags & COLLISION) && WeaponElementPtr->hit_points <= HitElementPtr->mass_points)) { if (damage) { damage = TARGET_DAMAGED_FOR_1_PT + (damage >> 1); if (damage > TARGET_DAMAGED_FOR_6_PLUS_PT) damage = TARGET_DAMAGED_FOR_6_PLUS_PT; ProcessSound (SetAbsSoundIndex (GameSounds, damage), HitElementPtr); } if (GetPrimType (&DisplayArray[WeaponElementPtr->PrimIndex]) != LINE_PRIM) WeaponElementPtr->state_flags |= DISAPPEARING; WeaponElementPtr->hit_points = 0; WeaponElementPtr->life_span = 0; WeaponElementPtr->state_flags |= COLLISION | NONSOLID; hBlastElement = AllocElement (); if (hBlastElement) { COUNT blast_index; SIZE blast_offs; COUNT angle, num_blast_frames; ELEMENTPTR BlastElementPtr; extern FRAME blast[]; PutElement (hBlastElement); LockElement (hBlastElement, &BlastElementPtr); BlastElementPtr->state_flags = APPEARING | FINITE_LIFE | NONSOLID | (WeaponElementPtr->state_flags & (GOOD_GUY | BAD_GUY)); SetPrimType (&DisplayArray[BlastElementPtr->PrimIndex], STAMP_PRIM); BlastElementPtr->current.location.x = DISPLAY_TO_WORLD (pWPt->x); BlastElementPtr->current.location.y = DISPLAY_TO_WORLD (pWPt->y); angle = GetVelocityTravelAngle (&WeaponElementPtr->velocity); if ((blast_offs = WeaponElementPtr->blast_offset) > 0) { BlastElementPtr->current.location.x += COSINE (angle, DISPLAY_TO_WORLD (blast_offs)); BlastElementPtr->current.location.y += SINE (angle, DISPLAY_TO_WORLD (blast_offs)); } blast_index = NORMALIZE_FACING (ANGLE_TO_FACING (angle + HALF_CIRCLE)); blast_index = ((blast_index >> 2) << 1) + (blast_index & 0x3 ? 1 : 0); num_blast_frames = GetFrameCount (WeaponElementPtr->next.image.frame); if (num_blast_frames <= ANGLE_TO_FACING (FULL_CIRCLE)) { BlastElementPtr->life_span = 2; BlastElementPtr->current.image.farray = blast; BlastElementPtr->current.image.frame = SetAbsFrameIndex (blast[0], blast_index); } else { BlastElementPtr->life_span = num_blast_frames - ANGLE_TO_FACING (FULL_CIRCLE); BlastElementPtr->turn_wait = BlastElementPtr->next_turn = 0; BlastElementPtr->preprocess_func = animation_preprocess; BlastElementPtr->current.image.farray = WeaponElementPtr->next.image.farray; BlastElementPtr->current.image.frame = SetAbsFrameIndex ( BlastElementPtr->current.image.farray[0], ANGLE_TO_FACING (FULL_CIRCLE)); } UnlockElement (hBlastElement); return (hBlastElement); } } (void) pHPt; /* Satisfying compiler (unused parameter) */ return ((HELEMENT)0); } FRAME ModifySilhouette (ELEMENTPTR ElementPtr, PSTAMP modify_stamp, BYTE modify_flags) { FRAME f; RECT r, or; INTERSECT_CONTROL ShipIntersect, ObjectIntersect; STARSHIPPTR StarShipPtr; CONTEXT OldContext; f = 0; ObjectIntersect.IntersectStamp = *modify_stamp; GetFrameRect (ObjectIntersect.IntersectStamp.frame, &or); GetElementStarShip (ElementPtr, &StarShipPtr); if (modify_flags & MODIFY_IMAGE) { ShipIntersect.IntersectStamp.frame = StarShipPtr->silhouette; if (ShipIntersect.IntersectStamp.frame == 0) return (0); GetFrameRect (ShipIntersect.IntersectStamp.frame, &r); ShipIntersect.IntersectStamp.origin.x = 0; ShipIntersect.IntersectStamp.origin.y = 0; ShipIntersect.EndPoint = ShipIntersect.IntersectStamp.origin; do { ObjectIntersect.IntersectStamp.origin.x = ((COUNT)TFB_Random () % (r.extent.width - or.extent.width)) + ((or.extent.width - r.extent.width) >> 1); ObjectIntersect.IntersectStamp.origin.y = ((COUNT)TFB_Random () % (r.extent.height - or.extent.height)) + ((or.extent.height - r.extent.height) >> 1); ObjectIntersect.EndPoint = ObjectIntersect.IntersectStamp.origin; } while (!DrawablesIntersect (&ObjectIntersect, &ShipIntersect, MAX_TIME_VALUE)); ObjectIntersect.IntersectStamp.origin.x += STATUS_WIDTH >> 1; ObjectIntersect.IntersectStamp.origin.y += 31; } ObjectIntersect.IntersectStamp.origin.y += (WHICH_SIDE (ElementPtr->state_flags) ? BAD_GUY_YOFFS : GOOD_GUY_YOFFS); if (modify_flags & MODIFY_SWAP) { or.corner.x += ObjectIntersect.IntersectStamp.origin.x; or.corner.y += ObjectIntersect.IntersectStamp.origin.y; InitShipStatus (StarShipPtr, &or); } else { OldContext = SetContext (StatusContext); DrawStamp (&ObjectIntersect.IntersectStamp); SetContext (OldContext); } return (f); } // Find the closest possible target ship, to be set in Tracker->hTarget. // *pfacing will be turned one angle unit into the direction towards the // target. // The return value will be the actual number of angle units to turn, or // -1 if no target was found. // Cloaked ships won't be detected, except when the APPEARING flag is // set for the Tracker. SIZE TrackShip (ELEMENTPTR Tracker, PCOUNT pfacing) { SIZE best_delta_facing, best_delta; HELEMENT hShip, hNextShip; ELEMENTPTR Trackee; best_delta = 0; best_delta_facing = -1; hShip = Tracker->hTarget; if (hShip) { LockElement (hShip, &Trackee); Tracker->hTarget = hNextShip = 0; goto CheckTracking; } for (hShip = GetHeadElement (); hShip != 0; hShip = hNextShip) { LockElement (hShip, &Trackee); hNextShip = GetSuccElement (Trackee); if ((Trackee->state_flags & PLAYER_SHIP) && (Trackee->state_flags & (GOOD_GUY | BAD_GUY)) != (Tracker->state_flags & (GOOD_GUY | BAD_GUY)) && (!OBJECT_CLOAKED (Trackee) || ((Tracker->state_flags & PLAYER_SHIP) && (Tracker->state_flags & APPEARING)) )) { STARSHIPPTR StarShipPtr; CheckTracking: GetElementStarShip (Trackee, &StarShipPtr); if (Trackee->life_span && StarShipPtr->RaceDescPtr->ship_info.crew_level) { SIZE delta_x, delta_y, delta_facing; if (Tracker->state_flags & PRE_PROCESS) { delta_x = Trackee->next.location.x - Tracker->next.location.x; delta_y = Trackee->next.location.y - Tracker->next.location.y; } else { delta_x = Trackee->current.location.x - Tracker->current.location.x; delta_y = Trackee->current.location.y - Tracker->current.location.y; } delta_x = WRAP_DELTA_X (delta_x); delta_y = WRAP_DELTA_Y (delta_y); delta_facing = NORMALIZE_FACING ( ANGLE_TO_FACING (ARCTAN (delta_x, delta_y)) - *pfacing ); if (delta_x < 0) delta_x = -delta_x; if (delta_y < 0) delta_y = -delta_y; delta_x += delta_y; // 'delta_x + delta_y' is used as an approximation // of the actual distance 'sqrt(sqr(delta_x) + // sqr(delta_y))'. if (best_delta == 0 || delta_x < best_delta) { best_delta = delta_x; best_delta_facing = delta_facing; Tracker->hTarget = hShip; } } } UnlockElement (hShip); } if (best_delta_facing > 0) { COUNT facing; facing = *pfacing; if (best_delta_facing == ANGLE_TO_FACING (HALF_CIRCLE)) facing += (((BYTE)TFB_Random () & 1) << 1) - 1; else if (best_delta_facing < ANGLE_TO_FACING (HALF_CIRCLE)) ++facing; else --facing; *pfacing = NORMALIZE_FACING (facing); } return (best_delta_facing); } uqm-0.6.2/sc2/src/sc2code/commanim.c0000600000175000017500000003243210543202101015543 0ustar joeyjoey//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define COMM_INTERNAL #include "commanim.h" #include "comm.h" #include "element.h" #include "setup.h" #include "libs/compiler.h" #include "libs/graphics/gfx_common.h" #include "libs/mathlib.h" // Maximum ambient animation frame rate (actual execution rate) // A gfx frame is not always produced during an execution frame, // and several animations are combined into one gfx frame. // The rate was originally 120fps which allowed for more animation // precision which is ultimately wasted on the human eye anyway. // The highest known stable animation rate is 40fps, so that's what we use. #define AMBIENT_ANIM_RATE 40 // Oscilloscope frame rate // Should be <= AMBIENT_ANIM_RATE // XXX: was 32 picked experimentally? #define OSCILLOSCOPE_RATE 32 static int ambient_anim_task (void *data); volatile BOOLEAN PauseAnimTask = FALSE; static void SetUpSequence (PSEQUENCE pSeq) { COUNT i; ANIMATION_DESCPTR ADPtr; i = CommData.NumAnimations; pSeq = &pSeq[i]; ADPtr = &CommData.AlienAmbientArray[i]; while (i--) { --ADPtr; --pSeq; if (ADPtr->AnimFlags & COLORXFORM_ANIM) pSeq->AnimType = COLOR_ANIM; else pSeq->AnimType = PICTURE_ANIM; pSeq->Direction = UP_DIR; pSeq->FramesLeft = ADPtr->NumFrames; if (pSeq->AnimType == COLOR_ANIM) pSeq->AnimObj.CurCMap = SetAbsColorMapIndex ( CommData.AlienColorMap, ADPtr->StartIndex); else pSeq->AnimObj.CurFrame = SetAbsFrameIndex ( CommData.AlienFrame, ADPtr->StartIndex); if (ADPtr->AnimFlags & RANDOM_ANIM) { if (pSeq->AnimType == COLOR_ANIM) pSeq->AnimObj.CurCMap = SetRelColorMapIndex (pSeq->AnimObj.CurCMap, (COUNT)((COUNT)TFB_Random () % pSeq->FramesLeft)); else pSeq->AnimObj.CurFrame = SetRelFrameIndex (pSeq->AnimObj.CurFrame, (COUNT)((COUNT)TFB_Random () % pSeq->FramesLeft)); } else if (ADPtr->AnimFlags & YOYO_ANIM) { --pSeq->FramesLeft; if (pSeq->AnimType == COLOR_ANIM) pSeq->AnimObj.CurCMap = SetRelColorMapIndex (pSeq->AnimObj.CurCMap, 1); else pSeq->AnimObj.CurFrame = IncFrameIndex (pSeq->AnimObj.CurFrame); } pSeq->Alarm = ADPtr->BaseRestartRate + ((COUNT)TFB_Random () % (ADPtr->RandomRestartRate + 1)) + 1; } } static int ambient_anim_task (void *data) { SIZE TalkAlarm; FRAME TalkFrame; FRAME ResetTalkFrame = NULL; FRAME TransitionFrame = NULL; FRAME AnimFrame[MAX_ANIMATIONS + 1]; COUNT i; DWORD LastTime; FRAME CommFrame; SEQUENCE Sequencer[MAX_ANIMATIONS]; ANIMATION_DESC TalkBuffer = CommData.AlienTalkDesc; PSEQUENCE pSeq; ANIMATION_DESCPTR ADPtr; DWORD ActiveMask; DWORD LastOscillTime; Task task = (Task) data; BOOLEAN TransitionDone = FALSE; BOOLEAN TalkFrameChanged = FALSE; BOOLEAN FrameChanged[MAX_ANIMATIONS]; BOOLEAN ColorChange = FALSE; while ((CommFrame = CommData.AlienFrame) == 0 && !Task_ReadState (task, TASK_EXIT)) TaskSwitch (); LockMutex (GraphicsLock); memset ((PSTR)&DisplayArray[0], 0, sizeof (DisplayArray)); SetUpSequence (Sequencer); UnlockMutex (GraphicsLock); ActiveMask = 0; TalkAlarm = 0; TalkFrame = 0; LastTime = GetTimeCounter (); LastOscillTime = LastTime; memset (FrameChanged, 0, sizeof (FrameChanged)); memset (AnimFrame, 0, sizeof (AnimFrame)); for (i = 0; i <= CommData.NumAnimations; i++) if (CommData.AlienAmbientArray[i].AnimFlags & YOYO_ANIM) AnimFrame[i] = SetAbsFrameIndex (CommFrame, CommData.AlienAmbientArray[i].StartIndex); else AnimFrame[i] = SetAbsFrameIndex (CommFrame, (COUNT)(CommData.AlienAmbientArray[i].StartIndex + CommData.AlienAmbientArray[i].NumFrames - 1)); while (!Task_ReadState (task, TASK_EXIT)) { BOOLEAN Change, CanTalk; DWORD CurTime, ElapsedTicks; SleepThreadUntil (LastTime + ONE_SECOND / AMBIENT_ANIM_RATE); LockMutex (GraphicsLock); BatchGraphics (); CurTime = GetTimeCounter (); ElapsedTicks = CurTime - LastTime; LastTime = CurTime; Change = FALSE; i = CommData.NumAnimations; if (CommData.AlienFrame) CanTalk = TRUE; else { i = 0; CanTalk = FALSE; } pSeq = &Sequencer[i]; ADPtr = &CommData.AlienAmbientArray[i]; while (i-- && !Task_ReadState (task, TASK_EXIT)) { --ADPtr; --pSeq; if (ADPtr->AnimFlags & ANIM_DISABLED) continue; if (pSeq->Direction == NO_DIR) { if (!(ADPtr->AnimFlags & CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING)) pSeq->Direction = UP_DIR; } else if ((DWORD)pSeq->Alarm > ElapsedTicks) pSeq->Alarm -= (COUNT)ElapsedTicks; else { if (!(ActiveMask & ADPtr->BlockMask) && (--pSeq->FramesLeft || ((ADPtr->AnimFlags & YOYO_ANIM) && pSeq->Direction == UP_DIR))) { ActiveMask |= 1L << i; pSeq->Alarm = ADPtr->BaseFrameRate + ((COUNT)TFB_Random () % (ADPtr->RandomFrameRate + 1)) + 1; } else { ActiveMask &= ~(1L << i); pSeq->Alarm = ADPtr->BaseRestartRate + ((COUNT)TFB_Random () % (ADPtr->RandomRestartRate + 1)) + 1; if (ActiveMask & ADPtr->BlockMask) continue; } if (pSeq->AnimType == COLOR_ANIM) { XFormColorMap (GetColorMapAddress (pSeq->AnimObj.CurCMap), (COUNT) (pSeq->Alarm - 1)); } else { Change = TRUE; AnimFrame[i] = pSeq->AnimObj.CurFrame; FrameChanged[i] = 1; } if (pSeq->FramesLeft == 0) { pSeq->FramesLeft = (BYTE)(ADPtr->NumFrames - 1); if (pSeq->Direction == DOWN_DIR) pSeq->Direction = UP_DIR; else if (ADPtr->AnimFlags & YOYO_ANIM) pSeq->Direction = DOWN_DIR; else { ++pSeq->FramesLeft; if (pSeq->AnimType == COLOR_ANIM) pSeq->AnimObj.CurCMap = SetRelColorMapIndex ( pSeq->AnimObj.CurCMap, (SWORD) (-pSeq->FramesLeft)); else { pSeq->AnimObj.CurFrame = SetRelFrameIndex ( pSeq->AnimObj.CurFrame, (SWORD) (-pSeq->FramesLeft)); } } } if (ADPtr->AnimFlags & RANDOM_ANIM) { COUNT nextIndex = ADPtr->StartIndex + (TFB_Random () % ADPtr->NumFrames); if (pSeq->AnimType == COLOR_ANIM) pSeq->AnimObj.CurCMap = SetAbsColorMapIndex ( pSeq->AnimObj.CurCMap, nextIndex); else pSeq->AnimObj.CurFrame = SetAbsFrameIndex ( pSeq->AnimObj.CurFrame, nextIndex); } else if (pSeq->AnimType == COLOR_ANIM) { if (pSeq->Direction == UP_DIR) pSeq->AnimObj.CurCMap = SetRelColorMapIndex ( pSeq->AnimObj.CurCMap, 1); else pSeq->AnimObj.CurCMap = SetRelColorMapIndex ( pSeq->AnimObj.CurCMap, -1); } else { if (pSeq->Direction == UP_DIR) pSeq->AnimObj.CurFrame = IncFrameIndex (pSeq->AnimObj.CurFrame); else pSeq->AnimObj.CurFrame = DecFrameIndex (pSeq->AnimObj.CurFrame); } } if (pSeq->AnimType == PICTURE_ANIM && (ADPtr->AnimFlags & CommData.AlienTalkDesc.AnimFlags & WAIT_TALKING) && pSeq->Direction != NO_DIR) { COUNT index; CanTalk = FALSE; if (!(pSeq->Direction != UP_DIR || (index = GetFrameIndex (pSeq->AnimObj.CurFrame)) > ADPtr->StartIndex + 1 || (index == ADPtr->StartIndex + 1 && (ADPtr->AnimFlags & CIRCULAR_ANIM)))) pSeq->Direction = NO_DIR; } } ADPtr = &CommData.AlienTalkDesc; if (CanTalk && ADPtr->NumFrames && (ADPtr->AnimFlags & WAIT_TALKING) && !(CommData.AlienTransitionDesc.AnimFlags & PAUSE_TALKING)) { BOOLEAN done = FALSE; for (i = 0; i < CommData.NumAnimations; i++) if (ActiveMask & (1L << i) && CommData.AlienAmbientArray[i].AnimFlags & WAIT_TALKING) done = TRUE; if (!done) { if (ADPtr->StartIndex != TalkBuffer.StartIndex) { Change = TRUE; ResetTalkFrame = SetAbsFrameIndex (CommFrame, TalkBuffer.StartIndex); TalkBuffer = CommData.AlienTalkDesc; } if ((long)TalkAlarm > (long)ElapsedTicks) TalkAlarm -= (SIZE)ElapsedTicks; else { BYTE AFlags; SIZE FrameRate; if (TalkAlarm > 0) TalkAlarm = 0; else TalkAlarm = -1; AFlags = ADPtr->AnimFlags; if (!(AFlags & (TALK_INTRO | TALK_DONE))) { FrameRate = ADPtr->BaseFrameRate + ((COUNT)TFB_Random () % (ADPtr->RandomFrameRate + 1)); if (TalkAlarm < 0 || GetFrameIndex (TalkFrame) == ADPtr->StartIndex) { TalkFrame = SetAbsFrameIndex (CommFrame, (COUNT) (ADPtr->StartIndex + 1 + ((COUNT)TFB_Random () % (ADPtr->NumFrames - 1)))); FrameRate += ADPtr->BaseRestartRate + ((COUNT)TFB_Random () % (ADPtr->RandomRestartRate + 1)); } else { TalkFrame = SetAbsFrameIndex (CommFrame, ADPtr->StartIndex); if (ADPtr->AnimFlags & PAUSE_TALKING) { if (!(CommData.AlienTransitionDesc.AnimFlags & TALK_DONE)) { CommData.AlienTransitionDesc.AnimFlags |= PAUSE_TALKING; ADPtr->AnimFlags &= ~PAUSE_TALKING; } else if (CommData.AlienTransitionDesc.NumFrames) ADPtr->AnimFlags |= TALK_DONE; else ADPtr->AnimFlags &= ~(WAIT_TALKING | PAUSE_TALKING); FrameRate = 0; } } } else { ADPtr = &CommData.AlienTransitionDesc; if (AFlags & TALK_INTRO) { FrameRate = ADPtr->BaseFrameRate + ((COUNT)TFB_Random () % (ADPtr->RandomFrameRate + 1)); if (TalkAlarm < 0 || TransitionDone) { TalkFrame = SetAbsFrameIndex (CommFrame, ADPtr->StartIndex); TransitionDone = FALSE; } else TalkFrame = IncFrameIndex (TalkFrame); if ((BYTE)(GetFrameIndex (TalkFrame) - ADPtr->StartIndex + 1) == ADPtr->NumFrames) { CommData.AlienTalkDesc.AnimFlags &= ~TALK_INTRO; TransitionDone = TRUE; } TransitionFrame = TalkFrame; } else /* if (AFlags & TALK_DONE) */ { FrameRate = ADPtr->BaseFrameRate + ((COUNT)TFB_Random () % (ADPtr->RandomFrameRate + 1)); if (TalkAlarm < 0) TalkFrame = SetAbsFrameIndex (CommFrame, (COUNT) (ADPtr->StartIndex + ADPtr->NumFrames - 1)); else TalkFrame = DecFrameIndex (TalkFrame); if (GetFrameIndex (TalkFrame) == ADPtr->StartIndex) { CommData.AlienTalkDesc.AnimFlags &= ~(PAUSE_TALKING | TALK_DONE); if (ADPtr->AnimFlags & TALK_INTRO) CommData.AlienTalkDesc.AnimFlags &= ~WAIT_TALKING; else { ADPtr->AnimFlags |= PAUSE_TALKING; ADPtr->AnimFlags &= ~TALK_DONE; } FrameRate = 0; } TransitionFrame = NULL; } } TalkFrameChanged = TRUE; Change = TRUE; TalkAlarm = FrameRate; } } else if (done && (ADPtr->AnimFlags & PAUSE_TALKING)) { ADPtr->AnimFlags &= ~(WAIT_TALKING | PAUSE_TALKING); } } if (!PauseAnimTask) { CONTEXT OldContext; BOOLEAN CheckSub = FALSE; BOOLEAN ClearSub; SUBTITLE_STATE sub_state; ClearSub = SetClearSubtitle (FALSE, &sub_state); OldContext = SetContext (TaskContext); if (ColorChange || ClearSummary) { FRAME F; F = CommData.AlienFrame; CommData.AlienFrame = CommFrame; DrawAlienFrame (TalkFrame, &Sequencer[CommData.NumAnimations - 1]); CommData.AlienFrame = F; CheckSub = TRUE; ClearSub = ClearSummary; ColorChange = FALSE; ClearSummary = FALSE; } if (Change || ClearSub) { STAMP s; s.origin.x = -SAFE_X; s.origin.y = 0; if (ClearSub) { s.frame = CommFrame; DrawStamp (&s); } i = CommData.NumAnimations; while (i--) { if (ClearSub || FrameChanged[i]) { s.frame = AnimFrame[i]; DrawStamp (&s); FrameChanged[i] = 0; } } if (ClearSub && TransitionFrame) { s.frame = TransitionFrame; DrawStamp (&s); } if (ResetTalkFrame) { s.frame = ResetTalkFrame; DrawStamp (&s); ResetTalkFrame = NULL; } if (TalkFrame && TalkFrameChanged) { s.frame = TalkFrame; DrawStamp (&s); TalkFrameChanged = FALSE; } Change = FALSE; CheckSub = TRUE; } if (CheckSub && sub_state >= SPACE_SUBTITLE) RedrawSubtitles (); SetContext (OldContext); } if (LastOscillTime + (ONE_SECOND / OSCILLOSCOPE_RATE) < CurTime) { LastOscillTime = CurTime; UpdateSpeechGraphics (FALSE); } UnbatchGraphics (); UnlockMutex (GraphicsLock); ColorChange = XFormColorMap_step (); } FinishTask (task); return 0; } Task StartCommAnimTask(void) { return AssignTask (ambient_anim_task, 3072, "ambient animations"); } uqm-0.6.2/sc2/src/sc2code/uqmdebug.c0000600000175000017500000007744210543202101015566 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if defined(DEBUG) || defined(USE_DEBUG_KEY) #include "uqmdebug.h" #include "colors.h" #include "clock.h" #include "encount.h" #include "gamestr.h" #include "gameev.h" #include "globdata.h" #include "planets/lifeform.h" #include "races.h" #include "setup.h" #include "state.h" #include "libs/mathlib.h" #include "libs/misc.h" #include #include static void dumpEventCallback (const EVENTPTR eventPtr, void *arg); static void starRecurse (STAR_DESC *star, void *arg); static void planetRecurse (STAR_DESC *star, SOLARSYS_STATE *system, PLANET_DESC *planet, void *arg); static void moonRecurse (STAR_DESC *star, SOLARSYS_STATE *system, PLANET_DESC *planet, PLANET_DESC *moon, void *arg); static void dumpSystemCallback (const STAR_DESC *star, const SOLARSYS_STATE *system, void *arg); static void dumpPlanetCallback (const PLANET_DESC *planet, void *arg); static void dumpMoonCallback (const PLANET_DESC *moon, void *arg); static void dumpWorld (FILE *out, const PLANET_DESC *world); static void dumpPlanetTypeCallback (int index, const PlanetFrame *planet, void *arg); BOOLEAN instantMove = FALSE; BOOLEAN disableInteractivity = FALSE; void (* volatile debugHook) (void) = NULL; void debugKeyPressed (void) { // State modifying: equipShip (); resetCrewBattle (); resetEnergyBattle (); instantMove = !instantMove; showSpheres (); activateAllShips (); // forwardToNextEvent (TRUE); // Tests // Scale_PerfTest (); // Informational: // dumpEvents (stderr); // dumpPlanetTypes(stderr); // debugHook = dumpUniverseToFile; // This will cause dumpUniverseToFile to be called from the // main loop. Calling it from here would give threading // problems. // Interactive: // uio_debugInteractive(stdin, stdout, stderr); } //////////////////////////////////////////////////////////////////////////// // Fast forwards to the next event. // If skipHEE is set, HYPERSPACE_ENCOUNTER_EVENTs are skipped. void forwardToNextEvent (BOOLEAN skipHEE) { HEVENT hEvent; EVENTPTR EventPtr; COUNT year, month, day; // time of next event BOOLEAN done; if (!GameClockRunning ()) return; SuspendGameClock (); done = !skipHEE; do { hEvent = GetHeadEvent (); if (hEvent == 0) return; LockEvent (hEvent, &EventPtr); if (EventPtr->func_index != HYPERSPACE_ENCOUNTER_EVENT) done = TRUE; year = EventPtr->year_index; month = EventPtr->month_index; day = EventPtr->day_index; UnlockEvent (hEvent); for (;;) { if (GLOBAL (GameClock.year_index) > year || (GLOBAL (GameClock.year_index) == year && (GLOBAL (GameClock.month_index) > month || (GLOBAL (GameClock.month_index) == month && GLOBAL (GameClock.day_index) >= day)))) break; while (ClockTick () > 0) ; ResumeGameClock (); SleepThread (ONE_SECOND / 60); SuspendGameClock (); } } while (!done); ResumeGameClock (); } const char * eventName (BYTE func_index) { switch (func_index) { case ARILOU_ENTRANCE_EVENT: return "ARILOU_ENTRANCE_EVENT"; case ARILOU_EXIT_EVENT: return "ARILOU_EXIT_EVENT"; case HYPERSPACE_ENCOUNTER_EVENT: return "HYPERSPACE_ENCOUNTER_EVENT"; case KOHR_AH_VICTORIOUS_EVENT: return "KOHR_AH_VICTORIOUS_EVENT"; case ADVANCE_PKUNK_MISSION: return "ADVANCE_PKUNK_MISSION"; case ADVANCE_THRADD_MISSION: return "ADVANCE_THRADD_MISSION"; case ZOQFOT_DISTRESS_EVENT: return "ZOQFOT_DISTRESS"; case ZOQFOT_DEATH_EVENT: return "ZOQFOT_DEATH_EVENT"; case SHOFIXTI_RETURN_EVENT: return "SHOFIXTI_RETURN_EVENT"; case ADVANCE_UTWIG_SUPOX_MISSION: return "ADVANCE_UTWIG_SUPOX_MISSION"; case KOHR_AH_GENOCIDE_EVENT: return "KOHR_AH_GENOCIDE_EVENT"; case SPATHI_SHIELD_EVENT: return "SPATHI_SHIELD_EVENT"; case ADVANCE_ILWRATH_MISSION: return "ADVANCE_ILWRATH_MISSION"; case ADVANCE_MYCON_MISSION: return "ADVANCE_MYCON_MISSION"; case ARILOU_UMGAH_CHECK: return "ARILOU_UMGAH_CHECK"; case YEHAT_REBEL_EVENT: return "YEHAT_REBEL_EVENT"; case SLYLANDRO_RAMP_UP: return "SLYLANDRO_RAMP_UP"; case SLYLANDRO_RAMP_DOWN: return "SLYLANDRO_RAMP_DOWN"; default: // Should not happen return "???"; } } static void dumpEventCallback (const EVENTPTR eventPtr, void *arg) { FILE *out = (FILE *) arg; dumpEvent (out, eventPtr); } void dumpEvent (FILE *out, EVENTPTR eventPtr) { fprintf (out, "%4u/%02u/%02u: %s\n", eventPtr->year_index, eventPtr->month_index, eventPtr->day_index, eventName (eventPtr->func_index)); } void dumpEvents (FILE *out) { BOOLEAN restartClock = FALSE; if (GameClockRunning ()) { SuspendGameClock (); restartClock = TRUE; } ForAllEvents (dumpEventCallback, out); if (restartClock) ResumeGameClock (); } //////////////////////////////////////////////////////////////////////////// // NB: Ship maximum speed and turning rate aren't updated in // HyperSpace/QuasiSpace or in melee. void equipShip (void) { int i; // Don't do anything unless in the full game. if (LOBYTE (GLOBAL (CurrentActivity)) == SUPER_MELEE) return; // Thrusters: for (i = 0; i < NUM_DRIVE_SLOTS; i++) GLOBAL_SIS (DriveSlots[i]) = FUSION_THRUSTER; // Turning jets: for (i = 0; i < NUM_JET_SLOTS; i++) GLOBAL_SIS (JetSlots[i]) = TURNING_JETS; // Shields: SET_GAME_STATE (LANDER_SHIELDS, (1 << EARTHQUAKE_DISASTER) | (1 << BIOLOGICAL_DISASTER) | (1 << LIGHTNING_DISASTER) | (1 << LAVASPOT_DISASTER)); // Modules: if (GET_GAME_STATE (CHMMR_BOMB_STATE) < 2) { // The Precursor bomb has not been installed. // This is the original TFB testing layout. i = 0; GLOBAL_SIS (ModuleSlots[i++]) = HIGHEFF_FUELSYS; GLOBAL_SIS (ModuleSlots[i++]) = HIGHEFF_FUELSYS; GLOBAL_SIS (ModuleSlots[i++]) = CREW_POD; GLOBAL_SIS (ModuleSlots[i++]) = CREW_POD; GLOBAL_SIS (ModuleSlots[i++]) = CREW_POD; GLOBAL_SIS (ModuleSlots[i++]) = CREW_POD; GLOBAL_SIS (ModuleSlots[i++]) = CREW_POD; GLOBAL_SIS (ModuleSlots[i++]) = STORAGE_BAY; GLOBAL_SIS (ModuleSlots[i++]) = SHIVA_FURNACE; GLOBAL_SIS (ModuleSlots[i++]) = SHIVA_FURNACE; GLOBAL_SIS (ModuleSlots[i++]) = DYNAMO_UNIT; GLOBAL_SIS (ModuleSlots[i++]) = TRACKING_SYSTEM; GLOBAL_SIS (ModuleSlots[i++]) = TRACKING_SYSTEM; GLOBAL_SIS (ModuleSlots[i++]) = SHIVA_FURNACE; GLOBAL_SIS (ModuleSlots[i++]) = CANNON_WEAPON; GLOBAL_SIS (ModuleSlots[i++]) = CANNON_WEAPON; // Landers: GLOBAL_SIS (NumLanders) = MAX_LANDERS; } else { // The Precursor bomb has been installed. i = NUM_BOMB_MODULES; GLOBAL_SIS (ModuleSlots[i++]) = HIGHEFF_FUELSYS; GLOBAL_SIS (ModuleSlots[i++]) = CREW_POD; GLOBAL_SIS (ModuleSlots[i++]) = SHIVA_FURNACE; GLOBAL_SIS (ModuleSlots[i++]) = SHIVA_FURNACE; GLOBAL_SIS (ModuleSlots[i++]) = CANNON_WEAPON; GLOBAL_SIS (ModuleSlots[i++]) = SHIVA_FURNACE; } assert (i <= NUM_MODULE_SLOTS); // Fill the fuel and crew compartments to the maximum. GLOBAL_SIS (FuelOnBoard) = FUEL_RESERVE; GLOBAL_SIS (CrewEnlisted) = 0; for (i = 0; i < NUM_MODULE_SLOTS; i++) { switch (GLOBAL_SIS (ModuleSlots[i])) { case CREW_POD: GLOBAL_SIS (CrewEnlisted) += CREW_POD_CAPACITY; break; case FUEL_TANK: GLOBAL_SIS (FuelOnBoard) += FUEL_TANK_CAPACITY; break; case HIGHEFF_FUELSYS: GLOBAL_SIS (FuelOnBoard) += HEFUEL_TANK_CAPACITY; break; } } // Update the maximum speed and turning rate when in interplanetary. if (pSolarSysState != NULL) { // Thrusters: pSolarSysState->max_ship_speed = 5 * IP_SHIP_THRUST_INCREMENT; for (i = 0; i < NUM_DRIVE_SLOTS; i++) if (GLOBAL_SIS (DriveSlots[i] == FUSION_THRUSTER)) pSolarSysState->max_ship_speed += IP_SHIP_THRUST_INCREMENT; // Turning jets: pSolarSysState->turn_wait = IP_SHIP_TURN_WAIT; for (i = 0; i < NUM_JET_SLOTS; i++) if (GLOBAL_SIS (JetSlots[i]) == TURNING_JETS) pSolarSysState->turn_wait -= IP_SHIP_TURN_DECREMENT; } // Make sure everything is redrawn: if (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE || LOBYTE (GLOBAL (CurrentActivity)) == IN_INTERPLANETARY) { LockMutex (GraphicsLock); DeltaSISGauges (UNDEFINED_DELTA, UNDEFINED_DELTA, UNDEFINED_DELTA); UnlockMutex (GraphicsLock); } } //////////////////////////////////////////////////////////////////////////// #if 0 // Not needed anymore, but could be useful in the future. // Find the HELEMENT belonging to the Flagship. static HELEMENT findFlagshipElement (void) { HELEMENT hElement, hNextElement; ELEMENTPTR ElementPtr; // Find the ship element. for (hElement = GetTailElement (); hElement != 0; hElement = hNextElement) { LockElement (hElement, &ElementPtr); if ((ElementPtr->state_flags & PLAYER_SHIP) != 0) { UnlockElement (hElement); return hElement; } hNextElement = GetPredElement (ElementPtr); UnlockElement (hElement); } return 0; } #endif // Move the Flagship to the destination of the autopilot. // Should only be called from HyperSpace/QuasiSpace. // It can be called from debugHook directly after entering HS/QS though. void doInstantMove (void) { // Move to the new location: GLOBAL_SIS (log_x) = UNIVERSE_TO_LOGX((GLOBAL (autopilot)).x); GLOBAL_SIS (log_y) = UNIVERSE_TO_LOGY((GLOBAL (autopilot)).y); // Check for a solar systems at the destination. if (GET_GAME_STATE (ARILOU_SPACE_SIDE) <= 1) { // If there's a solar system at the destination, enter it. CurStarDescPtr = FindStar (0, &(GLOBAL (autopilot)), 0, 0); if (CurStarDescPtr) { // Leave HyperSpace/QuasiSpace if we're there: SET_GAME_STATE (USED_BROADCASTER, 0); GLOBAL (CurrentActivity) &= ~IN_BATTLE; // Enter IP: GLOBAL (ShipStamp.frame) = 0; // This causes the ship position in IP to be reset. GLOBAL (CurrentActivity) |= START_INTERPLANETARY; } } // Turn off the autopilot: (GLOBAL (autopilot)).x = ~0; (GLOBAL (autopilot)).y = ~0; } //////////////////////////////////////////////////////////////////////////// void showSpheres (void) { HSTARSHIP hStarShip, hNextShip; for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); hStarShip != NULL; hStarShip = hNextShip) { EXTENDED_SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (EXTENDED_SHIP_FRAGMENTPTR) LockStarShip ( &GLOBAL (avail_race_q), hStarShip); hNextShip = _GetSuccLink (StarShipPtr); if ((StarShipPtr->ShipInfo.actual_strength != (COUNT) ~0) && (StarShipPtr->ShipInfo.known_strength != StarShipPtr->ShipInfo.actual_strength)) { StarShipPtr->ShipInfo.known_strength = StarShipPtr->ShipInfo.actual_strength; StarShipPtr->ShipInfo.known_loc = StarShipPtr->ShipInfo.loc; } UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } } //////////////////////////////////////////////////////////////////////////// void activateAllShips (void) { HSTARSHIP hStarShip, hNextShip; for (hStarShip = GetHeadLink (&GLOBAL (avail_race_q)); hStarShip != NULL; hStarShip = hNextShip) { EXTENDED_SHIP_FRAGMENTPTR StarShipPtr; StarShipPtr = (EXTENDED_SHIP_FRAGMENTPTR) LockStarShip ( &GLOBAL (avail_race_q), hStarShip); hNextShip = _GetSuccLink (StarShipPtr); if (StarShipPtr->ShipInfo.icons != NULL) // Skip the Ur-Quan probe. { StarShipPtr->ShipInfo.ship_flags &= ~(GOOD_GUY | BAD_GUY); StarShipPtr->ShipInfo.ship_flags |= GOOD_GUY; } UnlockStarShip (&GLOBAL (avail_race_q), hStarShip); } } //////////////////////////////////////////////////////////////////////////// void forAllStars (void (*callback) (STAR_DESC *, void *), void *arg) { int i; extern STAR_DESC starmap_array[]; for (i = 0; i < NUM_SOLAR_SYSTEMS; i++) callback (&starmap_array[i], arg); } void forAllPlanets (STAR_DESC *star, SOLARSYS_STATE *system, void (*callback) ( STAR_DESC *, SOLARSYS_STATE *, PLANET_DESC *, void *), void *arg) { COUNT i; assert(CurStarDescPtr = star); assert(pSolarSysState == system); for (i = 0; i < system->SunDesc[0].NumPlanets; i++) callback (star, system, &system->PlanetDesc[i], arg); } void forAllMoons (STAR_DESC *star, SOLARSYS_STATE *system, PLANET_DESC *planet, void (*callback) (STAR_DESC *, SOLARSYS_STATE *, PLANET_DESC *, PLANET_DESC *, void *), void *arg) { COUNT i; assert(pSolarSysState == system); assert(system->pBaseDesc == planet); for (i = 0; i < planet->NumPlanets; i++) callback (star, system, planet, &system->MoonDesc[i], arg); } //////////////////////////////////////////////////////////////////////////// void UniverseRecurse (UniverseRecurseArg *universeRecurseArg) { BOOLEAN clockRunning; ACTIVITY savedActivity; if (universeRecurseArg->systemFunc == NULL && universeRecurseArg->planetFunc == NULL && universeRecurseArg->moonFunc == NULL) return; clockRunning = GameClockRunning (); if (clockRunning) SuspendGameClock (); //TFB_DEBUG_HALT = 1; savedActivity = GLOBAL (CurrentActivity); disableInteractivity = TRUE; forAllStars (starRecurse, (void *) universeRecurseArg); disableInteractivity = FALSE; GLOBAL (CurrentActivity) = savedActivity; if (clockRunning) ResumeGameClock (); } static void starRecurse (STAR_DESC *star, void *arg) { UniverseRecurseArg *universeRecurseArg = (UniverseRecurseArg *) arg; SOLARSYS_STATE SolarSysState; PSOLARSYS_STATE oldPSolarSysState = pSolarSysState; DWORD oldSeed = TFB_SeedRandom (MAKE_DWORD (star->star_pt.x, star->star_pt.y)); STAR_DESCPTR oldStarDescPtr = CurStarDescPtr; CurStarDescPtr = star; memset (&SolarSysState, 0, sizeof (SolarSysState)); SolarSysState.SunDesc[0].pPrevDesc = 0; SolarSysState.SunDesc[0].rand_seed = TFB_Random (); SolarSysState.SunDesc[0].data_index = STAR_TYPE (star->Type); SolarSysState.SunDesc[0].location.x = 0; SolarSysState.SunDesc[0].location.y = 0; //SolarSysState.SunDesc[0].radius = MIN_ZOOM_RADIUS; SolarSysState.GenFunc = GenerateIP (star->Index); pSolarSysState = &SolarSysState; (*pSolarSysState->GenFunc) (GENERATE_PLANETS); if (universeRecurseArg->systemFunc != NULL) { (*universeRecurseArg->systemFunc) ( star, &SolarSysState, universeRecurseArg->arg); } if (universeRecurseArg->planetFunc != NULL || universeRecurseArg->moonFunc != NULL) { forAllPlanets (star, &SolarSysState, planetRecurse, (void *) universeRecurseArg); } pSolarSysState = oldPSolarSysState; CurStarDescPtr = oldStarDescPtr; TFB_SeedRandom (oldSeed); } static void planetRecurse (STAR_DESC *star, SOLARSYS_STATE *system, PLANET_DESC *planet, void *arg) { UniverseRecurseArg *universeRecurseArg = (UniverseRecurseArg *) arg; assert(CurStarDescPtr = star); assert(pSolarSysState == system); system->pBaseDesc = planet; planet->pPrevDesc = &system->SunDesc[0]; if (universeRecurseArg->planetFunc != NULL) { system->pOrbitalDesc = planet; DoPlanetaryAnalysis (&system->SysInfo, planet); // When GenerateRandomIP is used as GenFunc, // GENERATE_ORBITAL will also call DoPlanetaryAnalysis, // but with other GenFuncs this is not guaranteed. (*system->GenFunc) (GENERATE_ORBITAL); (*universeRecurseArg->planetFunc) ( planet, universeRecurseArg->arg); } if (universeRecurseArg->moonFunc != NULL) { DWORD oldSeed = TFB_SeedRandom (planet->rand_seed); (*system->GenFunc) (GENERATE_MOONS); forAllMoons (star, system, planet, moonRecurse, (void *) universeRecurseArg); TFB_SeedRandom (oldSeed); } } static void moonRecurse (STAR_DESC *star, SOLARSYS_STATE *system, PLANET_DESC *planet, PLANET_DESC *moon, void *arg) { UniverseRecurseArg *universeRecurseArg = (UniverseRecurseArg *) arg; assert(CurStarDescPtr = star); assert(pSolarSysState == system); assert(system->pBaseDesc == planet); moon->pPrevDesc = planet; if (universeRecurseArg->moonFunc != NULL) { system->pOrbitalDesc = moon; DoPlanetaryAnalysis (&system->SysInfo, moon); // When GenerateRandomIP is used as GenFunc, // GENERATE_ORBITAL will also call DoPlanetaryAnalysis, // but with other GenFuncs this is not guaranteed. (*system->GenFunc) (GENERATE_ORBITAL); (*universeRecurseArg->moonFunc) ( moon, universeRecurseArg->arg); } } //////////////////////////////////////////////////////////////////////////// typedef struct { FILE *out; } DumpUniverseArg; void dumpUniverse (FILE *out) { DumpUniverseArg dumpUniverseArg; UniverseRecurseArg universeRecurseArg; dumpUniverseArg.out = out; universeRecurseArg.systemFunc = dumpSystemCallback; universeRecurseArg.planetFunc = dumpPlanetCallback; universeRecurseArg.moonFunc = dumpMoonCallback; universeRecurseArg.arg = (void *) &dumpUniverseArg; UniverseRecurse (&universeRecurseArg); } void dumpUniverseToFile (void) { FILE *out; # define UNIVERSE_DUMP_FILE "PlanetInfo" out = fopen(UNIVERSE_DUMP_FILE, "w"); if (out == NULL) { fprintf(stderr, "Error: Could not open file '%s' for " "writing: %s\n", UNIVERSE_DUMP_FILE, strerror(errno)); return; } dumpUniverse (out); fclose(out); fprintf(stdout, "*** Star dump complete. The game may be in an " "undefined state.\n"); // Data generation may have changed the game state, // in particular for special planet generation. } static void dumpSystemCallback (const STAR_DESC *star, const SOLARSYS_STATE *system, void *arg) { FILE *out = ((DumpUniverseArg *) arg)->out; dumpSystem (out, star, system); } void dumpSystem (FILE *out, const STAR_DESC *star, const SOLARSYS_STATE *system) { UNICODE name[256]; UNICODE buf[40]; GetClusterName ((STAR_DESCPTR) star, name); snprintf (buf, sizeof buf, "%s %s", bodyColorString (STAR_COLOR(star->Type)), starTypeString (STAR_TYPE(star->Type))); fprintf (out, "%-22s (%3d.%1d, %3d.%1d) %-19s %s\n", name, star->star_pt.x / 10, star->star_pt.x % 10, star->star_pt.y / 10, star->star_pt.y % 10, buf, starPresenceString (star->Index)); (void) system; /* satisfy compiler */ } const char * bodyColorString (BYTE col) { switch (col) { case BLUE_BODY: return "blue"; case GREEN_BODY: return "green"; case ORANGE_BODY: return "orange"; case RED_BODY: return "red"; case WHITE_BODY: return "white"; case YELLOW_BODY: return "yellow"; case CYAN_BODY: return "cyan"; case PURPLE_BODY: return "purple"; case VIOLET_BODY: return "violet"; default: // Should not happen return "???"; } } const char * starTypeString (BYTE type) { switch (type) { case DWARF_STAR: return "dwarf"; case GIANT_STAR: return "giant"; case SUPER_GIANT_STAR: return "super giant"; default: // Should not happen return "???"; } } const char * starPresenceString (BYTE index) { switch (index) { case 0: // nothing return ""; case SOL_DEFINED: return "Sol"; case SHOFIXTI_DEFINED: return "Shofixti male"; case MAIDENS_DEFINED: return "Shofixti maidens"; case START_COLONY_DEFINED: return "Starting colony"; case SPATHI_DEFINED: return "Spathi home"; case ZOQFOT_DEFINED: return "Zoq-Fot-Pik home"; case MELNORME0_DEFINED: return "Melnorme trader #0"; case MELNORME1_DEFINED: return "Melnorme trader #1"; case MELNORME2_DEFINED: return "Melnorme trader #2"; case MELNORME3_DEFINED: return "Melnorme trader #3"; case MELNORME4_DEFINED: return "Melnorme trader #4"; case MELNORME5_DEFINED: return "Melnorme trader #5"; case MELNORME6_DEFINED: return "Melnorme trader #6"; case MELNORME7_DEFINED: return "Melnorme trader #7"; case MELNORME8_DEFINED: return "Melnorme trader #8"; case TALKING_PET_DEFINED: return "Talking Pet"; case CHMMR_DEFINED: return "Chmmr home"; case SYREEN_DEFINED: return "Syreen home"; case BURVIXESE_DEFINED: return "Burvixese ruins"; case SLYLANDRO_DEFINED: return "Slylandro home"; case DRUUGE_DEFINED: return "Druuge home"; case BOMB_DEFINED: return "Precursor bomb"; case AQUA_HELIX_DEFINED: return "Aqua Helix"; case SUN_DEVICE_DEFINED: return "Sun Device"; case TAALO_PROTECTOR_DEFINED: return "Taalo Shield"; case SHIP_VAULT_DEFINED: return "Syreen ship vault"; case URQUAN_WRECK_DEFINED: return "Ur-Quan ship wreck"; case VUX_BEAST_DEFINED: return "Zex' beauty"; case SAMATRA_DEFINED: return "Sa-Matra"; case ZOQ_SCOUT_DEFINED: return "Zoq-Fot-Pik scout"; case MYCON_DEFINED: return "Mycon home"; case EGG_CASE0_DEFINED: return "Mycon egg shell #0"; case EGG_CASE1_DEFINED: return "Mycon egg shell #1"; case EGG_CASE2_DEFINED: return "Mycon egg shell #2"; case PKUNK_DEFINED: return "Pkunk home"; case UTWIG_DEFINED: return "Utwig home"; case SUPOX_DEFINED: return "Supox home"; case YEHAT_DEFINED: return "Yehat home"; case VUX_DEFINED: return "Vux home"; case ORZ_DEFINED: return "Orz home"; case THRADD_DEFINED: return "Thraddash home"; case RAINBOW_DEFINED: return "Rainbow world"; case ILWRATH_DEFINED: return "Ilwrath home"; case ANDROSYNTH_DEFINED: return "Androsynth ruins"; case MYCON_TRAP_DEFINED: return "Mycon trap"; default: // Should not happen return "???"; } } static void dumpPlanetCallback (const PLANET_DESC *planet, void *arg) { FILE *out = ((DumpUniverseArg *) arg)->out; dumpPlanet (out, planet); } void dumpPlanet (FILE *out, const PLANET_DESC *planet) { (*pSolarSysState->GenFunc) (GENERATE_NAME); fprintf (out, "- %-37s %s\n", GLOBAL_SIS (PlanetName), planetTypeString (planet->data_index & ~PLANET_SHIELDED)); dumpWorld (out, planet); } static void dumpMoonCallback (const PLANET_DESC *moon, void *arg) { FILE *out = ((DumpUniverseArg *) arg)->out; dumpMoon (out, moon); } void dumpMoon (FILE *out, const PLANET_DESC *moon) { const char *typeStr; if (moon->data_index == (BYTE) ~0) { typeStr = "StarBase"; } else if (moon->data_index == (BYTE) (~0 - 1)) { typeStr = "Sa-Matra"; } else { typeStr = planetTypeString (moon->data_index & ~PLANET_SHIELDED); } fprintf (out, " - Moon %-30c %s\n", 'a' + (moon - &pSolarSysState->MoonDesc[0]), typeStr); dumpWorld (out, moon); } static void dumpWorld (FILE *out, const PLANET_DESC *world) { PLANET_INFO *info; if (world->data_index == (BYTE) ~0) { // StarBase return; } if (world->data_index == (BYTE)(~0 - 1)) { // Sa-Matra return; } info = &pSolarSysState->SysInfo.PlanetInfo; fprintf(out, " AxialTilt: %d\n", info->AxialTilt); fprintf(out, " Tectonics: %d\n", info->Tectonics); fprintf(out, " Weather: %d\n", info->Weather); fprintf(out, " Density: %d\n", info->PlanetDensity); fprintf(out, " Radius: %d\n", info->PlanetRadius); fprintf(out, " Gravity: %d\n", info->SurfaceGravity); fprintf(out, " Temp: %d\n", info->SurfaceTemperature); fprintf(out, " Day: %d\n", info->RotationPeriod); fprintf(out, " Atmosphere: %d\n", info->AtmoDensity); fprintf(out, " LifeChance: %d\n", info->LifeChance); fprintf(out, " DistToSun: %d\n", info->PlanetToSunDist); if (world->data_index & PLANET_SHIELDED) { // Slave-shielded planet return; } fprintf (out, " Bio: %4d Min: %4d\n", calculateBioValue (pSolarSysState, world), calculateMineralValue (pSolarSysState, world)); } COUNT calculateBioValue (const SOLARSYS_STATE *system, const PLANET_DESC *world) { COUNT result; COUNT numBio; COUNT i; assert(system->pOrbitalDesc == world); ((SOLARSYS_STATE *) system)->CurNode = (COUNT)~0; (*system->GenFunc) (GENERATE_LIFE); numBio = system->CurNode; result = 0; for (i = 0; i < numBio; i++) { ((SOLARSYS_STATE *) system)->CurNode = i; (*system->GenFunc) (GENERATE_LIFE); result += BIO_CREDIT_VALUE * LONIBBLE (CreatureData[ system->SysInfo.PlanetInfo.CurType].ValueAndHitPoints); } return result; } void generateBioIndex(const SOLARSYS_STATE *system, const PLANET_DESC *world, COUNT bio[]) { COUNT numBio; COUNT i; assert(system->pOrbitalDesc == world); ((SOLARSYS_STATE *) system)->CurNode = (COUNT)~0; (*system->GenFunc) (GENERATE_LIFE); numBio = system->CurNode; for (i = 0; i < NUM_CREATURE_TYPES + NUM_SPECIAL_CREATURE_TYPES; i++) bio[i] = 0; for (i = 0; i < numBio; i++) { ((SOLARSYS_STATE *) system)->CurNode = i; (*system->GenFunc) (GENERATE_LIFE); bio[system->SysInfo.PlanetInfo.CurType]++; } } COUNT calculateMineralValue (const SOLARSYS_STATE *system, const PLANET_DESC *world) { COUNT result; COUNT numDeposits; COUNT i; assert(system->pOrbitalDesc == world); ((SOLARSYS_STATE *) system)->CurNode = (COUNT)~0; (*system->GenFunc) (GENERATE_MINERAL); numDeposits = system->CurNode; result = 0; for (i = 0; i < numDeposits; i++) { ((SOLARSYS_STATE *) system)->CurNode = i; (*system->GenFunc) (GENERATE_MINERAL); result += HIBYTE (system->SysInfo.PlanetInfo.CurDensity) * GLOBAL (ElementWorth[ElementCategory ( system->SysInfo.PlanetInfo.CurType)]); } return result; } void generateMineralIndex(const SOLARSYS_STATE *system, const PLANET_DESC *world, COUNT minerals[]) { COUNT numDeposits; COUNT i; assert(system->pOrbitalDesc == world); ((SOLARSYS_STATE *) system)->CurNode = (COUNT)~0; (*system->GenFunc) (GENERATE_MINERAL); numDeposits = system->CurNode; for (i = 0; i < NUM_ELEMENT_CATEGORIES; i++) minerals[i] = 0; for (i = 0; i < numDeposits; i++) { ((SOLARSYS_STATE *) system)->CurNode = i; (*system->GenFunc) (GENERATE_MINERAL); minerals[ElementCategory(system->SysInfo.PlanetInfo.CurType)] += HIBYTE (system->SysInfo.PlanetInfo.CurDensity); } } //////////////////////////////////////////////////////////////////////////// void forAllPlanetTypes (void (*callback) (int, const PlanetFrame *, void *), void *arg) { int i; extern const PlanetFrame planet_array[]; for (i = 0; i < NUMBER_OF_PLANET_TYPES; i++) callback (i, &planet_array[i], arg); } typedef struct { FILE *out; } DumpPlanetTypesArg; void dumpPlanetTypes (FILE *out) { DumpPlanetTypesArg dumpPlanetTypesArg; dumpPlanetTypesArg.out = out; forAllPlanetTypes (dumpPlanetTypeCallback, (void *) &dumpPlanetTypesArg); } static void dumpPlanetTypeCallback (int index, const PlanetFrame *planetType, void *arg) { DumpPlanetTypesArg *dumpPlanetTypesArg = (DumpPlanetTypesArg *) arg; dumpPlanetType(dumpPlanetTypesArg->out, index, planetType); } void dumpPlanetType (FILE *out, int index, const PlanetFrame *planetType) { int i; fprintf (out, "%s\n" "\tType: %s\n" "\tColor: %s\n" "\tSurface generation algoritm: %s\n" "\tTectonics: %s\n" "\tAtmosphere: %s\n" "\tDensity: %s\n" "\tElements:\n", planetTypeString (index), worldSizeString (PLANSIZE (planetType->Type)), bodyColorString (PLANCOLOR (planetType->Type)), worldGenAlgoString (PLANALGO (planetType->Type)), tectonicsString (planetType->BaseTectonics), atmosphereString (HINIBBLE (planetType->AtmoAndDensity)), densityString (LONIBBLE (planetType->AtmoAndDensity)) ); for (i = 0; i < NUM_USEFUL_ELEMENTS; i++) { const ElementEntry *entry; entry = &planetType->UsefulElements[i]; if (entry->Density == 0) continue; fprintf(out, "\t\t0 to %d %s-quality (+%d) deposits of %s (%s)\n", DEPOSIT_QUANTITY (entry->Density), depositQualityString (DEPOSIT_QUALITY (entry->Density)), DEPOSIT_QUALITY (entry->Density) * 5, GAME_STRING (ELEMENTS_STRING_BASE + entry->ElementType), GAME_STRING (CARGO_STRING_BASE + 2 + ElementCategory ( entry->ElementType)) ); } fprintf (out, "\n"); } const char * planetTypeString (int typeIndex) { static UNICODE typeStr[40]; if (typeIndex >= FIRST_GAS_GIANT) { // "Gas Giant" snprintf(typeStr, sizeof typeStr, "%s", GAME_STRING (SCAN_STRING_BASE + 4 + 51)); } else { // " World" (eg. "Water World") snprintf(typeStr, sizeof typeStr, "%s %s", GAME_STRING (SCAN_STRING_BASE + 4 + typeIndex), GAME_STRING (SCAN_STRING_BASE + 4 + 50)); } return typeStr; } // size is what you get from PLANSIZE (planetFrame.Type) const char * worldSizeString (BYTE size) { switch (size) { case SMALL_ROCKY_WORLD: return "small rocky world"; case LARGE_ROCKY_WORLD: return "large rocky world"; case GAS_GIANT: return "gas giant"; default: // Should not happen return "???"; } } // algo is what you get from PLANALGO (planetFrame.Type) const char * worldGenAlgoString (BYTE algo) { switch (algo) { case TOPO_ALGO: return "TOPO_ALGO"; case CRATERED_ALGO: return "CRATERED_ALGO"; case GAS_GIANT_ALGO: return "GAS_GIANT_ALGO"; default: // Should not happen return "???"; } } // tectonics is what you get from planetFrame.BaseTechtonics // not reentrant const char * tectonicsString (BYTE tectonics) { static char buf[sizeof "-127"]; switch (tectonics) { case NO_TECTONICS: return "none"; case LOW_TECTONICS: return "low"; case MED_TECTONICS: return "medium"; case HIGH_TECTONICS: return "high"; case SUPER_TECTONICS: return "super"; default: snprintf (buf, sizeof buf, "%d", tectonics); return buf; } } // atmosphere is what you get from HINIBBLE (planetFrame.AtmoAndDensity) const char * atmosphereString (BYTE atmosphere) { switch (atmosphere) { case LIGHT: return "thin"; case MEDIUM: return "normal"; case HEAVY: return "thick"; default: return "super thick"; } } // density is what you get from LONIBBLE (planetFrame.AtmoAndDensity) const char * densityString (BYTE density) { switch (density) { case GAS_DENSITY: return "gaseous"; case LIGHT_DENSITY: return "light"; case LOW_DENSITY: return "low"; case NORMAL_DENSITY: return "normal"; case HIGH_DENSITY: return "high"; case SUPER_DENSITY: return "super high"; default: // Should not happen return "???"; } } // quality is what you get from DEPOSIT_QUALITY (elementEntry.Density) const char * depositQualityString (BYTE quality) { switch (quality) { case LIGHT: return "low"; case MEDIUM: return "medium"; case HEAVY: return "high"; default: // Should not happen return "???"; } } //////////////////////////////////////////////////////////////////////////// // Which should be GOOD_GUY or BAD_GUY STARSHIPPTR findPlayerShip(ELEMENT_FLAGS which) { HELEMENT hElement, hNextElement; for (hElement = GetHeadElement (); hElement; hElement = hNextElement) { ELEMENTPTR ElementPtr; LockElement (hElement, &ElementPtr); hNextElement = GetSuccElement (ElementPtr); if ((ElementPtr->state_flags & PLAYER_SHIP) && (ElementPtr->state_flags & (GOOD_GUY | BAD_GUY)) == which) { STARSHIPPTR StarShipPtr; GetElementStarShip (ElementPtr, &StarShipPtr); UnlockElement (hElement); return StarShipPtr; } UnlockElement (hElement); } return NULL; } //////////////////////////////////////////////////////////////////////////// void resetCrewBattle(void) { STARSHIPPTR StarShipPtr; COUNT delta; CONTEXT OldContext; if (!(GLOBAL (CurrentActivity) & IN_BATTLE) || (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE)) return; StarShipPtr = findPlayerShip (GOOD_GUY); if (StarShipPtr == NULL || StarShipPtr->RaceDescPtr == NULL) return; delta = StarShipPtr->RaceDescPtr->ship_info.max_crew - StarShipPtr->RaceDescPtr->ship_info.crew_level; OldContext = SetContext (StatusContext); DeltaCrew (StarShipPtr->hShip, delta); SetContext (OldContext); } void resetEnergyBattle(void) { STARSHIPPTR StarShipPtr; COUNT delta; CONTEXT OldContext; if (!(GLOBAL (CurrentActivity) & IN_BATTLE) || (LOBYTE (GLOBAL (CurrentActivity)) == IN_HYPERSPACE)) return; StarShipPtr = findPlayerShip (GOOD_GUY); if (StarShipPtr == NULL || StarShipPtr->RaceDescPtr == NULL) return; delta = StarShipPtr->RaceDescPtr->ship_info.max_energy - StarShipPtr->RaceDescPtr->ship_info.energy_level; OldContext = SetContext (StatusContext); DeltaEnergy (StarShipPtr->hShip, delta); SetContext (OldContext); } #endif /* DEBUG */ uqm-0.6.2/sc2/src/options.h0000600000175000017500000000417110543202107014126 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Eventually this should include all configuration stuff, * for now there's few options which indicate 3do/pc flavors. */ #ifndef OPTIONS_H #define OPTIONS_H #include "port.h" #include "libs/compiler.h" #include "libs/uio.h" #define OPT_3DO 0x01 #define OPT_PC 0x02 #define OPT_ALL 0xFF extern int optWhichMusic; extern int optWhichCoarseScan; extern int optWhichMenu; extern int optWhichFonts; extern int optWhichIntro; extern int optWhichShield; extern int optSmoothScroll; extern int optMeleeScale; extern BOOLEAN optSubtitles; extern BOOLEAN optStereoSFX; extern uio_DirHandle *contentDir; extern uio_DirHandle *configDir; extern uio_DirHandle *saveDir; extern uio_DirHandle *meleeDir; extern char baseContentPath[PATH_MAX]; extern uio_DirList *availableAddons; /* These get edited by TEXTENTRY widgets, so they should have room to * hold as much as one of them allows by default. */ typedef struct _input_template { char name[30]; /* This should eventually also hold things like Joystick Port * and whether or not joysticks are enabled at all, and * possibly the whole configuration scheme. If we do that, we * can actually ditch much of VControl. */ } INPUT_TEMPLATE; extern INPUT_TEMPLATE input_templates[6]; void prepareContentDir (const char *contentDirName, const char **addons); void prepareConfigDir (const char *configDirName); void prepareMeleeDir (void); void prepareSaveDir (void); #endif uqm-0.6.2/sc2/src/config_win.h.in0000644000175000017500000000310410547157076015207 0ustar joeyjoey/* This file contains some compile-time configuration options for MS Windows * systems when building using build.sh (MinGW, Cygwin). * config_win.h is generated from src/config_win.h.in by build.sh * For building using MSVC, you'll have to edit src/msvc++/config.h manually * if you want anything else than the defaults. * For *nix systems, config_unix.h is used, which is generated by build.sh * from src/config_unix.h.in. */ #ifndef _CONFIG_WIN_H #define _CONFIG_WIN_H /* Directory where the UQM game data is located */ #define CONTENTDIR "../content/" /* Directory where game data will be stored */ //#define USERDIR "../userdata/" #define USERDIR "%APPDATA%/uqm/" /* Directory where config files will be stored */ #define CONFIGDIR USERDIR /* Directory where supermelee teams will be stored */ #define MELEEDIR "%UQM_CONFIG_DIR%/teams/" /* Directory where save games will be stored */ #define SAVEDIR "%UQM_CONFIG_DIR%/save/" /* Defined if words are stored with the most significant byte first */ @WORDS_BIGENDIAN@ /* Defined if your system has readdir_r of its own */ @HAVE_READDIR_R@ /* Defined if your system has setenv of its own */ @HAVE_SETENV@ /* Defined if your system has strupr of its own */ @HAVE_STRUPR@ /* Defined if your system has stricmp of its own */ @HAVE_STRICMP@ /* Defined if your system has getopt_long */ @HAVE_GETOPT_LONG@ /* Defined if your system has iswgraph of its own*/ @HAVE_ISWGRAPH@ /* Defined if your system has wchar_t of its own */ @HAVE_WCHAR_T@ /* Defined if your system has wint_t of its own */ @HAVE_WINT_T@ #endif /* _CONFIG_WIN_H */ uqm-0.6.2/sc2/src/options.c0000644000175000017500000002454710546776503014165 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Eventually this should include all configuration stuff, * for now there's few options which indicate 3do/pc flavors. */ #include "options.h" #include "port.h" #include "libs/graphics/gfx_common.h" #include "file.h" #include "config.h" #include "libs/compiler.h" #include "libs/uio.h" #include "libs/strlib.h" #include "libs/log.h" #include #include #include #include #include int optWhichMusic; int optWhichCoarseScan; int optWhichMenu; int optWhichFonts; int optWhichIntro; int optWhichShield; int optSmoothScroll; int optMeleeScale; BOOLEAN optSubtitles; BOOLEAN optStereoSFX; uio_DirHandle *contentDir; uio_DirHandle *configDir; uio_DirHandle *saveDir; uio_DirHandle *meleeDir; char baseContentPath[PATH_MAX]; uio_DirList *availableAddons; extern uio_Repository *repository; extern uio_DirHandle *rootDir; INPUT_TEMPLATE input_templates[6]; static const char *findFileInDirs (const char *locs[], int numLocs, const char *file); static void mountContentDir (uio_Repository *repository, const char *contentPath, const char **addons); static void mountDirZips (uio_MountHandle *contentHandle, uio_DirHandle *dirHandle); // Looks for a file 'file' in all 'numLocs' locations from 'locs'. // returns the first element from locs where 'file' is found. // If there is no matching location, NULL will be returned and // errno will be set to 'ENOENT'. // Entries from 'locs' that together with 'file' are longer than // PATH_MAX will be ignored, except for a warning given to stderr. static const char * findFileInDirs (const char *locs[], int numLocs, const char *file) { int locI; char path[PATH_MAX]; size_t fileLen; fileLen = strlen (file); for (locI = 0; locI < numLocs; locI++) { size_t locLen; const char *loc; bool needSlash; loc = locs[locI]; locLen = strlen (loc); needSlash = (locLen != 0 && loc[locLen - 1] != '/'); if (locLen + (needSlash ? 1 : 0) + fileLen + 1 >= sizeof path) { // This dir plus the file name is too long. log_add (log_Warning, "Warning: path '%s' is ignored" " because it is too long.", loc); continue; } snprintf (path, sizeof path, "%s%s%s", loc, needSlash ? "/" : "", file); if (fileExists (path)) return loc; } // No matching location was found. errno = ENOENT; return NULL; } void prepareContentDir (const char *contentDirName, const char **addons) { const char *testFile = "version"; const char *loc; if (contentDirName == NULL) { // Try the default content locations. const char *locs[] = { CONTENTDIR, /* defined in config.h */ "" "content", "../../content" /* For running from MSVC */ }; loc = findFileInDirs (locs, sizeof locs / sizeof locs[0], testFile); } else { // Only use the explicitely supplied content dir. loc = findFileInDirs (&contentDirName, 1, testFile); } if (loc == NULL) { log_add (log_Fatal, "Fatal error: Could not find content."); exit (EXIT_FAILURE); } if (expandPath (baseContentPath, sizeof baseContentPath, loc, EP_ALL_SYSTEM) == -1) { log_add (log_Fatal, "Fatal error: Could not expand path to content " "directory: %s", strerror (errno)); exit (EXIT_FAILURE); } log_add (log_Debug, "Using '%s' as base content dir.", baseContentPath); mountContentDir (repository, baseContentPath, addons); } void prepareConfigDir (const char *configDirName) { char buf[PATH_MAX]; static uio_AutoMount *autoMount[] = { NULL }; uio_MountHandle *contentHandle; if (configDirName == NULL) { configDirName = getenv("UQM_CONFIG_DIR"); if (configDirName == NULL) configDirName = CONFIGDIR; } if (expandPath (buf, PATH_MAX - 13, configDirName, EP_ALL_SYSTEM) == -1) { // Doesn't have to be fatal, but might mess up things when saving // config files. log_add (log_Fatal, "Fatal error: Invalid path to config files."); exit (EXIT_FAILURE); } configDirName = buf; log_add (log_Debug, "Using config dir '%s'", configDirName); // Set the environment variable UQM_CONFIG_DIR so UQM_MELEE_DIR // and UQM_SAVE_DIR can refer to it. setenv("UQM_CONFIG_DIR", configDirName, 1); // Create the path upto the config dir, if not already existing. if (mkdirhier (configDirName) == -1) exit (EXIT_FAILURE); contentHandle = uio_mountDir (repository, "/", uio_FSTYPE_STDIO, NULL, NULL, configDirName, autoMount, uio_MOUNT_TOP, NULL); if (contentHandle == NULL) { log_add (log_Fatal, "Fatal error: Could not mount config dir: %s", strerror (errno)); exit (EXIT_FAILURE); } configDir = uio_openDir (repository, "/", 0); if (configDir == NULL) { log_add (log_Fatal, "Fatal error: Could not open config dir: %s", strerror (errno)); exit (EXIT_FAILURE); } } void prepareSaveDir (void) { char buf[PATH_MAX]; const char *saveDirName; saveDirName = getenv("UQM_SAVE_DIR"); if (saveDirName == NULL) saveDirName = SAVEDIR; if (expandPath (buf, PATH_MAX - 13, saveDirName, EP_ALL_SYSTEM) == -1) { // Doesn't have to be fatal, but might mess up things when saving // config files. log_add (log_Fatal, "Fatal error: Invalid path to config files."); exit (EXIT_FAILURE); } saveDirName = buf; setenv("UQM_SAVE_DIR", saveDirName, 1); // Create the path upto the save dir, if not already existing. if (mkdirhier (saveDirName) == -1) exit (EXIT_FAILURE); log_add (log_Debug, "Saved games are kept in %s.", saveDirName); saveDir = uio_openDirRelative (configDir, "save", 0); // TODO: this doesn't work if the save dir is not // "save" in the config dir. if (saveDir == NULL) { log_add (log_Fatal, "Fatal error: Could not open save dir: %s", strerror (errno)); exit (EXIT_FAILURE); } } void prepareMeleeDir (void) { char buf[PATH_MAX]; const char *meleeDirName; meleeDirName = getenv("UQM_MELEE_DIR"); if (meleeDirName == NULL) meleeDirName = MELEEDIR; if (expandPath (buf, PATH_MAX - 13, meleeDirName, EP_ALL_SYSTEM) == -1) { // Doesn't have to be fatal, but might mess up things when saving // config files. log_add (log_Fatal, "Fatal error: Invalid path to config files."); exit (EXIT_FAILURE); } meleeDirName = buf; setenv("UQM_MELEE_DIR", meleeDirName, 1); // Create the path upto the save dir, if not already existing. if (mkdirhier (meleeDirName) == -1) exit (EXIT_FAILURE); meleeDir = uio_openDirRelative (configDir, "teams", 0); // TODO: this doesn't work if the save dir is not // "teams" in the config dir. if (meleeDir == NULL) { log_add (log_Fatal, "Fatal error: Could not open melee teams dir: %s", strerror (errno)); exit (EXIT_FAILURE); } } static void mountContentDir (uio_Repository *repository, const char *contentPath, const char **addons) { uio_MountHandle *contentHandle; uio_DirHandle *packagesDir, *addonsDir, *addonDir; static uio_AutoMount *autoMount[] = { NULL }; availableAddons = NULL; contentHandle = uio_mountDir (repository, "/", uio_FSTYPE_STDIO, NULL, NULL, contentPath, autoMount, uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL); if (contentHandle == NULL) { log_add (log_Fatal, "Fatal error: Could not mount content dir: %s", strerror (errno)); exit (EXIT_FAILURE); } contentDir = uio_openDir (repository, "/", 0); if (contentDir == NULL) { log_add (log_Fatal, "Fatal error: Could not open content dir: %s", strerror (errno)); exit (EXIT_FAILURE); } packagesDir = uio_openDir (repository, "/packages", 0); if (packagesDir == NULL) { // No packages dir means no packages to load. if (addons[0] != NULL) { // addons were specified, but there's no /packages dir, // let alone a /packages/addons dir. log_add (log_Error, "Warning: There's no 'packages/addons' " "directory in the 'content' directory;\n\t'--addon' " "options are ignored."); } return; } mountDirZips (contentHandle, packagesDir); // NB: note the difference between addonsDir and addonDir. // the former is the dir 'packages/addons', the latter a directory // in that dir. addonsDir = uio_openDirRelative (packagesDir, "addons", 0); if (addonsDir == NULL) { // No addon dir found. log_add (log_Error, "Warning: There's no 'packages/addons' " "directory in the 'content' directory;\n\t'--addon' " "options are ignored."); uio_closeDir (packagesDir); return; } uio_closeDir (packagesDir); availableAddons = uio_getDirList (addonsDir, "", "", match_MATCH_PREFIX); if (availableAddons != NULL) { int i, count; count = availableAddons->numNames; if (count != 1) { log_add (log_Info, "%d available addon packs.", count); } else { log_add (log_Info, "1 available addon pack."); } for (i = 0; i < count; i++) { log_add (log_Info, " %d. %s", i+1, availableAddons->names[i]); } } else { log_add (log_Info, "0 available addon packs."); } for (; *addons != NULL; addons++) { addonDir = uio_openDirRelative (addonsDir, *addons, 0); if (addonDir == NULL) { log_add (log_Error, "Warning: directory 'packages/addons/%s' " "not found; addon skipped.", *addons); continue; } mountDirZips (contentHandle, addonDir); uio_closeDir (addonDir); } uio_closeDir (addonsDir); } static void mountDirZips (uio_MountHandle *contentHandle, uio_DirHandle *dirHandle) { static uio_AutoMount *autoMount[] = { NULL }; uio_DirList *dirList; dirList = uio_getDirList (dirHandle, "", ".(zip|uqm)$", match_MATCH_REGEX); if (dirList != NULL) { int i; for (i = 0; i < dirList->numNames; i++) { if (uio_mountDir (repository, "/", uio_FSTYPE_ZIP, dirHandle, dirList->names[i], "/", autoMount, uio_MOUNT_BELOW | uio_MOUNT_RDONLY, contentHandle) == NULL) { log_add (log_Error, "Warning: Could not mount '%s': %s.", dirList->names[i], strerror (errno)); } } } uio_DirList_free (dirList); } uqm-0.6.2/sc2/src/Makeinfo0000600000175000017500000000036710543202107013741 0ustar joeyjoeyuqm_SUBDIRS="sc2code getopt res" case "$HOST_SYSTEM" in Darwin) uqm_SUBDIRS="$uqm_SUBDIRS darwin" ;; esac if [ "$uqm_HAVE_REGEX" = 0 ]; then uqm_SUBDIRS="$uqm_SUBDIRS regex" fi uqm_CFILES="options.c port.c starcon2.c" test_CFILES=test.c uqm-0.6.2/sc2/src/config.h0000600000175000017500000000123310543202107013674 0ustar joeyjoey/* This file contains some compile-time configuration options. */ #ifdef _MSC_VER /* In this case, build.sh is not run to generate a config file, so * we use a default file msvc++/config.h instead. * If you want anything else than the defaults, you'll have to edit * that file manually. */ # include "msvc++/config.h" #elif defined (__MINGW32__) || defined (__CYGWIN__) /* If we're compiling on MS Windows using build.sh, use * config_win.h, generated from * src/config_win.h.in. */ # include "config_win.h" #else /* If we're compiling in unix, use config_unix.h, generated from * src/config_unix.h.in by build.sh. */ # include "config_unix.h" #endif uqm-0.6.2/sc2/src/endian_uqm.h0000600000175000017500000000717410543202107014561 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Endian swapping, taken from SDL-1.2.5 sources and modified * Original copyright (C) Sam Lantinga */ #ifndef _ENDIAN_UQM_H #define _ENDIAN_UQM_H #include "config.h" #include "types.h" #if defined (__APPLE__) && defined (__GNUC__) // When using the MacOS gcc compiler to build universal binaries, // each file will be compiled once for each platform. // This means that checking endianness beforehand from build.sh will not do, // but fortunately, gcc defines __BIG_ENDIAN__ or __LITTLE_ENDIAN__ on // this platform. # if defined(__BIG_ENDIAN__) # undef WORDS_BIGENDIAN # define WORDS_BIGENDIAN # elif defined(__LITTLE_ENDIAN__) # undef WORDS_BIGENDIAN # else // Neither __BIG_ENDIAN__ nor __LITTLE_ENDIAN__ is defined. // Fallback to using the build.sh defined value. # endif #endif /* __APPLE__ */ #if defined(_MSC_VER) || defined(__BORLANDC__) || \ defined(__DMC__) || defined(__SC__) || \ defined(__WATCOMC__) || defined(__LCC__) #ifndef __inline__ #define __inline__ __inline #endif #endif /* The macros used to swap values */ /* Try to use superfast macros on systems that support them */ #ifdef linux #include #ifdef __arch__swab16 #define UQM_Swap16 __arch__swab16 #endif #ifdef __arch__swab32 #define UQM_Swap32 __arch__swab32 #endif #endif /* linux */ /* Use inline functions for compilers that support them, and static functions for those that do not. Because these functions become static for compilers that do not support inline functions, this header should only be included in files that actually use them. */ #ifndef UQM_Swap16 static __inline__ uint16 UQM_Swap16(uint16 D) { return((D<<8)|(D>>8)); } #endif #ifndef UQM_Swap32 static __inline__ uint32 UQM_Swap32(uint32 D) { return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24)); } #endif #ifdef UQM_INT64 #ifndef UQM_Swap64 static __inline__ uint64 UQM_Swap64(uint64 val) { uint32 hi, lo; /* Separate into high and low 32-bit values and swap them */ lo = (uint32)(val&0xFFFFFFFF); val >>= 32; hi = (uint32)(val&0xFFFFFFFF); val = UQM_Swap32(lo); val <<= 32; val |= UQM_Swap32(hi); return(val); } #endif #else #ifndef UQM_Swap64 /* This is mainly to keep compilers from complaining in SDL code. If there is no real 64-bit datatype, then compilers will complain about the fake 64-bit datatype that SDL provides when it compiles user code. */ #define UQM_Swap64(X) (X) #endif #endif /* UQM_INT64 */ /* Byteswap item from the specified endianness to the native endianness */ #ifndef WORDS_BIGENDIAN #define UQM_SwapLE16(X) (X) #define UQM_SwapLE32(X) (X) #define UQM_SwapLE64(X) (X) #define UQM_SwapBE16(X) UQM_Swap16(X) #define UQM_SwapBE32(X) UQM_Swap32(X) #define UQM_SwapBE64(X) UQM_Swap64(X) #else #define UQM_SwapLE16(X) UQM_Swap16(X) #define UQM_SwapLE32(X) UQM_Swap32(X) #define UQM_SwapLE64(X) UQM_Swap64(X) #define UQM_SwapBE16(X) (X) #define UQM_SwapBE32(X) (X) #define UQM_SwapBE64(X) (X) #endif #endif /* _ENDIAN_H */ uqm-0.6.2/sc2/src/msvc++/0000755000175000017500000000000010552600273013373 5ustar joeyjoeyuqm-0.6.2/sc2/src/msvc++/UrQuanMasters.dsp0000600000175000017500000027535410543202106016656 0ustar joeyjoey# Microsoft Developer Studio Project File - Name="UrQuanMasters" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=UrQuanMasters - Win32 Debug NoAccel !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "UrQuanMasters.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "UrQuanMasters.mak" CFG="UrQuanMasters - Win32 Debug NoAccel" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "UrQuanMasters - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "UrQuanMasters - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "UrQuanMasters - Win32 Debug NoAccel" (based on "Win32 (x86) Console Application") !MESSAGE "UrQuanMasters - Win32 Release NoAccel" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "UrQuanMasters - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "." /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /I "..\regex" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D "HAVE_OPENGL" /D "GFXMODULE_SDL" /D "HAVE_OPENAL" /D "HAVE_ZIP" /D "HAVE_JOYSTICK" /D "NETPLAY" /D "ZLIB_DLL" /D "USE_INTERNAL_MIKMOD" /D "USE_PLATFORM_ACCEL" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib zdll.lib ws2_32.lib /nologo /subsystem:windows /pdb:none /debug /machine:I386 /nodefaultlib:"msvcrtd.lib" /out:"../../uqm.exe" # Begin Special Build Tool SOURCE="$(InputPath)" PostBuild_Desc=Stripping debug info... PostBuild_Cmds=rebase -b 0x400000 -x . "../../uqm.exe" # End Special Build Tool !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "." /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /I "..\regex" /D "DEBUG" /D "_DEBUG" /D "DEBUG_TRACK_SEM" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D "HAVE_OPENGL" /D "GFXMODULE_SDL" /D "HAVE_OPENAL" /D "HAVE_ZIP" /D "HAVE_JOYSTICK" /D "NETPLAY" /D "ZLIB_DLL" /D "USE_INTERNAL_MIKMOD" /D "USE_PLATFORM_ACCEL" /FR /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo /o"UrQuanMasters.bsc" LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib zdll.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"../../uqmdebug.exe" /pdbtype:sept # SUBTRACT LINK32 /nodefaultlib !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Debug NoAccel" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug_NoAccel" # PROP BASE Intermediate_Dir "Debug_NoAccel" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug_NoAccel" # PROP Intermediate_Dir "Debug_NoAccel" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /I "." /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /I "..\regex" /D "DEBUG" /D "_DEBUG" /D "DEBUG_TRACK_SEM" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D "HAVE_OPENGL" /D "GFXMODULE_SDL" /D "HAVE_OPENAL" /D "HAVE_ZIP" /D "ZLIB_DLL" /D "USE_PLATFORM_ACCEL" /FR /FD /GZ /c # SUBTRACT BASE CPP /YX # ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "." /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /I "..\regex" /D "DEBUG" /D "_DEBUG" /D "DEBUG_TRACK_SEM" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D "HAVE_OPENGL" /D "GFXMODULE_SDL" /D "HAVE_OPENAL" /D "HAVE_ZIP" /D "HAVE_JOYSTICK" /D "NETPLAY" /D "ZLIB_DLL" /D "USE_INTERNAL_MIKMOD" /FR /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo /o"UrQuanMasters.bsc" # ADD BSC32 /nologo /o"UrQuanMasters.bsc" LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib zdll.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"../../uqmdebug.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib zdll.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"../../uqmdebug.exe" /pdbtype:sept # SUBTRACT LINK32 /nodefaultlib !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Release NoAccel" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release_NoAccel" # PROP BASE Intermediate_Dir "Release_NoAccel" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release_NoAccel" # PROP Intermediate_Dir "Release_NoAccel" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /Zi /O2 /I "." /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /I "..\regex" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D "HAVE_OPENGL" /D "GFXMODULE_SDL" /D "HAVE_OPENAL" /D "HAVE_ZIP" /D "ZLIB_DLL" /D "USE_PLATFORM_ACCEL" /FD /c # SUBTRACT BASE CPP /YX # ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "." /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /I "..\regex" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D "HAVE_OPENGL" /D "GFXMODULE_SDL" /D "HAVE_OPENAL" /D "HAVE_ZIP" /D "HAVE_JOYSTICK" /D "NETPLAY" /D "ZLIB_DLL" /D "USE_INTERNAL_MIKMOD" /FR /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib zdll.lib ws2_32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"msvcrtd.lib" /out:"../../uqm.exe" # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib zdll.lib ws2_32.lib /nologo /subsystem:windows /pdb:none /debug /machine:I386 /nodefaultlib:"msvcrtd.lib" /out:"../../uqm.exe" # Begin Special Build Tool SOURCE="$(InputPath)" PostBuild_Desc=Stripping debug info... PostBuild_Cmds=rebase -b 0x400000 -x . "../../uqm.exe" # End Special Build Tool !ENDIF # Begin Target # Name "UrQuanMasters - Win32 Release" # Name "UrQuanMasters - Win32 Debug" # Name "UrQuanMasters - Win32 Debug NoAccel" # Name "UrQuanMasters - Win32 Release NoAccel" # Begin Group "Source Files" # PROP Default_Filter "" # Begin Group "getopt" # PROP Default_Filter "" # Begin Source File SOURCE=..\getopt\getopt.c # End Source File # Begin Source File SOURCE=..\getopt\getopt.h # End Source File # Begin Source File SOURCE=..\getopt\getopt1.c # End Source File # End Group # Begin Group "regex" # PROP Default_Filter "" # Begin Source File SOURCE=..\regex\regcomp.ci # End Source File # Begin Source File SOURCE=..\regex\regex.c # End Source File # Begin Source File SOURCE=..\regex\regex.h # End Source File # Begin Source File SOURCE=..\regex\regex_internal.ci # End Source File # Begin Source File SOURCE=..\regex\regex_internal.h # End Source File # Begin Source File SOURCE=..\regex\regexec.ci # End Source File # End Group # Begin Group "sc2code" # PROP Default_Filter "" # Begin Group "libs" # PROP Default_Filter "" # Begin Group "callback" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\callback\alarm.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\callback\alarm.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\callback\callback.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\callback\callback.h # End Source File # End Group # Begin Group "decomp" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\decomp\lzdecode.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\decomp\lzencode.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\decomp\lzh.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\decomp\update.c # End Source File # End Group # Begin Group "file" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\file\dirs.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\file\files.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\file\filintrn.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\file\temp.c # End Source File # End Group # Begin Group "graphics" # PROP Default_Filter "" # Begin Group "sdl" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\2xscalers.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\2xscalers.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\2xscalers_3dnow.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\2xscalers_mmx.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\2xscalers_mmx.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\2xscalers_sse.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\3do_blt.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\3do_funcs.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\3do_getbody.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\bbox.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\bbox.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\biadv2x.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\bilinear2x.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\canvas.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\dcqueue.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\hq2x.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\nearest2x.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\opengl.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\opengl.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\primitives.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\primitives.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\pure.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\pure.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\rndzoom.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\rotozoom.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\rotozoom.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\scaleint.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\scalemmx.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\scalers.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\scalers.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\sdl_common.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\sdl_common.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\sdluio.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\sdluio.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\sdl\triscan2x.c # End Source File # End Group # Begin Source File SOURCE=..\sc2code\libs\graphics\boxint.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\clipline.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\cmap.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\cmap.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\context.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\context.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\display.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\drawable.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\drawable.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\drawcmd.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\filegfx.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\font.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\font.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\frame.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\gfx_common.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\gfx_common.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\gfxintrn.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\gfxother.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\intersec.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\loaddisp.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\pixmap.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\prim.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\resgfx.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\tfb_draw.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\tfb_draw.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\tfb_prim.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\tfb_prim.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\widgets.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\graphics\widgets.h # End Source File # End Group # Begin Group "heap" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\heap\heap.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\heap\heap.h # End Source File # End Group # Begin Group "input" # PROP Default_Filter "" # Begin Group "sdl No. 1" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\input\sdl\input.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\input\sdl\input.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\input\sdl\keynames.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\input\sdl\keynames.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\input\sdl\vcontrol.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\input\sdl\vcontrol.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\input\sdl\vcontrol_malloc.h # End Source File # End Group # Begin Source File SOURCE=..\sc2code\libs\input\inpintrn.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\input\input_common.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\input\input_common.h # End Source File # End Group # Begin Group "list" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\list\list.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\list\list.h # End Source File # End Group # Begin Group "log" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\log\uqmlog.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\log\uqmlog.h # End Source File # End Group # Begin Group "math" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\math\mthintrn.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\math\random.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\math\random.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\math\sqrt.c # End Source File # End Group # Begin Group "memory" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\memory\w_memlib.c # End Source File # End Group # Begin Group "resource" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\resource\alist.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\alist.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\direct.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\filecntl.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\getres.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\index.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\loadres.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\mapres.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\resdata.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\resinit.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\resintrn.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\stringbank.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\resource\stringbank.h # End Source File # End Group # Begin Group "sound" # PROP Default_Filter "" # Begin Group "openal" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\sound\openal\audiodrv_openal.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\openal\audiodrv_openal.h # End Source File # End Group # Begin Group "decoders" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\sound\decoders\decoder.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\decoders\decoder.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\decoders\dukaud.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\decoders\dukaud.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\decoders\modaud.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\decoders\modaud.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\decoders\oggaud.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\decoders\oggaud.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\decoders\wav.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\decoders\wav.h # End Source File # End Group # Begin Group "mixer" # PROP Default_Filter "" # Begin Group "mixsdl" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\sound\mixer\sdl\audiodrv_sdl.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\mixer\sdl\audiodrv_sdl.h # End Source File # End Group # Begin Group "nosound" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\sound\mixer\nosound\audiodrv_nosound.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\mixer\nosound\audiodrv_nosound.h # End Source File # End Group # Begin Source File SOURCE=..\sc2code\libs\sound\mixer\mixer.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\mixer\mixer.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\mixer\mixerint.h # End Source File # End Group # Begin Source File SOURCE=..\sc2code\libs\sound\audiocore.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\audiocore.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\fileinst.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\music.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\resinst.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\sfx.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\sndintrn.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\sound.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\sound.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\stream.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\stream.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\trackint.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\trackplayer.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\sound\trackplayer.h # End Source File # End Group # Begin Group "strings" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\strings\getstr.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\strings\sfileins.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\strings\sresins.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\strings\strings.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\strings\strintrn.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\strings\unicode.c # End Source File # End Group # Begin Group "video" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\video\dukvid.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\video\dukvid.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\video\vfileins.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\video\video.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\video\video.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\video\videodec.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\video\videodec.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\video\vidplayer.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\video\vidplayer.h # End Source File # End Group # Begin Group "threads" # PROP Default_Filter "" # Begin Group "sdl No. 3" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\threads\sdl\sdlthreads.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\threads\sdl\sdlthreads.h # End Source File # End Group # Begin Source File SOURCE=..\sc2code\libs\threads\thrcommon.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\threads\thrcommon.h # End Source File # End Group # Begin Group "time" # PROP Default_Filter "" # Begin Group "sdl No. 4" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\time\sdl\sdltime.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\time\sdl\sdltime.h # End Source File # End Group # Begin Source File SOURCE=..\sc2code\libs\time\timecommon.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\time\timecommon.h # End Source File # End Group # Begin Group "task" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\task\tasklib.c # End Source File # End Group # Begin Group "uio" # PROP Default_Filter "" # Begin Group "stdio" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\uio\stdio\stdio.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\stdio\stdio.h # End Source File # End Group # Begin Group "zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\uio\zip\zip.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\zip\zip.h # End Source File # End Group # Begin Source File SOURCE=..\sc2code\libs\uio\charhashtable.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\charhashtable.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\debug.c !IF "$(CFG)" == "UrQuanMasters - Win32 Release" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Debug" !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Debug NoAccel" !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Release NoAccel" # PROP BASE Exclude_From_Build 1 # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\debug.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\defaultfs.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\defaultfs.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\fileblock.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\fileblock.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\fstypes.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\fstypes.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\gphys.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\gphys.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\hashtable.c !IF "$(CFG)" == "UrQuanMasters - Win32 Release" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Debug" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Debug NoAccel" # PROP BASE Exclude_From_Build 1 # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Release NoAccel" # PROP BASE Exclude_From_Build 1 # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\hashtable.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\io.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\io.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\ioaux.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\ioaux.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\iointrn.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\match.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\match.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\mem.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\memdebug.c !IF "$(CFG)" == "UrQuanMasters - Win32 Release" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Debug" # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Debug NoAccel" # PROP BASE Exclude_From_Build 1 # PROP Exclude_From_Build 1 !ELSEIF "$(CFG)" == "UrQuanMasters - Win32 Release NoAccel" # PROP BASE Exclude_From_Build 1 # PROP Exclude_From_Build 1 !ENDIF # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\memdebug.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\mount.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\mount.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\mounttree.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\mounttree.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\paths.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\paths.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\physical.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\physical.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\types.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\uioport.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\uiostream.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\uiostream.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\uioutils.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\uioutils.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\utils.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio\utils.h # End Source File # End Group # Begin Group "mikmod" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\mikmod\drv_nos.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\load_it.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\load_mod.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\load_s3m.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\load_stm.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\load_xm.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mdreg.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mdriver.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mikmod.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mikmod_build.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mikmod_internals.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mloader.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mlreg.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mlutil.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mmalloc.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mmerror.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mmio.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mplayer.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\munitrk.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\mwav.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\npertab.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\sloader.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\virtch.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\virtch2.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\mikmod\virtch_common.c # End Source File # End Group # Begin Group "network" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\network\bytesex.h # End Source File # Begin Group "connect" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\network\connect\connect.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\connect\connect.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\connect\listen.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\connect\listen.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\connect\resolve.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\connect\resolve.h # End Source File # End Group # Begin Group "netmanager" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\network\netmanager\ndesc.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\netmanager\ndesc.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\netmanager\ndindex.ci # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\netmanager\netmanager_common.ci # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\netmanager\netmanager.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\netmanager\netmanager_win.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\netmanager\netmanager_win.h # End Source File # End Group # Begin Source File SOURCE=..\sc2code\libs\network\netport.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\netport.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\network_win.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\network.h # End Source File # Begin Group "socket" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\libs\network\socket\socket.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\socket\socket.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\socket\socket_win.c # End Source File # Begin Source File SOURCE=..\sc2code\libs\network\socket\socket_win.h # End Source File # End Group # Begin Source File SOURCE=..\sc2code\libs\network\wspiapiwrap.h # End Source File # End Group # Begin Source File SOURCE=..\sc2code\libs\alarm.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\callback.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\compiler.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\declib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\file.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\gfxlib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\heap.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\inplib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\list.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\log.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\mathlib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\memlib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\misc.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\net.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\platform.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\reslib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\sndlib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\strlib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\tasklib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\threadlib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\timelib.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\uio.h # End Source File # Begin Source File SOURCE=..\sc2code\libs\vidlib.h # End Source File # End Group # Begin Group "comm" # PROP Default_Filter "" # Begin Group "arilou.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\arilou\arilouc.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\arilou\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\arilou\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\arilou\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\arilou\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\arilou\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\arilou\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\arilou\strings.h # End Source File # End Group # Begin Group "blackur.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\blackur\blackurc.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\blackur\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\blackur\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\blackur\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\blackur\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\blackur\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\blackur\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\blackur\strings.h # End Source File # End Group # Begin Group "chmmr.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\chmmr\chmmrc.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\chmmr\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\chmmr\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\chmmr\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\chmmr\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\chmmr\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\chmmr\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\chmmr\strings.h # End Source File # End Group # Begin Group "comandr.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\comandr\comandr.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\comandr\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\comandr\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\comandr\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\comandr\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\comandr\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\comandr\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\comandr\strings.h # End Source File # End Group # Begin Group "druuge.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\druuge\druugec.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\druuge\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\druuge\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\druuge\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\druuge\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\druuge\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\druuge\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\druuge\strings.h # End Source File # End Group # Begin Group "ilwrath.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\ilwrath\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\ilwrath\ilwrathc.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\ilwrath\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\ilwrath\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\ilwrath\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\ilwrath\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\ilwrath\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\ilwrath\strings.h # End Source File # End Group # Begin Group "melnorm.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\melnorm\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\melnorm\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\melnorm\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\melnorm\melnorm.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\melnorm\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\melnorm\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\melnorm\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\melnorm\strings.h # End Source File # End Group # Begin Group "mycon.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\mycon\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\mycon\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\mycon\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\mycon\myconc.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\mycon\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\mycon\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\mycon\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\mycon\strings.h # End Source File # End Group # Begin Group "orz.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\orz\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\orz\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\orz\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\orz\orzc.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\orz\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\orz\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\orz\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\orz\strings.h # End Source File # End Group # Begin Group "pkunk.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\pkunk\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\pkunk\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\pkunk\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\pkunk\pkunkc.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\pkunk\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\pkunk\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\pkunk\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\pkunk\strings.h # End Source File # End Group # Begin Group "rebel.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\rebel\rebel.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\rebel\strings.h # End Source File # End Group # Begin Group "shofixt.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\shofixt\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\shofixt\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\shofixt\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\shofixt\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\shofixt\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\shofixt\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\shofixt\shofixt.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\shofixt\strings.h # End Source File # End Group # Begin Group "slyhome.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\slyhome\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyhome\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyhome\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyhome\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyhome\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyhome\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyhome\slyhome.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyhome\strings.h # End Source File # End Group # Begin Group "slyland.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\slyland\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyland\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyland\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyland\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyland\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyland\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyland\slyland.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\slyland\strings.h # End Source File # End Group # Begin Group "spahome.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\spahome\spahome.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\spahome\strings.h # End Source File # End Group # Begin Group "spathi.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\spathi\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\spathi\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\spathi\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\spathi\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\spathi\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\spathi\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\spathi\spathic.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\spathi\strings.h # End Source File # End Group # Begin Group "starbas.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\starbas\starbas.c # End Source File # Begin Source File SOURCE=..\sc2code\comm\starbas\strings.h # End Source File # End Group # Begin Group "supox.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\supox\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\supox\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\supox\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\supox\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\supox\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\supox\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\supox\strings.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\supox\supoxc.c # End Source File # End Group # Begin Group "syreen.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\syreen\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\syreen\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\syreen\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\syreen\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\syreen\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\syreen\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\syreen\strings.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\syreen\syreenc.c # End Source File # End Group # Begin Group "talkpet.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\talkpet\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\talkpet\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\talkpet\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\talkpet\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\talkpet\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\talkpet\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\talkpet\strings.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\talkpet\talkpet.c # End Source File # End Group # Begin Group "thradd.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\thradd\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\thradd\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\thradd\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\thradd\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\thradd\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\thradd\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\thradd\strings.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\thradd\thraddc.c # End Source File # End Group # Begin Group "umgah.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\umgah\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\umgah\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\umgah\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\umgah\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\umgah\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\umgah\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\umgah\strings.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\umgah\umgahc.c # End Source File # End Group # Begin Group "urquan.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\urquan\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\urquan\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\urquan\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\urquan\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\urquan\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\urquan\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\urquan\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\urquan\strings.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\urquan\urquanc.c # End Source File # End Group # Begin Group "utwig.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\utwig\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\utwig\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\utwig\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\utwig\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\utwig\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\utwig\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\utwig\strings.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\utwig\utwigc.c # End Source File # End Group # Begin Group "vux.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\vux\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\vux\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\vux\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\vux\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\vux\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\vux\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\vux\strings.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\vux\vuxc.c # End Source File # End Group # Begin Group "yehat.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\yehat\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\yehat\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\yehat\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\yehat\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\yehat\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\yehat\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\yehat\strings.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\yehat\yehatc.c # End Source File # End Group # Begin Group "zoqfot.comm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\comm\zoqfot\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\zoqfot\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\zoqfot\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\zoqfot\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\zoqfot\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\zoqfot\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\zoqfot\strings.h # End Source File # Begin Source File SOURCE=..\sc2code\comm\zoqfot\zoqfotc.c # End Source File # End Group # Begin Source File SOURCE=..\sc2code\comm\commall.h # End Source File # End Group # Begin Group "netplay" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\netplay\checksum.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\checksum.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\checkbuf.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\checkbuf.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\crc.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\crc.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\nc_connect.ci # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netconnection.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netconnection.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netinput.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netinput.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netoptions.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netoptions.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netmelee.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netmelee.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netmisc.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netmisc.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netplay.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netrcv.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netrcv.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netsend.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netsend.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netstate.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\netstate.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\notify.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\notify.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\packet.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\packet.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\packethandlers.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\packethandlers.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\packetsenders.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\packetsenders.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\packetq.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\packetq.h # End Source File # Begin Group "proto" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\netplay\proto\npconfirm.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\proto\npconfirm.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\proto\ready.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\proto\ready.h # End Source File # Begin Source File SOURCE=..\sc2code\netplay\proto\reset.c # End Source File # Begin Source File SOURCE=..\sc2code\netplay\proto\reset.h # End Source File # End Group # End Group # Begin Group "planets" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\planets\calc.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\cargo.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\devices.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\elemdata.h # End Source File # Begin Source File SOURCE=..\sc2code\planets\genall.h # End Source File # Begin Source File SOURCE=..\sc2code\planets\genburv.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genchmmr.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\gencol.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\gendru.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genilw.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genmel.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genmyc.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genorz.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genpet.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genpku.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genrain.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\gensam.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genshof.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\gensly.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\gensol.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genspa.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\gensup.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\gensyr.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genthrad.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\gentopo.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genutw.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genvault.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genvux.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genwreck.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genyeh.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\genzoq.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\lander.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\lander.h # End Source File # Begin Source File SOURCE=..\sc2code\planets\lifeform.h # End Source File # Begin Source File SOURCE=..\sc2code\planets\orbits.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\oval.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\pl_stuff.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\plandata.h # End Source File # Begin Source File SOURCE=..\sc2code\planets\planets.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\planets.h # End Source File # Begin Source File SOURCE=..\sc2code\planets\plangen.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\pstarmap.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\report.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\roster.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\scan.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\scan.h # End Source File # Begin Source File SOURCE=..\sc2code\planets\solarsys.c # End Source File # Begin Source File SOURCE=..\sc2code\planets\sundata.h # End Source File # Begin Source File SOURCE=..\sc2code\planets\surface.c # End Source File # End Group # Begin Group "ships" # PROP Default_Filter "" # Begin Group "androsyn" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\androsyn\androsyn.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\androsyn\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\androsyn\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\androsyn\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\androsyn\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\androsyn\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\androsyn\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\androsyn\restypes.h # End Source File # End Group # Begin Group "arilou" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\arilou\arilou.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\arilou\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\arilou\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\arilou\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\arilou\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\arilou\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\arilou\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\arilou\restypes.h # End Source File # End Group # Begin Group "blackurq" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\blackurq\blackurq.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\blackurq\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\blackurq\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\blackurq\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\blackurq\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\blackurq\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\blackurq\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\blackurq\restypes.h # End Source File # End Group # Begin Group "chenjesu" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\chenjesu\chenjesu.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\chenjesu\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chenjesu\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chenjesu\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chenjesu\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chenjesu\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chenjesu\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chenjesu\restypes.h # End Source File # End Group # Begin Group "chmmr" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\chmmr\chmmr.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\chmmr\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chmmr\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chmmr\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chmmr\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chmmr\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chmmr\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\chmmr\restypes.h # End Source File # End Group # Begin Group "druuge" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\druuge\druuge.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\druuge\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\druuge\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\druuge\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\druuge\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\druuge\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\druuge\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\druuge\restypes.h # End Source File # End Group # Begin Group "human" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\human\human.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\human\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\human\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\human\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\human\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\human\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\human\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\human\restypes.h # End Source File # End Group # Begin Group "ilwrath" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\ilwrath\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\ilwrath\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\ilwrath\ilwrath.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\ilwrath\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\ilwrath\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\ilwrath\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\ilwrath\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\ilwrath\restypes.h # End Source File # End Group # Begin Group "lastbat" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\lastbat\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\lastbat\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\lastbat\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\lastbat\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\lastbat\lastbat.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\lastbat\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\lastbat\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\lastbat\restypes.h # End Source File # End Group # Begin Group "melnorme" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\melnorme\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\melnorme\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\melnorme\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\melnorme\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\melnorme\melnorme.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\melnorme\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\melnorme\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\melnorme\restypes.h # End Source File # End Group # Begin Group "mmrnmhrm" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\mmrnmhrm\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mmrnmhrm\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mmrnmhrm\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mmrnmhrm\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mmrnmhrm\mmrnmhrm.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\mmrnmhrm\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mmrnmhrm\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mmrnmhrm\restypes.h # End Source File # End Group # Begin Group "mycon" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\mycon\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mycon\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mycon\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mycon\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mycon\mycon.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\mycon\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mycon\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\mycon\restypes.h # End Source File # End Group # Begin Group "orz" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\orz\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\orz\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\orz\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\orz\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\orz\orz.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\orz\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\orz\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\orz\restypes.h # End Source File # End Group # Begin Group "pkunk" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\pkunk\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\pkunk\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\pkunk\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\pkunk\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\pkunk\pkunk.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\pkunk\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\pkunk\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\pkunk\restypes.h # End Source File # End Group # Begin Group "probe" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\probe\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\probe\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\probe\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\probe\probe.c # End Source File # Begin Source File SOURCE=..\sc2code\ships\probe\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\probe\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\probe\restypes.h # End Source File # End Group # Begin Group "shofixti" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\shofixti\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\shofixti\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\shofixti\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\shofixti\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\shofixti\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\shofixti\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\shofixti\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\shofixti\shofixti.c # End Source File # End Group # Begin Group "sis_ship" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\sis_ship\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\sis_ship\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\sis_ship\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\sis_ship\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\sis_ship\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\sis_ship\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\sis_ship\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\sis_ship\sis_ship.c # End Source File # End Group # Begin Group "slylandr" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\slylandr\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\slylandr\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\slylandr\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\slylandr\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\slylandr\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\slylandr\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\slylandr\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\slylandr\slylandr.c # End Source File # End Group # Begin Group "spathi" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\spathi\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\spathi\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\spathi\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\spathi\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\spathi\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\spathi\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\spathi\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\spathi\spathi.c # End Source File # End Group # Begin Group "supox" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\supox\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\supox\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\supox\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\supox\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\supox\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\supox\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\supox\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\supox\supox.c # End Source File # End Group # Begin Group "syreen" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\syreen\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\syreen\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\syreen\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\syreen\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\syreen\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\syreen\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\syreen\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\syreen\syreen.c # End Source File # End Group # Begin Group "thradd" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\thradd\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\thradd\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\thradd\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\thradd\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\thradd\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\thradd\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\thradd\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\thradd\thradd.c # End Source File # End Group # Begin Group "umgah" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\umgah\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\umgah\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\umgah\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\umgah\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\umgah\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\umgah\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\umgah\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\umgah\umgah.c # End Source File # End Group # Begin Group "urquan" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\urquan\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\urquan\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\urquan\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\urquan\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\urquan\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\urquan\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\urquan\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\urquan\urquan.c # End Source File # End Group # Begin Group "utwig" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\utwig\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\utwig\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\utwig\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\utwig\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\utwig\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\utwig\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\utwig\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\utwig\utwig.c # End Source File # End Group # Begin Group "vux" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\vux\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\vux\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\vux\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\vux\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\vux\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\vux\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\vux\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\vux\vux.c # End Source File # End Group # Begin Group "yehat" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\yehat\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\yehat\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\yehat\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\yehat\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\yehat\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\yehat\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\yehat\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\yehat\yehat.c # End Source File # End Group # Begin Group "zoqfot" # PROP Default_Filter "" # Begin Source File SOURCE=..\sc2code\ships\zoqfot\icode.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\zoqfot\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\zoqfot\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\zoqfot\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\zoqfot\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\zoqfot\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\zoqfot\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\ships\zoqfot\zoqfot.c # End Source File # End Group # Begin Source File SOURCE=..\sc2code\ships\ship.h # End Source File # End Group # Begin Source File SOURCE=..\sc2code\battle.c # End Source File # Begin Source File SOURCE=..\sc2code\battle.h # End Source File # Begin Source File SOURCE=..\sc2code\border.c # End Source File # Begin Source File SOURCE=..\sc2code\build.c # End Source File # Begin Source File SOURCE=..\sc2code\build.h # End Source File # Begin Source File SOURCE=..\sc2code\cleanup.c # End Source File # Begin Source File SOURCE=..\sc2code\clock.c # End Source File # Begin Source File SOURCE=..\sc2code\clock.h # End Source File # Begin Source File SOURCE=..\sc2code\cnctdlg.c # End Source File # Begin Source File SOURCE=..\sc2code\cnctdlg.h # End Source File # Begin Source File SOURCE=..\sc2code\coderes.h # End Source File # Begin Source File SOURCE=..\sc2code\collide.c # End Source File # Begin Source File SOURCE=..\sc2code\collide.h # End Source File # Begin Source File SOURCE=..\sc2code\colors.h # End Source File # Begin Source File SOURCE=..\sc2code\comm.c # End Source File # Begin Source File SOURCE=..\sc2code\comm.h # End Source File # Begin Source File SOURCE=..\sc2code\commanim.c # End Source File # Begin Source File SOURCE=..\sc2code\commanim.h # End Source File # Begin Source File SOURCE=..\sc2code\commglue.c # End Source File # Begin Source File SOURCE=..\sc2code\commglue.h # End Source File # Begin Source File SOURCE=..\sc2code\confirm.c # End Source File # Begin Source File SOURCE=..\sc2code\controls.h # End Source File # Begin Source File SOURCE=..\sc2code\credits.c # End Source File # Begin Source File SOURCE=..\sc2code\credits.h # End Source File # Begin Source File SOURCE=..\sc2code\cyborg.c # End Source File # Begin Source File SOURCE=..\sc2code\demo.h # End Source File # Begin Source File SOURCE=..\sc2code\displist.c # End Source File # Begin Source File SOURCE=..\sc2code\displist.h # End Source File # Begin Source File SOURCE=..\sc2code\dummy.c # End Source File # Begin Source File SOURCE=..\sc2code\element.h # End Source File # Begin Source File SOURCE=..\sc2code\encount.c # End Source File # Begin Source File SOURCE=..\sc2code\encount.h # End Source File # Begin Source File SOURCE=..\sc2code\fmv.c # End Source File # Begin Source File SOURCE=..\sc2code\fmv.h # End Source File # Begin Source File SOURCE=..\sc2code\galaxy.c # End Source File # Begin Source File SOURCE=..\sc2code\gameev.c # End Source File # Begin Source File SOURCE=..\sc2code\gameev.h # End Source File # Begin Source File SOURCE=..\sc2code\gameinp.c # End Source File # Begin Source File SOURCE=..\sc2code\gameopt.c # End Source File # Begin Source File SOURCE=..\sc2code\gameopt.h # End Source File # Begin Source File SOURCE=..\sc2code\gamestr.h # End Source File # Begin Source File SOURCE=..\sc2code\gendef.c # End Source File # Begin Source File SOURCE=..\sc2code\getchar.c # End Source File # Begin Source File SOURCE=..\sc2code\globdata.c # End Source File # Begin Source File SOURCE=..\sc2code\globdata.h # End Source File # Begin Source File SOURCE=..\sc2code\gravity.c # End Source File # Begin Source File SOURCE=..\sc2code\gravwell.c # End Source File # Begin Source File SOURCE=..\sc2code\grpinfo.c # End Source File # Begin Source File SOURCE=..\sc2code\hyper.c # End Source File # Begin Source File SOURCE=..\sc2code\hyper.h # End Source File # Begin Source File SOURCE=..\sc2code\ifontres.h # End Source File # Begin Source File SOURCE=..\sc2code\igfxres.h # End Source File # Begin Source File SOURCE=..\sc2code\imusicre.h # End Source File # Begin Source File SOURCE=..\sc2code\init.c # End Source File # Begin Source File SOURCE=..\sc2code\init.h # End Source File # Begin Source File SOURCE=..\sc2code\intel.c # End Source File # Begin Source File SOURCE=..\sc2code\intel.h # End Source File # Begin Source File SOURCE=..\sc2code\intro.c # End Source File # Begin Source File SOURCE=..\sc2code\ipdisp.c # End Source File # Begin Source File SOURCE=..\sc2code\ires_ind.h # End Source File # Begin Source File SOURCE=..\sc2code\istrtab.h # End Source File # Begin Source File SOURCE=..\sc2code\load.c # End Source File # Begin Source File SOURCE=..\sc2code\load.h # End Source File # Begin Source File SOURCE=..\sc2code\loadship.c # End Source File # Begin Source File SOURCE=..\sc2code\master.c # End Source File # Begin Source File SOURCE=..\sc2code\master.h # End Source File # Begin Source File SOURCE=..\sc2code\melee.c # End Source File # Begin Source File SOURCE=..\sc2code\melee.h # End Source File # Begin Source File SOURCE=..\sc2code\menu.c # End Source File # Begin Source File SOURCE=..\sc2code\menustat.h # End Source File # Begin Source File SOURCE=..\sc2code\misc.c # End Source File # Begin Source File SOURCE=..\sc2code\mouse_err.c # End Source File # Begin Source File SOURCE=..\sc2code\nameref.h # End Source File # Begin Source File SOURCE=..\sc2code\oscill.c # End Source File # Begin Source File SOURCE=..\sc2code\oscill.h # End Source File # Begin Source File SOURCE=..\sc2code\outfit.c # End Source File # Begin Source File SOURCE=..\sc2code\pickmele.c # End Source File # Begin Source File SOURCE=..\sc2code\pickmele.h # End Source File # Begin Source File SOURCE=..\sc2code\pickship.c # End Source File # Begin Source File SOURCE=..\sc2code\plandata.c # End Source File # Begin Source File SOURCE=..\sc2code\process.c # End Source File # Begin Source File SOURCE=..\sc2code\races.h # End Source File # Begin Source File SOURCE=..\sc2code\resinst.h # End Source File # Begin Source File SOURCE=..\sc2code\respkg.h # End Source File # Begin Source File SOURCE=..\sc2code\restart.c # End Source File # Begin Source File SOURCE=..\sc2code\restart.h # End Source File # Begin Source File SOURCE=..\sc2code\restypes.h # End Source File # Begin Source File SOURCE=..\sc2code\save.c # End Source File # Begin Source File SOURCE=..\sc2code\save.h # End Source File # Begin Source File SOURCE=..\sc2code\settings.c # End Source File # Begin Source File SOURCE=..\sc2code\settings.h # End Source File # Begin Source File SOURCE=..\sc2code\setup.c # End Source File # Begin Source File SOURCE=..\sc2code\setup.h # End Source File # Begin Source File SOURCE=..\sc2code\setupmenu.c # End Source File # Begin Source File SOURCE=..\sc2code\setupmenu.h # End Source File # Begin Source File SOURCE=..\sc2code\ship.c # End Source File # Begin Source File SOURCE=..\sc2code\shipcont.h # End Source File # Begin Source File SOURCE=..\sc2code\shipstat.c # End Source File # Begin Source File SOURCE=..\sc2code\shipyard.c # End Source File # Begin Source File SOURCE=..\sc2code\sis.c # End Source File # Begin Source File SOURCE=..\sc2code\sis.h # End Source File # Begin Source File SOURCE=..\sc2code\sounds.c # End Source File # Begin Source File SOURCE=..\sc2code\sounds.h # End Source File # Begin Source File SOURCE=..\sc2code\starbase.c # End Source File # Begin Source File SOURCE=..\sc2code\starbase.h # End Source File # Begin Source File SOURCE=..\sc2code\starcon.c # End Source File # Begin Source File SOURCE=..\sc2code\starcon.h # End Source File # Begin Source File SOURCE=..\sc2code\starmap.c # End Source File # Begin Source File SOURCE=..\sc2code\state.c # End Source File # Begin Source File SOURCE=..\sc2code\state.h # End Source File # Begin Source File SOURCE=..\sc2code\status.c # End Source File # Begin Source File SOURCE=..\sc2code\tactrans.c # End Source File # Begin Source File SOURCE=..\sc2code\trans.c # End Source File # Begin Source File SOURCE=..\sc2code\units.h # End Source File # Begin Source File SOURCE=..\sc2code\uqmdebug.c # End Source File # Begin Source File SOURCE=..\sc2code\uqmdebug.h # End Source File # Begin Source File SOURCE=..\sc2code\util.c # End Source File # Begin Source File SOURCE=..\sc2code\util.h # End Source File # Begin Source File SOURCE=..\sc2code\velocity.c # End Source File # Begin Source File SOURCE=..\sc2code\velocity.h # End Source File # Begin Source File SOURCE=..\sc2code\weapon.c # End Source File # Begin Source File SOURCE=..\sc2code\weapon.h # End Source File # End Group # Begin Source File SOURCE=config.h # End Source File # Begin Source File SOURCE=..\endian_uqm.h # End Source File # Begin Source File SOURCE=..\options.c # End Source File # Begin Source File SOURCE=..\options.h # End Source File # Begin Source File SOURCE=..\port.c # End Source File # Begin Source File SOURCE=..\port.h # End Source File # Begin Source File SOURCE=..\starcon2.c # End Source File # Begin Source File SOURCE=..\types.h # End Source File # Begin Source File SOURCE=..\uqmversion.h # End Source File # End Group # Begin Group "Doc" # PROP Default_Filter "" # Begin Group "Devel" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\doc\devel\aniformat # End Source File # Begin Source File SOURCE=..\..\doc\devel\checklist # End Source File # Begin Source File SOURCE=..\..\doc\devel\debug # End Source File # Begin Source File SOURCE=..\..\doc\devel\dialogs # End Source File # Begin Source File SOURCE=..\..\doc\devel\files # End Source File # Begin Source File SOURCE=..\..\doc\devel\fontres # End Source File # Begin Source File SOURCE=..\..\doc\devel\generate # End Source File # Begin Source File SOURCE=..\..\doc\devel\gfxlib # End Source File # Begin Source File SOURCE=..\..\doc\devel\gfxres # End Source File # Begin Source File SOURCE=..\..\doc\devel\gfxversions # End Source File # Begin Source File SOURCE=..\..\doc\devel\glossary # End Source File # Begin Source File SOURCE=..\..\doc\devel\graphicslock # End Source File # Begin Source File SOURCE=..\..\doc\devel\input # End Source File # Begin Source File SOURCE=..\..\doc\devel\musicres # End Source File # Begin Source File SOURCE=..\..\doc\devel\pkgformat # End Source File # Begin Source File SOURCE=..\..\doc\devel\planetrender # End Source File # Begin Source File SOURCE=..\..\doc\devel\planetrotate # End Source File # Begin Source File SOURCE=..\..\doc\devel\plugins # End Source File # Begin Source File SOURCE=..\..\doc\devel\resources # End Source File # Begin Source File SOURCE=..\..\doc\devel\script # End Source File # Begin Source File SOURCE=..\..\doc\devel\sfx # End Source File # Begin Source File SOURCE=..\..\doc\devel\strtab # End Source File # Begin Source File SOURCE=..\..\doc\devel\threads # End Source File # Begin Source File SOURCE=..\..\doc\devel\timing # End Source File # End Group # Begin Group "Users" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\doc\users\manual.txt # End Source File # Begin Source File SOURCE=..\..\doc\users\unixinstall # End Source File # End Group # Begin Source File SOURCE=..\..\BUGS # End Source File # Begin Source File SOURCE=..\..\ChangeLog # End Source File # Begin Source File SOURCE=..\..\TODO # End Source File # End Group # Begin Group "Resources" # PROP Default_Filter "" # Begin Source File SOURCE="..\res\kohr-ah1.ico" # End Source File # Begin Source File SOURCE=..\res\sis1.ico # End Source File # Begin Source File SOURCE=..\res\starcon2.ico # End Source File # Begin Source File SOURCE="..\res\ur-quan-icon-alpha.ico" # End Source File # Begin Source File SOURCE="..\res\ur-quan-icon-std.ico" # End Source File # Begin Source File SOURCE="..\res\ur-quan1.ico" # End Source File # Begin Source File SOURCE="..\res\ur-quan2.ico" # End Source File # Begin Source File SOURCE=..\res\UrQuanMasters.rc # End Source File # End Group # End Target # End Project uqm-0.6.2/sc2/src/msvc++/AbxDecoder.dsp0000600000175000017500000001015210543202106016063 0ustar joeyjoey# Microsoft Developer Studio Project File - Name="AbxDecoder" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=AbxDecoder - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AbxDecoder.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AbxDecoder.mak" CFG="AbxDecoder - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AbxDecoder - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "AbxDecoder - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=xicl6.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "AbxDecoder - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "AbxDecoder___Win32_Release" # PROP BASE Intermediate_Dir "AbxDecoder___Win32_Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "AbxDecoder_Release" # PROP Intermediate_Dir "AbxDecoder_Release" # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x1d000000" /subsystem:windows /dll /machine:I386 /nodefaultlib:"msvcrtd.lib" /out:"../../content/cdps/abxadec.dll" !ELSEIF "$(CFG)" == "AbxDecoder - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "AbxDecoder___Win32_Debug" # PROP BASE Intermediate_Dir "AbxDecoder___Win32_Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "AbxDecoder_Debug" # PROP Intermediate_Dir "AbxDecoder_Debug" # PROP Ignore_Export_Lib 1 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c # ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "." /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x1d000000" /subsystem:windows /dll /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"../../content/cdps/abxadec.dll" /pdbtype:sept !ENDIF # Begin Target # Name "AbxDecoder - Win32 Release" # Name "AbxDecoder - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=../abxadec/abxaud.c # End Source File # Begin Source File SOURCE=../abxadec/abxaud.h # End Source File # End Group # End Target # End Project uqm-0.6.2/sc2/src/msvc++/UrQuanMasters.dsw0000600000175000017500000000104710543202106016647 0ustar joeyjoeyMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "UrQuanMasters"=".\UrQuanMasters.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### uqm-0.6.2/sc2/src/msvc++/config.h0000644000175000017500000000321410547157076015025 0ustar joeyjoey/* This file contains some compile-time configuration options for MS Windows * systems when building using MSVC. * Change the values below if you want anything other than the defaults. * For *nix systems, config_unix.h is used, which is generated by build.sh * from src/config_unix.h.in. * When building on MS Windows using build.sh (MinGW, Cygwin), * config_win.h is generated from src/config_win.h.in. */ #ifndef _CONFIG_H #define _CONFIG_H /* Directory where the UQM game data is located */ #define CONTENTDIR "../content/" /* Directory where game data will be stored */ //#define USERDIR "../userdata/" #define USERDIR "%APPDATA%/uqm/" /* Directory where config files will be stored */ #define CONFIGDIR USERDIR /* Directory where supermelee teams will be stored */ #define MELEEDIR "%UQM_CONFIG_DIR%/teams/" /* Directory where save games will be stored */ #define SAVEDIR "%UQM_CONFIG_DIR%/save/" /* Define if words are stored with the most significant byte first */ #undef WORDS_BIGENDIAN /* Defined if your system has readdir_r of its own */ #undef HAVE_READDIR_R /* Defined if your system has setenv of its own */ #undef HAVE_SETENV /* Defined if your system has strupr of its own */ #define HAVE_STRUPR /* Defined if your system has stricmp of its own */ #define HAVE_STRICMP /* Defined if your system has getopt_long */ #undef HAVE_GETOPT_LONG /* Defined if your system has iswgraph of its own*/ #define HAVE_ISWGRAPH /* Defined if your system has wchar_t of its own */ #define HAVE_WCHAR_T /* Defined if your system has wint_t of its own */ #define HAVE_WINT_T #endif /* _CONFIG_H */ uqm-0.6.2/sc2/src/types.h0000600000175000017500000000701710543202107013601 0ustar joeyjoey/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Data types used in the UQM port * Draft 3 * Compiled from various sources */ #ifndef _TYPES_H #define _TYPES_H #ifdef _MSC_VER # if (_MSC_VER >= 1300) # include # else typedef int intptr_t; typedef unsigned int uintptr_t; # endif # ifdef _WIN64 # define PRIxPTR "lx" # else # define PRIxPTR "x" # endif #else # include #endif #if defined(__arch64__) || defined(__alpha) || defined(__x86_64) \ || defined(_M_IA64) || defined(_M_AMD64) /* 64-bit platforms */ # define UQM_INT16 short # define UQM_INT32 int # define UQM_INT64 long #elif defined(__MACOS__) # define UQM_INT16 short # define UQM_INT32 long /* Add your OS support here */ #else /* all other sane 32bit: WIN32, __MACOSX__, __BEOS__, __EMX__ */ # define UQM_INT16 short # define UQM_INT32 int #endif /* Figure out how to support 64-bit datatypes */ #if !defined(UQM_INT64) && !defined(__STRICT_ANSI__) # if defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) # define UQM_INT64 long long # elif defined(_MSC_VER) || defined(__BORLANDC__) # define UQM_INT64 __int64 # endif #endif /* !__STRICT_ANSI__ */ /* The 64-bit type isn't available on EPOC/Symbian OS */ #ifdef __SYMBIAN32__ # undef UQM_INT64 #endif typedef enum { false = 0, true } bool; /* If it isn't char, what is it ?!*/ typedef unsigned char uint8; typedef signed char sint8; typedef unsigned UQM_INT16 uint16; typedef signed UQM_INT16 sint16; typedef unsigned UQM_INT32 uint32; typedef signed UQM_INT32 sint32; #if defined(UQM_INT64) typedef unsigned UQM_INT64 uint64; typedef signed UQM_INT64 sint64; #undef UQM_INT64 #else /* dont have UQM_INT64 */ typedef struct { uint32 hi; uint32 lo; } uint64; typedef struct { sint32 hi; uint32 lo; } sint64; #endif /* UQM_INT64 */ #undef UQM_INT16 #undef UQM_INT32 /* Make sure the types really have the right sizes * Adapted from SDL * This will generate "negative subscript or subscript is too large" * error during compile, if the actual size of a type is wrong */ #define UQM_COMPILE_TIME_ASSERT(name, x) \ typedef int UQM_dummy_##name [(x) * 2 - 1] UQM_COMPILE_TIME_ASSERT(uint8, sizeof(uint8) == 1); UQM_COMPILE_TIME_ASSERT(uint16, sizeof(uint16) == 2); UQM_COMPILE_TIME_ASSERT(uint32, sizeof(uint32) == 4); UQM_COMPILE_TIME_ASSERT(uint64, sizeof(uint64) == 8); #undef UQM_COMPILE_TIME_ASSERT #undef SINT8_MIN #undef SINT8_MAX #undef SINT16_MIN #undef SINT16_MAX #undef SINT32_MIN #undef SINT32_MAX #undef UINT8_MAX #undef UINT16_MAX #undef UINT32_MAX #define SINT8_MIN (-128) #define SINT8_MAX 127 #define SINT16_MIN (-32767-1) #define SINT16_MAX 32767 #define SINT32_MIN (-2147483647-1) #define SINT32_MAX 2147483647 #define UINT8_MAX 0xff /* 255U */ #define UINT16_MAX 0xffff /* 65535U */ #define UINT32_MAX 0xffffffff /* 4294967295U */ #endif /* _TYPES_H */ uqm-0.6.2/sc2/README0000600000175000017500000000142610543204457012365 0ustar joeyjoeyYou're looking at the readme for 'The Ur-Quan Masters', a volunteer project that intends to bring the classic game 'Star Control II' to modern systems. The program code that comprises 'The Ur-Quan Masters' was derived from code written by Toys for Bob, Inc. for the 3DO version of 'Star Control II', with their permission and encouragement. If you've got this file from the source tree, you can find everything you need to get started in INSTALL (INSTALL.mingw for MinGW) and doc/users/unixinstall. The home page of the project is located at http://sc2.sourceforge.net/ You can find links to downloads, our bug database, and our forum there. Have fun! Star Control II is a registered trademark of Accolade, Inc. All other trademarks and tradenames belong to their respective owners. uqm-0.6.2/sc2/content/0000755000175000017500000000000010552567174013174 5ustar joeyjoeyuqm-0.6.2/sc2/content/version0000600000175000017500000000007510543204457014566 0ustar joeyjoey0.6.0 $Date: 2006-12-16 05:47:43 +0100 (Sat, 16 Dec 2006) $ uqm-0.6.2/sc2/ChangeLog0000644000175000017500000013713710552567104013301 0ustar joeyjoeyChanges towards version 0.7: 0.6.2 (maintenance release): - A bit more debug info for failed connects. - SvdB - Exit with failure if basic content cannot be found, ensuring proper error reporting under Windows - Michael - Popup windows for "Really Exit?" and Game Pause are immune to fades and crossfades (Bug #455) - Michael - No longer depend on SDLK_LAST statically; key input should now be safe if compiled with a different version of SDL than the one running the program (Bug #936, possibly also #834 and #883) - Michael - Unix build scripts now work under LC_CTYPE=tr_TR - SvdB - Flush write buffer when doing a uio_fclose() after doing only uio_fwrite() operations. - SvdB - Major rewrite of the SwapBuffers commands -- screen compositing logic has all been abstracted out into sdl_common.c instead of being nearly-duplicated in opengl.c and pure.c - Michael 0.6.1 (maintenance release): - The Unicode Private Use Area is no longer considered printable. This is a stopgap to handle unusual behavior with text entry under OS X. See bug #942 for more details - Michael - Do not rely on GL_UNPACK_SKIP_* arguments, which some OpenGL drivers mishandle (Bug #914) - Michael - Do not overwrite GLOBAL_SIS (CrewEnlisted) when leaving Hyperspace (Bug #938) - Michael - Fixed a text entry width problem that was deleting control template names (Bug #947) - Michael - uio cleanups, documentation - SvdB - uio path parsing fixes/improvements - SvdB - Windows UNC path support (#907) - Windows drive-relative paths ("D:path" without a path seperator) - treat multiple consecutive path seperators as one (like POSIX) - config dir no longer needs trailing path seperator (bug #738)- SvdB - Simplification of uio Stream functions. No more internal seeks. - SvdB 0.6.0: - Fixed a bug where an input delay was used for non-network games - SvdB - Fixed a bug where the victory ditty would end prematurely when UQM is compiled without Netplay support - SvdB - Take $CFLAGS and $LDFLAGS into account for dependency detection (they were already used for the building itself) - SvdB - Validate UQM version of either side of a Netplay game - SvdB - Better abort and disconnect handling for Netplay - SvdB - Menu sounds in Setup track rest of game (#922), from Nic - Michael - Shifted the Mouse Error to a Popup Window, moved the message to starcon.txt for translators - Michael - Generic DoPopupWindow() command for status messages - Michael - Update the 'current selection' icon after deleting or inserting ships in a fleet in SuperMelee - SvdB - Correct some background pixels in melebkgd.{25,26}.png - SvdB - Unix build scripts improvements. - SvdB - Build fixes for MacOS X (with thanks to Nic) - SvdB - Ships in battle can resume normal speed in all circumstances after the enemy Avatar's tractor beam disengages (bug #860; this is a netplay desynchronizing change) - Alex - Conversation summary breaks lines based on actual chars/words that fit (bug #916) - Alex - Netplay configuration dialog - Michael - Better error message for 'Kernel failed to load' (#917) - Michael - Pushbutton for connecting to netplay, in anticipation of a full configuration dialog later - Michael - Cleanup of comm.c - SvdB - Netplay - SvdB - Added step-by-step instructions for compilation on MSVC++ - SvdB - All output done in binary mode, due to uio/Win32 conflicts (#912) - Michael - Online key configuration menu actually functional now - Michael - Tweak to Lander UI - Special Weapon is now explicitly Lander Escape, just as Warp Escape is - Michael - Default key configuration changed slightly; online display of current key bindings - Michael - Input templates can now be renamed, both online and off - Michael - Fixed an integer-size error that was causing crashes on AMD64, from Solomon Peachy (#895) - Michael - Added some generic lib code to be used by future code. - SvdB - Joystick support is now optional; from SvdB, Alex - Restructed and normalized savegame and game-state reading/writing code; savegames are now compatible between same-endian 32- and 64-bit systems; savegames from prior 64-bit builds cannot be used - Alex - (Unix build scripts) Failed mkdep doesn't result in empty .d files anymore. Now using the gcc 3 "-MF" and "-MT" options. - SvdB - removed internal libmikmod, adding a dependancy on an external one - SvdB - Added a quit button for the Super Melee main menu - Michael - Fixed sporadic uqm.cfg loading errors in release builds - Alex - Quit (F10) now works correctly during intro (bug #862) - Alex - Playing failure sounds when entering text consistently (bug #884) - Alex - 64-bit fixes in construct_response () - Michael - Removed rotating 3d planet frame caching (cuts mem usage by 5M) - Alex - One pixel fix in melee menu pictures. - SvdB - Debugging function to add energy during battle. - SvdB - Changed slaveshield throb rate to match the 3DO - SvdB - Fixed recently introduced bug with crew count on exit to HyperSpace. (bug #875) - SvdB - Fixed static vars not reinited in alien comm code (caused various side-effects; bug #870) - Alex - Fixed a spinlock in Melee's final score screen (Bug 879) - Michael - Phase 2 of online keyconfig - Setup Menu can configure assignment of templates to players - Michael - Control scheme shifted to Menus + Control Templates in preparation for the online keyconfig - Michael - Fixes to logic in the Utwig conversations (Bugs 327, 647), from Nic and Michael - Removed unused and invalid lander font chars - Alex - Setup menu reads strings out of lbm/setupmenu.txt - Michael - More fixes towards working 64-bits binaries. - SvdB - Flashing outfit modules to build w/ PC menus too; bug #871 - Alex - Corrected caption Orbit: to Tilt: in planet scan; bug #847 - Alex - Added missing failure sounds in Outfit, Shipyard, Cargo and Roster; played when over/under capacity, not enough RUs, etc; bug #842 -Alex - Crew retrieved from space after the end of an encounter will no longer set the crew larger than the ship's maximum. - SvdB - Flagship crew numbers are no longer continuously synchronised during melee, but only at the beginning and end of the battle. - SvdB - Various small cleanups. - SvdB - Debugging function to add crew during battle. - SvdB - More documentation - SvdB. - RMPLIFIED PRECURSOR BOMB is now AMPLIFIED, from Vorn (bug #812) -Michael 0.5: - Innocent original c&p bug fixed, from bpoint. - Handle relative dirs in -C correctly, from Jan Lönnberg (part of bug #738). - Internationalization fixes: moved many hardcoded English strings into string resource file starcon.txt (bug #778), from Andrew Zabolotny - Melee Scale and Slides/Movies now take effect immediately - Michael - The intro now plays only when a new game is started - Alex - fixed uio_rename() and some other cases where a new file is created under specific circumstances. - SvdB - Fix bug in GetStringContents which used the number of chars where it should have used the memory size. - SvdB - Control scheme upgrades checked (VControl Version upgrade) - Michael - Better instant-move (for debugging) - SvdB - Fixed version checking in unix build scripts. SDL 1.2.10 is now recognised as newer than 1.2.9. - SvdB - Some small improvements to the portability of the build system, from Jim Paris - Fixed two-week bomb installation at the Starbase bypassing the defeat condition (bug #757), from Nic, Alex - Added star search in Starmap (define Menu-Search and Menu-Next keys in your keys.cfg) from kworces, Alex, SvdB - Fixed Orz greeting at Taalo homeworld inconsistency (bug #819) - Alex - Fixed Venus' atmo density to 90 times that of Earth (bug #821) - Alex - Internationalization fixes: better or, in some cases, fixed support of non-Latin UTF-8 strings (more to come; bug #778), from Andrew Zabolotny - Remaped special chars used in the game (degree, infinity and earth signs; middle dot) to their UCS equivalent codes (bug #818) - Alex - Color depth is now determined entirely automatically - Michael - Text input is now available in languages other than English (UCS/Unicode; SDL does not support Unicode input on Windows yet; you must have proper font chars installed -- see translations) - Alex - Re-added joystick text input (w/ Up/Down/PageUp/PageDown keys); joystick alphabet in content/lbm/joyalpha.txt (bug #495) - Alex - Text input refactoring: enabled key repeat, added support for Home, End and BackSpace keys; (bugs #671, #815) - Alex - Selecting the scan methods for shielded and gas giant planets is now allowed when using PC menus (bug #800) - Alex - Added a unified credit roll combined with outtakes (bug #46) - Alex - Setup menu selection doesn't reset when you quit a submenu now - Michael - Split config.alwaysgl and config.usegl so that "Use Pure Mode If Possible" persists across runs even when using a GL mode - Michael - Fixed Yehat Rebel left hand doubling up problem (bug #807) - Alex - Fixed the problem with Melnorme stripping Chmmr bomb/crystal modules from the ship in a fuel deal (bug #803) - Alex - Corrected baseline of 'j' in Micro font (bug #797) - Alex - Fixed small VUX animation glitch (out of order frames; bug #808) - Alex - CANCEL now behaves as expected in setup menu - Michael - Only SELECT and CANCEL trigger the fade-to-black at the end of a Super Melee, solving the issue in bug #547 - Michael - Admiral ZEX is no longer referred to as "Commander" or "Zex" (bug #811) - Michael - Keypress status is not reset when entering battle mode (solves bug #596) - Michael - Added the rest of devel/ and users/ documentation into MSVC .dsp files (bug #589) - Michael - Fixed PNG transparency info (tRNS chunk) in all images according to info specified by .ani - Alex - Comm animation fixes (bugs 557, 705, 806); from chmmravatar, Alex - Imported DOS versions of alien comm graphics which have richer palettes and look better in most cases (bug #314) - Alex - Added slider controls for volume to setup menu - Michael - Added --shield and --scaler hq to setup menu - Michael - Fixed lockup when skipping past VUX beast analysis data in Starbase (bug #790; should take care of all spliced comm edge cases) - Alex - Added 3DO-style throbbing slave shield (--shield; bug #32); special thanks to Nic for inspiration and some code - Alex - Rotating 3D planet changes: nicer looking slave shield; planet now finally looks like a rotating sphere (and not cylinder); added some lighting variance to give it a 3D feel (not a smooth ball) - Alex - Refactored colormaps storage, management and transforms; paletted images rendering should be much faster now - Alex - Corrected intro slide 5 (crosshair removed); bug #794, from AusME - Split off alien comm colormaps from global scclrtab into corresponding race dirs (avoids potential mod collisions) - Alex - Refactored font engine: fonts are loaded and treated as alpha-channel-only images (allowing for antialiased fonts now); solid color and gradient/alternate effects processing is unified - Alex - Fixed problems with pausing the game during ending sequences (game-clock bug; undrawing incorrectly due to cliprect) - Alex - Removed hotspot abuse from lander report drawing to fix bad positioning desync brought on by new hotspot handling - Alex - Trilinear melee scaler overhaul (melee smooth mode should look nicer now; melee can now fully use alpha gfx) - Alex - Miscellaneous Sa-Matra gfx fixes (Generator collision masks and explosion frame 0 were off; Shield position was off in med and sml; Main sml gfx was 2 pixels too narrow) - Alex - Replaced the binary resource indexes by textual ones (also resolves bug #687) - SvdB - Some subtitle timing fixes (bug #s 771, 780) - Alex - Entering Planetary Orbit wait screen is back (from DOS) - Alex - Gfx engine changes: now always 32bpp internally (facilitates alpha channel usage); accelerated platform-specific scaler code; only using alpha channel where needed. Processor pack is necessary for compilation on VC6. - Alex - New 2x scaler 'hq' (by Maxim Stepin; www.hiend3d.com/hq2x.html) - Alex - Removed MikMod i/o hacks (using MREADER i/o now; bug #787) - Alex - Fixed fast escape weirdness (bug #619) - from Jan Lönnberg - New topographical 4x planet surface scaler (bug #786) - Alex - Added support for Tremor for Ogg Vorbis decoding (avoids floating point math) - SvdB - Fixed T-Pet compulsion graphics (partially); bug #772 - Alex - Doing game-state file I/O in memory instead of temp files; should avoid problems as in bug #752 - Alex - Separate config_win.h file for build.sh builds on Windows - SvdB - Fixed a typo ("we" -> "he") in Thraddash dialog (bug #783) - Alex - Corrected grammar in Umgah 'Caster lander report (bug #781); from James Ho - Options selected in the Setup Menu now persist across runs -Michael - Added a simple implementation of key-value pair "resource" files for organizing simple data such as configuration options -Michael - Added a 'fullscreen' setup menu option - Alex - Fixed a bug that prevented Slylandro Probes from ever showing up in interplanetary exploration (found by SvdB, bug #768) - Lowered the Comm ambient animation rate from 120 to 40fps, thus limiting the CPU usage - Alex - Fixed Recursive Mutexes to still work even if the ThreadID is 0 (bug 779) - Michael - Permit independent selection of graphics driver and resolution in setup menu - Michael - Changed comm subtitle caching to use own context instead of screen grabs; should resolve Blue Comm Screen universally - Alex - Added missing break statement in DrawBatch:RECT_PRIM - Alex - Setup menu split into four submenus - Michael - Fixed fallback in getHomeDir() for when $HOME is not defined on *nix - SvdB - %APPDATA% fallback no longer to "../userdata", but to "./userdata", as we don't chdir() to the content dir anymore. - SvdB - Commander Hayes flickering lights animation now properly reenabled when applicable (bug #777) - Alex - Refactored setupmenu code to use generic widgets - Michael - Support UTF-8 chars in mineral names (bug #770) - SvdB - Modified scalers to use surface pitch instead of width - reported to fix bug #740 - Michael - Cleaner build output. Set '$MAKE_VERBOSE' to 1 for old output. - SvdB - Improved dependency tracking for unix build system. - SvdB "./build.sh uqm depend" is only needed for checking for new source files. - handle "." and ".." in paths - SvdB 0.4: - Nicer title image during intro, from Nic - Installation routine for MacOS X, from Nic. - Lots and lots of dialog fixes, from Nic. - Some speech is dependant on whether spoken voices are on, from Nic. - OpenAL header cleanup. Updating OpenAL may be necessary. Windows users should put the OpenAL headers in an AL/ directory now too (should be the default). - SvdB - Improvements to the unix build system for cross-compilation - SvdB - Do not define ssize_t for MinGW. - SvdB - Fallback readdir_r() - SvdB - Attempting to click the screen pops up an error message, from Nic, heavily modified (dodge on #533) -Michael - Fixed potential crash with a truecolor oscilloscope image (thanks jdorje) and made it generally more flexible (bug #729) -Alex - Added missing Tanaka battle portrait images (new artwork; oldcap) and minor fixes to other shofixti images (bug #183), from Nic - Mycon captain portrait finally fixed (bug #183), from Nic - Saving the game while on autopilot inside an interplanetary system will no longer reset the autopilot (bug #725) -Alex - Main menu and Super Melee menu can now play music tracks; drop in 'lbm/mainmenu.ogg' and 'melee/melemenu.ogg', respectively -Alex - Can now switch mod->ogg in intro/outro player (thanks Nic), and mod<->ogg everywhere in general -Alex - Fixed crash after T.Pet conversation upon reentering D.Crateris once Ur-Quan have been confused (bug #531) -Alex - Fixed last subtitle flashing after fast-forwarding to the end, pressing F10 and selecting NO (bug #498) -Alex - Fixed first contact with Arilou at homeworld; Talking Pet confusion (bug #638), from Paxtez - Fixed warp-escape in Cyborg mode removed by previous game input patches (bug #563) -Alex - Fixed spurious story-line changes (usually the manner of the encountered race) caused by loading a game from an Encounter screen (bug #519) -Alex - Option change: --meleescale to --meleezoom (bug #694) -Alex - The alpha icon is now default (for XP/2003); bug #474 -Alex - Fixed incomplete memset()s in comm alien animation code (comm should be saner now), from jdorje - Guard access to the Clock so that accessing it is a no-op when the game isn't actually in progress (bug #678), from Nic - Accept files with .uqm extension for packages (bug #558) Added regex fallback files. - SvdB - Music volume normalized throughout the game (bug #718) -Alex - VControl parse errors suppressed unless critical - attempting to set the threshold of a nonexistent joystick no longer makes the game refuse to run (Bug #660, again) - Michael - Properly handling Thraddash-Ilwrath mission overlap (bug #530) -Alex - Separate 'ask for fuel' player responses for Mercury and Luna missions (bug #716), from Nic - Stereo SFX model changed slightly (fixes #472) -Alex - Pkunk Spindle news items are now disabled until you befriend them (bug #315), from Paxtez - Melee captain names re-extracted and fixed (bug #188) -Alex - It is now possible to complete the game w/o ever allying with the Starbase at Earth; known as 'Beating the Game Differently' mode; (bug #592) -Alex - The direction flagship is facing is now preserved through an encounter in Hyperspace -Alex - Added support for PC-style 3-step melee zooming; -b=pc|step option; (bug #694) -Alex - Melee team building pick-ship box is now generated with actual ship icons (bug #692) -Alex - Setup Menu no longer crashes or misbehaves on custom resolutions (bug #693) - Michael - Quit confirmation window (on F10) undraws correctly during intro slides (bug #673) -Alex - Attempting to set to a mode that Doesn't Work in Setup no longer ends the program (bug #695) - Michael - Fixed segfault when shutting down because video could not be initialized (bug #683) - Michael - Fixed crash when restarting Sa-Matra battle after abort (bug #700) -Alex - Some cleanups, enabling successful build with GCC 4 (bug #710), mostly from Ville Skyttà -SvdB - Sa-Matra portrait now fills the portrait space (bug #514), from Nic - Updated melee images with original DOS content; should resolve most captain portrait issues (bug #183) -Alex - Bug #702 fixes (dead code + compiler warnings) -Alex - Flagship will not fly sideways on auto-pilot in Hyperspace (bug #642) -Alex - Fixed menu sounds in full-game battle ship selection box (bug #566) -Alex - Added '--version' - SvdB - Fixed a bad memory access which could occur when the code relies on CharCount for determining the end of a string (bug #701). - SvdB - Battle planet images now have corrected transparency info, so there is no more black square overlaping ships (bug #128); and coincidently 3DO credits now have a starfield background (bug #470) -Alex - Unicode support for fonts and strings - SvdB - Fixed image clipping with --meleescale=nearest (bug #126) -Alex - Setup menu now uses a background contributed by Joffrey Smith - If keys.cfg refers to a nonexistent joystick, the game will stil run (bug #660) -McMartin - Fixed support for languages other than English; loading font chars with codes above 136 is now possible (bug #690), from Matthias Hager - Enable the other insults against the Mycon (bug #559), from Nic. - Colormap format (.ct files) changed to allow for richer graphics. First step towards importing some of the original DOS gfx. See bug #314 for more info. -Alex - Better dependency checking in unix build scripts - SvdB - Many options menu changes: left-justified categories, and the ability to change driver/resolution/bpp/scaler in real time, and updates are less frequent so as to spare the DCQ -McMartin - PC ending animation now draws the flagship w/ modules according to the actual player's load; also the script structure changed allowing for an FPS improvement -Alex - Version number in the main menu does not blink anymore when the menu selection is changed (bug #672), from Nic - Massive amount of file restructuring and cleanups. Need many more. - SvdB - Added Intro and Ending slide shows (bug #46); use "-i pc" -Alex - Cross-fades in OpenGL mode with complex scalers fixed (bug #674) -Alex - Added doc/devel/dialogs - SvdB - Don't allow the reply "Symbionts, how interesting!" in the Supox conversation until they mentioned they were Symbionts. (bug #528), from Nic - Not initialising the various systems when -h/-? is supplied (bug #656), from Nic - F10 works when playing the intro (bug #665), from fOSSiL - Game clock counter overflow fix (bug #668) - [collective effort] - Cocoa hooks for MacOS X, from Nic - Corrected number for combat energy when outfitting starship. - SvdB - Added dumping planet info to uqmdebug.c - SvdB - Check language.txt for locale, from Zap - Make it possible to specify the config dir on the command line. (bug #645) - SvdB - Speech .txt and .ts corrections, from Nic. - SvdB - Made the unix build scripts more portable. Removed some small bugs. - SvdB - No longer chdir() to the content dir (bug #564) Environment variables and ~ are interpreted in the supplied content path now. Don't look for content in the default directories if an explicitely supplied path failed. It would only confuse users. - SvdB - The unix build script is now able to detect SDL on Darwin (bug #358) - SvdB - Resource units given more obviously when ordering a probe to self-destruct (bug #586), from Nic. - Shipyard "Combat Energy" changed to reflect the recharge rate (bug #522). Also, some cleanups. Thanks and apologies to Nic. - SvdB - Added lots of debugging functions, SvdB - Cleaned up use of the DEBUG define, SvdB - Talking Pet .txt file corrected to match the .ogg files, and talkpet.ts corrections, from Nic - Abstracted window-drawing code from confirm.c -Michael - Fixed blue comms screen problem (bug #363), from Joel Holveck & Nic - Automatically adding an icon for Darwin builds, from Nic - Fixed Roster-F10-Quit bug (#591), - Michael - Restructured starcon2.c, with better checks for argument parsing, and consistent error messages. - SvdB - Restructuring of the unix build scripts. Also, interrupted dependency builds are now detected. - SvdB - Unix build: Make it possible to use another directory than the current one for putting the build data in (such as build.vars, config.state, the obj/ dir, and the final binary). - SvdB - Fixed various odd behaviors when loading from HyperSpace (bug #587), from Nic and Michael - Added new 'triscan' scaler; derived from scale2x[.sf.net] -Alex - Space marines die in a self-destructing Scout (Bug #445), from Nic - Added the -l option to produce logfiles (bug #560), from Nic - Zoq-Fot-Pik speech properly vertically centered (bug #579), from Nic - Input code refactoring, phase 2: All player input is brokered by DoInput -Michael - Updated .cvsignore commands, from Nic - Fixed a keyrepeatbug from when the player cancels out of the Starmap in IP -Michael - IP_taskfunc now uses PulsedInputState instead of handling its own debounce delays -Michael - Input code refactoring, phase 1: Replaced messy structs with an array indexed by an enum. -Michael - Thread code refactoring: only the main thread will actually spawn threads, and thread IDs are properly recycled with SDL_WaitThead () once they're done. (With luck, this will fix bug #561) -Michael - Sound code refactoring: core api is now virtualized, MixSDL is divided to generic mixer and driver entities - Mika - Optimized MixSDL mixing and resampling routines (hopefully fixes bug #435) - Mika - MOD music should now play properly on big endian machines if using high quality mode (workaround for bug #166) - Mika - Better-looking slave shield (bug #32), from Nic - Bay door animations don't stall before aborting (bug #500), from chmmravatar - Reports SDL version on startup (bug #520) - Mika,Nic - Fuel usage on planet landing is now reported correctly on all situations (bug #556), from Nic - Fine-grained control of menu sounds, "MenuSounds" global now guaranteed to always be non-null -Michael - Added support for stdio file access through temporary files to uio. added uio_copyFile to uio - SvdB - Added uio_getFileLocation() and uio_getMountFileSystemType() to uio. Also some small improvements. - SvdB - Fixed fuel usage estimate to selected destination on the starmap. (original bug, not reported) - SvdB - Sound decoders refactoring: decoders are now virtualized, the high-level decoding code is unified and any format is theoretically streamable -Alex - Patches to enforce the invariant that the GraphicsLock is held when SetFlashRect is called (bug #504) -Michael - Major refactoring of threadlib; see doc/devel/threads -Michael - Downgraded the GraphicsLock to an ordinary Mutex -Michael - Added movie player; only movies defined are intro and ending; only .duk decoder present (.duk audio decoder mostly derived from decoder by SvdB) -Alex - Extra fallback for the unlikely situation that $HOME isn't set on a unix system. (#493) - SvdB - Accept spaces in --contentdir argument (#492) - SvdB - Separated and abstracted sound buffer-tagging and trackplayer clip/subtitle chaining -Alex - Abstracted the recursive mutexes in MixSDL and DCQ code -Michael - Introduced a new synchronization construct (CrossThreadMutex) and migrated the GraphicsSem and clock_sem over to it (#359) -Michael - Replaced thread-local Semaphores with Mutexes (#359) -Michael - Load/save icons don't flash anymore when in savegame menu (part of bug #291), from Paxtez - Savegame slot now defaults to the last one used during one execution of uqm (bug #477), from chmmravatar - Fixed one-pixel glitch in shipyard when scrapping (bug #461), from Paxtez - Adjusted subtitle timings when there are no oggs (part of bug #362), from chmmravatar - Fixed crash in conversation summary and ffw/frew problem when selling data to Melnorme (bug #476), from chmmravatar - Flush input after selecting "Navigate" (bug #475) - Michael - Fixed ships in solar system getting displaced after having visited a planet (bug #365) -Alex - Fixed collisions/encounters with "invisible" fleeing ships (bug #319) -Alex - Quit confirmation fixes: lander reports, conversation summaries, outtakes, end credits; font effect properly set/saved/restored; (bugs #454, #465, #466); from chmmravatar - Obsolete "register" keywords removed -Michael 0.3: - Dirty hack to avoid a warning about the "ignored.key" hack - SvdB - Typo 'natually' fixed in Arilou speech - SvdB - uio: Fixed a bug which could cause spurious warnings when using .zip files generated from DOS/Windows - SvdB - uio: Fixed a potentially memory-corrupting bug when in a .zip file a subdir is described before a dir higher in the directory structure. - uio: Fixed an incomplete message that would only show when handling a specific error - SvdB - Added doc/checklist file - SvdB - RUs properly cleared in savegame display, from Paxtez, chmmravatar - Support for up to 50 savegames, from Paxtez - Action names are properly null-terminated, stops a crash for some bad keys.cfg types -Michael - added '--addon ' - SvdB - keys.cfg from incompatible control scheme version is now renamed automatically to keys.old -Mika - Added warranty message in the console on startup, SvdB - Left and Right directions disabled in fuel screen (bug #452), from Paxtez - Syreen don't rejoice until victory truly is theirs (bug #451), from Nic - Guardian in Blazer mode being drained by DOGI will no longer result in a non-blazer Guardian with Blazer effects. Original sc2 bug. (bug #283); from Paxtez - 'CREW' and 'BATT' instead of icons in combat screen when using PC-style menus (bug #308); from Paxtez - New shipyard SCRAP system with scrapping confirmation (bug #413); from Paxtez - Syreen ships become available when Talana says they are (bug #264); from Nic, Alex - The infinity symbol is correctly printed for gas giant atmosphere in coarse scan screen (bug #239) -Alex - Prevent Syreen crew above 12 getting thrown out the airlock in Roster screen (bug #184); from chmmravatar, Alex - Lander report messages now use the entire panel (bug #36), from chmmravatar - Fix colour cycling in the roster screen (bug #279), from Nic - Fixed last seen battle-group teleporting to Sol after invoking Talking Pet in Sol (bug #109) -Alex - Fixed a dialog glitch on Slylandro homeworld (#442) -Michael - Freeze planetary simulation at beginning of landing sequence to stop event bursts (bug #80) -Michael - Extra 2 ship slots in supermelee, as in the PC SC2, and all the PC default teams, from chmmravatar (bug #248) NOTE: this breaks old team saves! - Made functions for GET_GAME_STATE and SET_GAME_STATE - SvdB - Fixed bug with entering closing portals (bug #108) - SvdB+chmmravatar - Mouse cursor is now hidden in fullscreen mode (bug #173) -Mika - Version checks inside the input code to flag incompatible changes --Michael - Install location for content on unix systems is now ${prefix}/share/uqm instead of ${prefix}/lib/uqm - SvdB - New main menu graphics from MarkVera, Paxtez, Nic (bug #393) - Removed a place where you could ask for repairs when you shouldn't (bug #432), from Nic - Can use F10 to quit during splash screen as well as main menu -Michael - Fixed starship location when being teleported from Procyon to the Earth Starbase after the Precursor bomb is installed. - SvdB - Crew death on planet is now counted properly in all cases (bug #70) -Mika - Fixed lockup in 'save failed' alert box (bug #397), from ghakko - Fixed glitch in Pkunk animation (bug #354), from Paxtez - Fixed Kohr-Ah final defeat message repeating (bug #426) -Mika - Fix for picking up talking pet after Umgah genocide - from Paxtez - MinGW compilation fixes - SvdB+Mika - Bilinear scaler is now faster, has 24bpp mode and uses regions -Alex - Accept CRLF line endings in .txt and .ts files - SvdB - Fixed overflow problem with 32bpp bilinear,biadapt,biadv scalers -Mika - MixSDL now handles resampling correctly (less cracklings); added cubic interpolation for high quality mode -Mika - Removed the redundant "GameExiting" variable -Michael - Added quit options to ingame menu (bug #409), from Paxtez - Fix position of blinking save/load in melee (bug #406), from Paxtez - New packaging/io system. - SvdB - Exit confirmation dialog is prettier and safer, from Paxtez - Exiting from the main menu with F10 now exits the game -Michael - Changed lander speed to 35 FPS, which matches reported 3DO speed (Bug #22) -Michael - Added a Menu-Delete key for the Super-Melee menu (#123) -Michael - Added support for positional (stereo) sound effects, currently works only with OpenAL -Mika - Fixed screen transitions from homeworld conversations (bug #348) -Michael - Fixed Fwiffo join_us_refusals initialization (bug #405) -Mika - Fix Druuge transactions to not elevate crew costs baselessly (bug #235), from ghakko - Fixed glitches and NULL Stamp draw attempt in menu code (bug #26) -Mika - Absence of voice files is now automatically detected (bug #309) -Mika - Fixed Commander Hayes mouth movement before radioactives are given (bug #343) -Mika - Fix glitches in slylandro probe animation (bugs #398, #399), from Paxtez - Confirmation dialog box for exiting the game is now menu-based - Commander Hayes explains his predicament before you get the option to rescue, closes #366, from Nic - Gestalt mode accelerates continuously as long as some key is held; should resolve to PC-style input wrt bug #381 - Michael - Fixed some more false key cancels, addressing 378 again - Michael - Added "gestalt mode" for acceleration cancels; fixes #381 - Michael - Fixed some "false key cancels" in the input system, addressing bugs #378 and #379 -Michael - Completely reworked the input system - Added PC version outtakes, from chmmravatar - Fix crash in PlayStream when whole file is prebuffered and its not speech (bug #259) -Mika - Fix endian problem in colormap transform code (bug #137) -Mika - Fix minor glitch in planet coarse scan (bug #238), from chmmravatar - Wav loader is now endian safe (bug #165) -Mika - Dialogue patch for Melnorme, fixing bug #335 - Two dialogue spots where visit count could run away patched; fixes bug #333, from Stas Sergeev - EventHandler checks CurStarDescPtr before dereferencing it (bug #347) - Oscilloscope/mini-map now has borders (bug #307 part 4) -Mika - Flashing rects are no longer constrained to even-numbered pixels on the y axis; fixes bug #255, from Nic - Fixed minor glitches in main window borders (bug #307 parts 1,2,3) -Mika - There's now space before and after : in coordinates (bug #307 part 6), from Paxtez - Star coordinates no longer shimmy (bug #331), from chmmravatar - The DRAWABLE_DESC datatype now uses separately allocated arrays for animation frames instead of doing pointer arithmetic between it and FRAME_DESCs --McMartin - Date on the green bar now has floating period between day and the year like in PC version (bug #307 part 5) -Mika - AWARE_OF_SAMATRA flag is now written as well as read (closes #113), from Nic - Subtitle drawing is now cached (closes #313) -Mika - Fix glitch and lockup in dialogs when rewinding (bugs #311 and #272), from chmmravatar - Fastforwarding when in last subtitle now works as expected (bug #318), from chmmravatar - Fixed MixSDL buffer underrun handling (bug #211) -Mika - Fix issue with caps lock and num lock preventing planet scan and lander message skipping (bug #299), from chmmravatar - Subtitles are now hidden after alien has finished talking (bug #312), from chmmravatar - Fix for mycon portrait (bug #183), from Nic - Music levels no longer drop in conversations when using -T 0 (partial fix for bug #309), from chmmravatar - Added PC-style conversation summaries (bug #310), from chmmravatar - Pressing pause key now stops dialog correctly (bug #167), from chmmravatar - Fix some glitches in load/save screen (bug #163), from chmmravatar - Utwig shield now pulsates properly (bug #269), from Nic - Fix for memory leak in TFB_DrawCanvas_ExtractPalette (bug #277), from Richard Braakman - Patched Umgah dialogue, fixing bug #8 - Crossfade code now explicitly caches the screen to transition from, and thus no longer glitches. The code needed a slight rewrite, but this does fix bug #33 -McMartin - Melee scaling is now trilinear by default, but it's still possible to choose nearest neighbour with --meleescale; fixes #34 -Mika - Minimum scaling extent is now 1,1; fixes mostly small-objects-disappearing problem in melee, from chmmravatar - Fixed a long standing memory leak relating to planet surface -PhracturedBlue - Scaled images no longer allocate/free memory all the time -McMartin - Planet spin on lander launch/return is now enabled -PhracturedBlue - Fix skipping after planet scan, landing (closes bug 31) -PhracturedBlue - Decelerate when entering orbit to give a smoother effect -PhracturedBlue - fix subtitle text overlap issues (bug 232) - 'Esc' now leaves planet surface (bug233) -PhracturedBlue - Fix race on exiting starbase (bug 230) -PracturedBlue - Cleanup shipyard door animation (bug 215) -PhracturedBlue - Misc .ani fixes; Fixes asteroid destruction crash (bugs 150, 155, 158) and somewhat fixes Mycon potrait (bug #183) -fOSSiL - Moved image scaling to DCQ thread; fixes scale-out-of-sync problem in melee -Mika - Fix lockup in cyborg melee (fixes 204 and 218) from chmmravatar - Added -g option to control gamma correction, from chmmravatar - Restored the CondBank to actually use condition variables properly (resolves a race condition under OpenBSD) - Removed aspects of the legacy graphics code that are never used or that are redundant. More 'C-like' use of the PRIMITIVE datatype. - Fix various graphics glitches during dialog. Especially Spathi Eye,and ZFP Closes #23, #156 - PhracturedBlue - Fix Syreen, KohrAh and Slylandro ship effects to not be screen size dependant (corolary to bug 93) - PhracturedBlue - Line clipping is now handled correctly; fixes #28 (one pixel corruptions) and #198 (beam weapons changing direction) -Mika - Vux warps in close (fixes bug 93) -from Nic - Fixed lockup on lander-report (Bug #144 annd 187?) - PhracturedBlue - Version # is now printed in the main menu, from Nic - Added PC Shipyard + Hangar power lines animation; (closes #176) -fOSSiL 0.2: - Shipyard/Outfit screens now use larger PC graphics; Outfit blueprint is properly aligned; from Nic - Key config is now saved in user dir too. melee.cfg too again. - SvdB - Added copyFile() - SvdB - Pure mode partial screen updates are now more efficient; fixed 'crossfades not finished' problem -Mika - Graduated colours for crew in shipyard, from Nic - Alien dialog fixes: Talking Pet, Utwig, Mycon, Syreen -fOSSiL - Updated all game, menu, melee and weapon sounds to original 3DO ones (extracted using various tools); some sounds were simply wrong: menu - "device success", weapons - arilou, slylandro, thraddash; others had bad sampling rates; (fixes #19) -fOSSiL - Fixed Melnrome repeating "Please do not mention this subject again" text (bug #145) -fOSSiL - Fixed load/save screen leaving characters when having more than 1000 units of some type of resources (bug #75) -fOSSiL - Lowered Drawable memory footprint, made Frame safer - Martin - Support for running without voice .ogg files present -PBlue - Slider should now work correctly everywhere -PhracturedBlue - Added 'nosound' driver and --sound=openal|mixsdl|none option; -a option has been removed -fOSSiL - Fix ZFP stuttering and some other random sound issues -PBlue - Correctly deal with multiply-mapped keys. This may fix some keys not being detected correctly on the Mac as well - PBlue - OpenGL mode now fully supports partial screen updates -Mika - Fixed melee ship selection-box bugs -fOSSiL - Added a 4th button to starcon.key 'Esc' now emergency-escapes -PBlue - Biadapt and biadv scalers now work in OpenGL mode too -Mika - Fixed lockup when fastforwarding through orz comm -PBlue - A new windows installer is now in builds/win32_install -PBlue - Added '-a' switch to go between OpenAL and MixSDL at runtime -PBlue - Melnorme will pronounce numbers now -fOSSiL - Added icons to win32 builds (MSVC and mingw) -fOSSiL - Removed the GraphicStrength code, since all that is handled with an arithmetic blit routine outside of the drawing thread - Added an improved version of biadapt scaling filter, working name "biadv" (use --scale=biadv) -fOSSiL - Removed SDL_mixer sound module - TFB_FlushGraphics keeps track of smallest bounding box that requires updating, allowing for faster scaling - Added a TFB_Canvas data buffer to let TFB_Image be more accessible - Added new graphics primitives - Added 'smooth' scolling for ff, frev (similar to the 3DO) - PhracturedBlue - New streaming code for openal/mixsdl. supports ff/frev in subtitles -PBlue - New sound module "mixsdl" (experimental) -fOSSiL - Fixed overlapping subtitle text while switch tracks -PhracturedBlue - New flash-thread cacheing scheme - PhracturedBlue - Voice-over / subtitle synch is done - PhracturedBlue - Optimized DCQ to be much smaller and faster - Added stat data in outfit screen (use --font=pc) - from Nic - Added fixed introx.mod, from fOSSiL - Fixed Orz .mod file, from fOSSiL - Added vertical alignment for subtitles (text runs off screen fix)-from Nic - Updated infinity text/symbol for RUs - from fOSSiL, Nic - Split away DCQ-specific code into its own header file - Added correct lander font - from fOSSiL - Added support for multiple menu hierarchies, and a few PC hiers. -PBlue - Fixed a potential semaphore race when suspending clock -PhracturedBlue - Function name conflict fixes for Mac OSX -by peterb - Minor fixes for pc-fonts (Outfit screen, gradient color swap) -by Nic - DCQ is now accessed uniformly by routines in gfx_common.c - Fixed OpenGL colors on MacOS X -Mika - Added a sane cmd-line naming scheme: --opt=(pc|3do) see --help for more -PBlue - Added new font effect (PC-lander messages), and set colors for text -PBlue - Use correct font for 'CAPTAIN', 'FUEL', and 'CREW' is status screen -PBlue - Added gradiated font support (for ship name), and PC-font option -PBlue - Minor fixes to PCMenu by fOSSiL, Nic, PhracturedBlue - Updated mingw support with better directions, and easier build -PBlue - PCMenus now suports 'settings', and menu font is correct -PhracturedBlue - Added '-b' option to get PC Menus -PhracturedBlue - Check for a deadlock in savedgames and try to continue -PhracturedBlue - Added an option ('-a') to display 'PC-style' coarse-scan -PhracturedBlue - Fixed deadlock races in new FlushGraphics method -PhracturedBlue - FlushGraphics now waits and notifies on a per-thread level - McMartin - No longer using SHGetFolderPath on Windows - SvdB - Key repeat is now enabled when typing text, from slayne - Capital letter bug in new input code fixed, from slayne - Oscilloscope now reacts to music when speech is disabled (OpenAL) -Mika - Rewritten input code (better and adds joystick/pad support), from slayne - Biadapt scaling for pure mode, from fOSSiL - Saving user data in "%APPDATA%/Application Data" on windows - SvdB - Melnorme comm fix, from TD. - Planet scan font character fixes (micro.fon), from fOSSiL - Temporary files are deleted on exit. - SvdB - Font png's no longer need to have alpha channel, black background with white pixels is enough -Mika - Added PC version intro/ending font, from VileRancour - Added files for intro and ending sequence, from fOSSiL; extracted using Mudrony's scripts plus his own work. - Added some corrected mods, from fOSSiL; extracted using Mudrony's scripts. - Replaced add_sub_frame with arith_frame_blit -PhracturedBlue - Crosshair in orbit leaving light trace to image in OpenGL mode fixed -Mika - Planet scan should now take ~2secs on all computers -PhracturedBlue - Updated earth image to look nicer (no vertical lines) -PhracturedBlue - Clock semaphore is now created with a value of 0 -PhracturedBlue - Rewrote Semaphore debugging code to be more useful - PhracturedBlue - Better fix for clearing load/save screen - fOSSiL - Implemented bilinear scaling in pure SDL mode - Mika - Planet surface is now smoothed, from PhracturedBlue - Implemented scanlines in pure SDL mode - Mika - Star sizes and colors are now correct in solar system, from fOSSiL - Captain portraits in melee are now updated properly after battle and bottom portrait always stays in correct place, from fOSSiL - Removed 2xSaI and SuperSAI scaling due to GPL incompatiblities. They should be reimplemented later. - Bucks print from wrong team in melee ship selection box fixed, from fOSSiL - Autopilot works in Quasispace when without fuel, from fOSSiL. - Negative shift warnings removed, from Fizban - Displaying correct lander images, from fOSSiL. - 3D planet now uses phong lighting, from PhracturedBlue - Put save data and temporary files in a seperate dir - SvdB - Fix OpenGL colors on big-endian CPUs, from Bryce McKinlay - MikMod now loops modules correctly (OpenAL), from Nic - player.fon/42.png corrected, from Parker - GraphicsSem usage reverted back in RotatePlanet, from PhracturedBlue - Pause/exit game dialog problem with planets fixed, from PhracturedBlue - Fixed lockup if sbuf_size was zero (OpenAL) - Planet surface changing color when using device fixed, from PhracturedBlue - Some race conditions eliminated, from PhracturedBlue - Earth / other slave shielded planet color issue fixed, from PhracturedBlue - Orbit/starmap related lockup fixed, from PhracturedBlue - 3D planet showing on starmap when in orbit fixed, from PhracturedBlue - Scan (single, interrupting) fixed, from PhracturedBlue - Defining DCQ_OF_DOOM lowers the DrawCommandQueue size to 512, to aid in simulating severe overload stresses on the machine - Removed TFB_FlushGraphics' dependency on GraphicsSem, which the new condition variable code both breaks and makes unnecessary - Scan tint is now cleared right after the scan, from PhracturedBlue - Recoded the DCQ to not sit on the heap, added debugging info - Fixed Outfit Starship and Shipyard graphics, from TDuck - 3D planet is now zoomed randomly from any corner, from PhracturedBlue - Flagship thrusters and modules one-pixel place fix, from TDuck - Earth topo map is now tinted as should, from PhracturedBlue - Fixed planet stuff when leaving surface with lander, from PhracturedBlue - RotatePlanet now holds GraphicsSem a shorter time, from PhracturedBlue - Added proper mutex usage to 3do_getbody.c, from PhracturedBlue - Scan uses now additive blit instead of transparency, from PhracturedBlue - Loading game saved while in orbit fixed (bg correct), from PhracturedBlue - Changed SDL_Delay to SleepThread in TFB_FlushGraphics - Rendering thread now broadcasts to a condition variable, stopping most of the problems we were having where a fast thread spams the DCQ with too many requests to handle in a timely manner - Fixed an unsafe memory freeing from sfx.c - Thread library now includes condition variables - Shofixti dialogue fixed to subtitles, by BlckKnght - Crash during loading from orbit fixed, from PhracturedBlue - Starmap issue when orbiting earth fixed, from PhracturedBlue - Oscilloscope is now implemented (OpenAL) - Moved initialisation of _MemorySem to memInit - SvdB - Planet scan is now cleared correctly, from l0ci - Flagship modules are now drawn correctly instead of one pix left, from l0ci - Planet code fixes, from PhracturedBlue - Build fixes for FreeBSD, from Max Horn. - Fixed typo in Thraddash text, from Dan Plimak. - Make HMalloc abort when no memory available, from Abaddon. - Replace malloc() calls by HMalloc, from Abaddon. - #include in main program, for OSX, from Max Horn. - Use sources for getopt() for all systems that don't support it, not only for Windows, from Max Horn. - Planet code cleanups, from PhracturedBlue - Changed some types to SDLKey in input.c to prevent overflows, from tamlin - Slider now moves in communications (OpenAL) - Fixed a DCQ bug where it wasn't freeing batches of graphics commands - > vs. >= bugfix on plangen.c, from PhracturedBlue - More appropriate names to ROSTER + 1 and ROSTER + 2, from slayne - Lines and colouring of planet surface when scanning, from PhracturedBlue - Melnorme bridge turns purple at the right spot in his conversation - Repaired a DrawCommandQueue invariant, from tamlin - Color transforms in communication merged into core animation thread - 3D planet is now antialiased, from PhracturedBlue - Hyperspace saving crash introduced by prev. patches fixed, from slayne - Precursor ship crew count is now placed correctly in melee, from wjp - Dialog choices doesn't go off rectangle in right anymore, from wjp - When saving in planet scan screen, screen is now redrawn, from slayne - Commas causing pixels to appear in planetary reports fixed, from slayne - Team names switching when selecting next ship to fight fixed, from slayne - More memory leak fixes in 3do_getbody.c, from PhracturedBlue - Fixed memory leak in _ReleaseCelData, from PhracturedBlue. - Fixed mutex deadlock in 3do_blt.c, from tamlin - 'additional credits' amount for Melnorme correct now, by Windplume. - Spheres of influence now move correctly in starmap, from l0ci@hotmail.com - Linux OpenAL fixes (music plays now as stereo) - Fuel giveaway bug fixed, from steve@blckknght.org and Windplume. - Starmap fuel range calculator and actual consumption matches now - Collision detection is now pixel-perfect (fixes Sa-Matra, BUTT missile, etc) - Fixed lander position sign bug which was introduced by previous fixes - Initial display of planet surface on landing is at correct position - Planet scan is now properly erased when cancelling/landing - 3D planet view when entering orbit is now implemented - TFB_DrawCommandQueue->FullSize was uninitialised. - Typo 'cultrue' for Thraddash fixed. - Autopilot indicator no longer blinking on starmap and combat - Entering a star system lockup/messed graphics fixed - Position of planet info icons/texts is now correct and centered - Yehat had no subtitles. - Incorrect position of 'empty slot' and 'team name' in supermelee fixed 0.1: - Initial release uqm-0.6.2/sc2/WhatsNew0000600000175000017500000003715110543204460013166 0ustar joeyjoeyThis file tries to organize and describe the changes between releases. Changes are broadly classified into the following categories: - New Features: These are either elements of the original games that were first implemented in this release, or actually new capabilities that are visible to the user. - Bugfixes: The removal of visible Bad Things from the code. - Internal Changes: The removal of invisible Bad Things from the code, or changes in the way the program itself is structured. These are unlikely to be of interest to you unless you plan on coding extensions. Version 0.6 ------------- NEW FEATURES - Netplay! You can now engage in Super Melee over the Internet. - Key configuration is now entirely in-game. - UQM now compiles and runs on 64-bit systems. BUGFIXES - The Quit button (F10) now works properly when used during the introduction sequence. - Various small fixes to text and conversation logic. INTERNAL CHANGES - The setup menu now reads all its text from the content, easing translation. - The MOD player for PC-style music can now be linked against an external version of libmikmod. - Various code cleanups and memory optimizations. Version 0.5 ------------- NEW FEATURES - The Starmap is searchable! Type / then the beginning of the constellation name, and you can tab through all possible completions. - New 'hq' scaler, based on Maxim Stepin's "HQ2X" scaler. See www.hiend3d.com/hq2x.html for more details. - Scalers can use MMX/SSE/3DNow! instructions for significant speed improvements. The "Processor pack" is necessary for compilation of same on VC6. - Imported DOS versions of many graphics; these have richer palettes and so generally look better - There's a proper credit roll at the end of the game now. - Superior Planet handling: topographical maps scaled far more precisely; optional 3DO-style throbbing slave shield; planets are finally rotating spheres instead of spotlit cylinders or rectangles. The old PC-style "Entering Planetary Orbit..." screen is back. - Setup Menu far more complete and easy to use, and selections made in the Setup Menu will actually persist when you restart the program - Added support for the Tremor Ogg Vorbis decoder (avoids floating point math) - Home, End and BackSpace keys work as you'd expect in text input. - Most of the game works with Unicode properly now, and so, with proper font characters installed, will work with non-Latin alphabets. (On Windows, Unicode input requires a very recent version of SDL.) - Text may be input with the joystick again, as on the 3DO. The available characters are stored in content/lbm/joyalpha.txt. - The intro now plays only when a new game is started. - Color depth is now determined entirely automatically. BUGFIXES - Only SELECT and CANCEL trigger the fade-to-black at the end of a Super Melee, solving the issue of invisible "Really Quit?" menus for Super Melee. The "quit during fades" problem in general is still extant. - Many dialog, and comm animation, and general graphical fixes - Keypress status is not reset when entering battle mode, so (for instance) Melnorme ships can continue to charge a shot across battles. - The Melnorme would occasionally strip off Plot Points as part of a fuel deal. No longer. - Bugs in the original code prevented certain ships from properly spawning in "uncontrolled" space. The "wilds" are now a bit wilder, as apparently originally intended. - Venus's atmospheric density was incorrectly corrected in the 3DO version. It's been correctly corrected now. - Scheduled plot events work properly, even when the game suddenly skips ahead in time. - Fixed version checking in unix build scripts. SDL 1.2.10 is now recognised as newer than 1.2.9. - Spliced communications can be safely skipped past now. - Fixed fast escape weirdness (bug #619) - Threading system no longer assumes that there is no thread 0; this permits compilation on AmigaOS. - Relative paths and fallback paths work properly now. - Scalers now use surface pitch instead of image width - this is reported to solve many strange display problems in non-OpenGL mode on Macs - Ending sequences may now be safely paused. INTERNAL CHANGES - Added the rest of devel/ and users/ documentation into MSVC .dsp files. - Control scheme upgraded. Old versions of keys.cfg will no longer work. - PNG transparency info (tRNS chunk) is now set properly, based on info in the .ani files. - Paletted images should render much faster now, and collisions between mods are less likely. - New font engine: fonts are loaded and treated as alpha-channel-only images, with font effects handled as backing images. - Melee works properly with alpha-channel graphics new, even when mipmapped. - Lander report drawing handled more sensibly now - Binary resource indexes have been replaced with textual ones. - All spritework is done internally in 32BPP. - Removed MikMod i/o hacks. - The temp files for representing star and group data are now kept in memory instead. - Separate config_win.h file for build.sh builds on Windows - Lowered some animation rates to reasonable levels, lowering CPU usage. - Changed comm subtitle caching scheme. Should kill the "blue comm screen" problem forever. - Refactored setup menu code to use generic widgets. - Cleaner build output. Set '$MAKE_VERBOSE' to 1 for old output. - Improved dependency tracking for unix build system. "./build.sh uqm depend" is now only needed for checking for new source files. Version 0.4 ------------- NEW FEATURES - Savegame slot defaults to the last one used during this play - PC intro and ending sequence are now present - 3DO intro and ending movies are supported for those who have these movies from the 3DO CD of Star Control II - Improved slave shield graphics - Added a new -l option to produce logfiles - Added a new 'triscan' scaler derived from scale2x - Made the fact that self-destructing ships grant resources more obvious - Added a "config dir" option for holding saves and melee information - Cocoa hooks - Setup menu now permits configuration of some options. They do not yet persist past program quit, though. - Added a "--version" option - Melee images are now based on the (richer) DOS content - 3-step melee zooming as per the PC version is now implemented - It is now possible to complete the game without ever allying with the Starbase (if one is insane; this is known on the forum as "Beating The Game Differently" - but bugs and plot elements preventing this have been fixed or evaded under this circumstance). BUGFIXES - Fixes to the Quit Confirmation dialog - Collisions/encounters with "invisible" fleeing ships gone - Other ships insystem remain in proper locations after planet landing - Fixed some keyboard "focus" problems where flight controls were being cleared at inappropriate times, or interfering with menus - Graphics fixes - Subtitle timings work in the absence of oggs - Conversation summaries with Melnorme no longer crash - --contentdir argument may now have spaces - $HOME isn't required for Unix systems anymore - Fuel estimates fixed (original bug) - Fuel usage on planet landing now correcly reported on all versions - MOD music will play on big-endian machines under high-quality now - Space marines die in a self-destructing Scout - ZFP speech is properly vertically aligned now - Various odd behaviors when loading in HyperSpace now fixed - Quitting from the Roster screen no longer crashes - Many dialog fixes - The "Blue Comm Screen" problem no longer occurs - Combat Energy computation in Outfit Flagship screen corrected - A game crash that manifested when pausing after 85 minutes has been corrected - Main menu version number drawn more consistently - Transparency bugfixes - 3DO ending credits, planets in battle - Content packs may also be named ".uqm" - these are really still zip files, but you can't expand them by accident. - One may now configure a joystick without crashing the game if the joystick is not present - Music volume normalized throughout the game INTERNAL CHANGES - Thread system completely reworked to provide more detailed thread information, and to prevent resource leaks - Sound code is now virtualized and separate from game logic - Fine-grained control of menu sounds - Input system fully unified - all parts of the game use the same basic structure now - Build scripts made more robust - Window-drawing code was lifted out of confirm.c and made more general - Lots of debugging functions - Unicode support for game dialogs and fonts - Lots of code cleanups - Documentation of more internals Version 0.3 ------------- NEW FEATURES - PC-style shipyard graphics, complete with animated power lines - Selling ships in the shipyards has slightly different controls that make it harder to sell ships accidentally - Main menu displays version number - Added a '-g' option to control gamma correction - Planet spin has been improved - Trilinear (mipmap-based) scaling in melee - PC-style conversation summaries have been implemented - Ship location display in status bar matches original more closely - Game flags (such as AWARE_OF_SAMATRA) that were ignored by half the game (even in the original) now are more universally available - Oscilloscope and Mini-Map have borders now - Commander Hayes won't let you rescue him until he's explained his predicament - Confirmation dialogs are now menu-based - Positional sound effects are available for OpenAL - Delete key works on Super-Melee team editing - Exit key from the Main Menu will quit the game - Quit option available in GAME menu - New Main Menu graphics: Setup (not yet implemented) and Quit are options at the Main Menu now - Cubic resampling in high quality audio mode - PC-style alien outtakes when game is completed - 2 more ship slots in melee, as the PC Star Control 2 had. - All the standard melee teams from the Star Control 2 PC version. - Support for 50 savegames, instead of just 10 - 'CREW'/'BATT' instead of icons in melee when using PC menus BUGFIXES - Text entry doesn't freeze up lander reports anymore - VUX warps in at proper range - Distance-based ship effects (Syreen, Slylandro, Kohr-Ah) were screen size dependent - Line clipping fixed - Various communication animation glitches solved - Various melee crashes solved - Various race conditions eliminated - Scaling of graphics is handled by the rendering thread now, solving issues where the background and object scales would drift out of sync - Subtitle text is clipped more carefully - Objects can no longer be scaled to total invisibility - Various dialogue fixes - Crossfade glitches eliminated - Pause and Exit keys function properly everywhere - Visit Count overflow with Yehat and Chmmr patched - Wav loader and color transforms are now endian safe - Menu glitches when leaving the "GAME" menu are gone - Druuge transactions no longer baselessly increase crew cost - Lander speed has been retimed to match 3DO - Audio resampling works now correctly (less cracklings) - MixSDL buffer underrun handling fixed - Some memory leaks have been eliminated - Fixes and speed improvements on bilinear, biadapt, biadv scalers - Various minor graphics glitch fixes - Crew death on planet is now counted properly in all cases - Mouse cursor is now hidden in fullscreen mode - Guardian in Blazer mode being drained by DOGI will no longer result in a non-blazer Guardian with Blazer effects. INTERNAL CHANGES - Legacy graphics code stripped down tremendously, a lot of "poor man's object orientation" has fallen away too. Many uses of function pointers with only one possible value replaced with simple direct calls. - Crossfades require you to explicitly cache the screen before drawing the transition target - User Input code has been completely rewritten - File I/O code has been completely rewritten - Subtitle drawing is now cached as its own sprite; communication screens are much less graphics intensive now - DRAWABLE_DESC uses separately allocated arrays for its frames Version 0.2 ------------- NEW FEATURES - Planet info "coarse scan" information available and properly rendered, either in 3DO way (symbols) or PC (text) - 3D spinning planet in orbit window is present, with antialiasing and phong lighting and an animated approach - Pixel-perfect collision detection; Spathi/Mycon are thus playable, and the game is now beatable - Build system enhanced and generalized to handle OpenBSD and FreeBSD cleanly. - Oscilloscope display works in communication now - Color-shading in planet scans - Earth with its slave shield now functions properly - Outfit Starship and Shipyard graphics re-extracted - Save data and temp files are put in a separate directory now - Star sizes and colors are properly differentiated. - Planet surface is smoothed, blurred, and randomized slightly when it's magnified - SIS Status window fully implemented (including gradiated fonts from PC version) - Dialogue "slider" shows how far along the speech is; rewind/forward works - 'ESC' alone lets you emergency-warp-escape - Optional PC version menus - Preliminary support for MacOS X (needs more work) BUGFIXES - Melee screens cleaned up, SuperMelee menus work. - Subtitles now render for all alien races - Major editing of subtitles to match more closely the speeches - Speech and subtitles are now synchronized properly - Autopilot indicator doesn't take over the top of the screen anymore. - Entering star systems on autopilot doesn't crash the system. - Planet scan is properly erased when cancelling/landing - Initial display of planet surface on landing is at correct position - Spheres of influence now move correctly on the starmap - Melnorme correctly compute the required additional credits - Team names switching when selecting the next ship to fight in melee fixed - Commas left dots behind on planetary reports; this is fixed - Screen resets properly after loading/saving - Dialog choices wrap properly - Precursor ship crew count now placed correctly in melee - 'Cued' color transforms in conversations occur at the right time now - SIS correctly predicts its own fuel usage now - Melnorme no longer give away fuel - Flagship modules are properly aligned - The PC soundtrack now loops correctly - Lander upgrades were drawn incorrectly - Autopilot now works in QuasiSpace without fuel - Captain portraits in melee are updated properly now - If you have over 1000 units of a resource, those numbers are properly cleared INTERNAL CHANGES - SDL_mixer has been abandoned in favor of either OpenAL or the new "MixSDL" library built on the basic SDL_audio routines - Color transforms in communications are merged into the core animation thread now, improving speed and stability - Much more flexible handling of commandline options - All allocated memory is allocated through 'safe' routines that abort if the allocation fails. - Thread library now includes condition variables - Threads can tell the rendering thread to sleep until everything they've requested is done - The rendering thread has been recoded to use no heap space and to have a far smaller memory footprint. - Added a special #define, DCQ_OF_DOOM, which simulates severe overload stresses. - SAI and related scalers removed due to GPL incompatibilities; similar algorithms reimplemented under GPL. - Files for the intro and ending sequence have been successfully extracted - Rendering thread routines are somewhat more modular than before - Created a new set of graphics primitives that's much easier to use - Only parts of the screen that actually changed are updated - Input code rewritten entirely - Various functions have their names changed to avoid conflicts with core library routines on OS X Version 0.1 ------------- Initial release. uqm-0.6.2/sc2/fixcrlf0000700000175000017500000000041710543204457013065 0ustar joeyjoey#!/bin/sh find src -type f -name "*.[ch]" -print0 | xargs -0 ./subst 's/ $//g' find src -type f -name "*.ci" -print0 | xargs -0 ./subst 's/ $//g' find src -type f -name "Makeinfo" -print0 | xargs -0 ./subst 's/ $//g' find doc -type f -print0 | xargs -0 ./subst 's/ $//g' uqm-0.6.2/sc2/BUGS0000600000175000017500000000027610543204460012164 0ustar joeyjoeyAll known bugs and missing features are listed in our online bug database, which can be found at http://bugs.uqm.stack.nl/ New bugs that you may find can be reported at the same location. uqm-0.6.2/sc2/uqm-indent0000700000175000017500000000024510543204457013510 0ustar joeyjoey#!/bin/bash indent -bad -bap -bl -bli0 -bls -cbi0 -cdw -ci8 -cli4 -i4 -hnl -l76 -nbc -nbfda -nce -nfca -nlp -nprs -nsob -pcs -psl -saf -sai -saw -sbi0 -ts4 -ut "$@" uqm-0.6.2/sc2/uqm.lsm0000600000175000017500000000202510543204457013020 0ustar joeyjoeyBegin3 Title: The Ur-Quan Masters Version: 0.6.0 Entered-date: 2006-12-15 Description: Port of the classic game 'Star Control II'. Keywords: Ur-Quan Masters, Star Control, game, space adventure, Super Melee Author: Toys for Bob The Ur-Quan Masters developers Maintained-by: Serge van den Boom Mika Kolehmainen Michael Chapman Martin Alex Volkov Primary-site: ftp.sourceforge.net /pub/sourceforge/s/sc/sc2/ 1225567 uqm-0.6.0-win32-installer.exe 11580000 uqm-0.6.0-content.uqm 18980071 uqm-0.6.0-3domusic.uqm 114823409 uqm-0.6.0-voice.uqm 21917799 uqm-0.6.0-macosx.dmg 1567422 uqm-0.6.0-source.tgz Platforms: Windows, Linux, FreeBSD, OpenBSD, MacOS X, BeOS Copying-policy: GPL for the C code, custom for the graphics and audio content End uqm-0.6.2/sc2/build.sh0000700000175000017500000000213010543204460013124 0ustar joeyjoey#!/bin/sh # Build helper # Copyright (c) 2002 Serge van den Boom # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # You can start this program as 'SH="/bin/sh -x" ./build.sh' to # enable command tracing. if [ -z "$SH" ]; then if [ `uname -s` = SunOS ]; then # /bin/sh of Solaris is incompatible. Fortunately, Sun ships # a decent sh in /usr/xpg4/bin/ nowadays. SH=/usr/xpg4/bin/sh else SH=/bin/sh fi export SH fi $SH build/unix/build.sh "$@" uqm-0.6.2/sc2/INSTALL.msvc0000644000175000017500000001420710550151300013500 0ustar joeyjoeyThis file describes step-by-step how to use Microsoft Visual C++ to build The Ur-Quan Masters. It assumes you want to install the Microsoft Visual C++ Express Edition, which can be downloaded for free from Microsoft. If you already have another version of MSVC++ installed, you can skip step 1, and you do not need to add the Platform SDK paths to the include and library locations in steps 5.2 and 5.3. The files and locations are for compilation on 32 bits systems; on 64 bits systems some will be slightly different. 1. Install the Microsoft development environment 1.1. Install Microsoft Visual C++ 2005 Express Edition: - Download the installer from http://msdn.microsoft.com/vstudio/express/visualc/ - Run the installer, and follow the instructions. There's no need to register your copy of MSVC++ to use it for compiling UQM. 1.2. Install the Microsoft Windows Platform SDK: - Download the installer from http://www.microsoft.com/downloads/details.aspx?FamilyId=0BAF2B35-C656-4969-ACE8-E4C0C0716ADB - Run the installer, and follow the instructions. 2. Install the tools needed to install all the requirements: 2.1. Install TortoiseSVN, a Subversion client which we will use to check out the most recent development version of the UQM source: - Download the installer from http://tortoisesvn.net/downloads - Run the installer, and follow the instructions 2.2. Install WinZip, which we use to extract the compressed .zip files. - Download WinZip from http://www.winzip.com/downwzeval.htm - Run the installer, and follow the instructions 3. Install the dependencies 3.1. Prepare the build location Create a folder "Build" in "C:\"; this is where we will put our dependency packages. 3.2 Install the SDL SDK: - Download SDL-devel-1.2.11-VC6.zip from http://www.libsdl.org/download-1.2.php - Use WinZip to Extract the .zip file in "C:\Build" A folder "SDL-1.2.11" will be created. 3.3 Install the SDL_image SDK: - Download SDL_image-devel-1.2.5-VC6.zip from http://www.libsdl.org/projects/SDL_image/ - Use WinZip to Extract the .zip file in "C:\Build" A folder "SDL_image-1.2.5" will be created. 3.4 Install the Ogg Vorbis SDK - Download http://www.vorbis.com/files/1.0.1/windows/OggVorbis-win32sdk-1.0.1.zip - Use WinZip to Extract the .zip file in "C:\Build" A folder "oggvorbis-win32sdk-1.0.1" will be created. 3.5 Install zlib: - Download zlib123-dll.zip ("zlib compiled DLL") from http://www.gzip.org/zlib/ - Create a folder "zlib-1.2.3" in "C:\Build\" - Extract "zlib123-dll.zip" in C:\Build\zlib-1.2.3\" 3.6 Install OpenAL - Download http://developer.creative.com/articles/article.asp?aid=45&file=OpenAL11CoreSDK.exe - Run the installer and follow the instructions - Create a directory AL in "C:\Program Files\OpenAL 1.1 SDK\include" - Move all the .h files from "C:\Program Files\OpenAL 1.1 SDK\include" into the "AL" directory. 4. Install the UQM files 4.1. Checkout the UQM source - Open the folder "C:\" - Right click on "Build", and select "SVN Checkout..." - In the "URL of repository" field input https://sc2.svn.sourceforge.net/svnroot/sc2/trunk/sc2/ - In the "Checkout directory" field input C:\Build\sc2 - Press ok and the checkout will begin. This may take a while. A folder "sc2" will be created in "C:\Build\". 4.2. Copy the runtime libraries where they can be found by UQM when run from MSVC++. - Copy the following files to "C:\Build\sc2\": - "C:\Build\SDL-1.2.11\lib\SDL.dll" - "C:\Build\SDL_image-1.2.5\lib\jpeg.dll" - "C:\Build\SDL_image-1.2.5\lib\libpng12.dll" - "C:\Build\SDL_image-1.2.5\lib\libtiff.dll" - "C:\Build\SDL_image-1.2.5\lib\SDL_image.dll" - "C:\Build\SDL_image-1.2.5\lib\zlib1.dll" - "C:\Build\oggvorbis-win32sdk-1.0.1\bin\ogg.dll" - "C:\Build\oggvorbis-win32sdk-1.0.1\bin\ogg_d.dll" - "C:\Build\oggvorbis-win32sdk-1.0.1\bin\vorbis.dll" - "C:\Build\oggvorbis-win32sdk-1.0.1\bin\vorbis_d.dll" - "C:\Build\oggvorbis-win32sdk-1.0.1\bin\vorbisenc.dll" - "C:\Build\oggvorbis-win32sdk-1.0.1\bin\vorbisenc_d.dll" - "C:\Build\oggvorbis-win32sdk-1.0.1\bin\vorbisfile.dll" - "C:\Build\oggvorbis-win32sdk-1.0.1\bin\vorbisfile_d.dll" 5. Set up the The Ur-Quan Masters project in Visual C++ 5.1. Import the VC6 .dsp file: - Open C:\Build\sc2\src\msvc++\ and double-click on "UrQuanMasters.dsp". Visual C++ 2005 Express Edition will start. Confirm when it asks to convert the VC6 .dsp file. 5.2. Setup the additional include locations for the project: - Still in MSVC++, right click on 'UrQuanMasters' in the Solution Explorer, and choose "Properties" - In the left part of the screen, select "Configuration Properties", then "C/C++", and then "General" - In the right part, select "Additional Include Directories", then click on "..." - Add the paths to the "include" folders of all of the dependency libraries: - "C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include" - "C:\Build\SDL-1.2.11\include" - "C:\Build\SDL_image-1.2.5\include" - "C:\Build\oggvorbis-win32sdk-1.0.1\include" - "C:\Program Files\OpenAL 1.1 SDK\include" - "C:\Build\zlib-1.2.3\include" 5.3. Setup the additional library locations for the project: - Still in the project properties pages, in the left part of the screen, click on "Linker", then "General" - In the right part, select "Additional Library Directories", then click on "..." - Add the paths to the "lib" folders of all of the dependency libraries: - "C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib" - "C:\Build\SDL-1.2.11\lib" - "C:\Build\SDL_image-1.2.5\lib" - "C:\Build\oggvorbis-win32sdk-1.0.1\lib" - "C:\Program Files\OpenAL 1.1 SDK\libs\Win32" - "C:\Build\zlib-1.2.3\lib" 5.4. Remove unnecessary dependencies - Still in the "Linker" part of the project properties pages, in the left part of the screen, click on "Input". - In the right part, select "Additional Dependencies", then click on "..." - Remove odbc32.lib and odbccp32.lib 5.5. Add user32.lib - Still in "Additional Dependencies", add "user32.lib" 6. Build The Ur-Quan Masters - Still inside MSVC++, press F7 If MSVC++ asks to save the project, confirm. If everything is right, you should now have a working uqm executable. You can press F5 to run it from MSVC++. uqm-0.6.2/sc2/COPYING0000600000175000017500000014075110543204460012537 0ustar joeyjoey The Ur-Quan Masters Copyright (C) 1992, 2002 Toys for Bob, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be entertaining, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. A copy of the General Public License is included at the end of this document. The content -- voiceovers, dialogue, graphics, and music -- are copyright (C) 1992, 1993, 2002 Toys for Bob, Inc. or their respective creators. The content may be used freely under the terms of the Creative Commons Attribution-NonCommercial-ShareAlike 2.5 license (included below, and also available at http://creativecommons.org/licenses/by-nc-sa/2.5/). The content may also be copied freely as part of a distribution of The Ur-Quan Masters. The documentation -- excluding documentation that is part of the code or otherwise clearly governed by the preceding licenses -- may be used freely under the terms of the Creative Commons Attribution 2.0 license (included below, and also available at http://creativecommons.org/licenses/by/2.0/). ---------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ---------------------------------------------------------------------------- CREATIVE COMMONS LICENSE Attribution-NonCommercial-ShareAlike 2.5 CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. License THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. 1. Definitions a. "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License. b. "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered a Derivative Work for the purpose of this License. c. "Licensor" means the individual or entity that offers the Work under the terms of this License. d. "Original Author" means the individual or entity who created the Work. e. "Work" means the copyrightable work of authorship offered under the terms of this License. f. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. g. "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, Noncommercial, ShareAlike. 2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws. 3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: a. to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works; b. to create and reproduce Derivative Works; c. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works; d. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission Derivative Works; The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights set forth in Sections 4(e) and 4(f). 4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: a. You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any credit as required by clause 4(d), as requested. If You create a Derivative Work, upon notice from any Licensor You must, to the extent practicable, remove from the Derivative Work any credit as required by clause 4(d), as requested. b. You may distribute, publicly display, publicly perform, or publicly digitally perform a Derivative Work only under the terms of this License, a later version of this License with the same License Elements as this License, or a Creative Commons iCommons license that contains the same License Elements as this License (e.g. Attribution-NonCommercial-ShareAlike 2.5 Japan). You must include a copy of, or the Uniform Resource Identifier for, this License or other license specified in the previous sentence with every copy or phonorecord of each Derivative Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Derivative Works that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder, and You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Derivative Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Derivative Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Derivative Work itself to be made subject to the terms of this License. c. You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in connection with the exchange of copyrighted works. d. If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Derivative Works or Collective Works, You must keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or Licensor designate another party or parties (e.g. a sponsor institute, publishing entity, journal) for attribution in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and in the case of a Derivative Work, a credit identifying the use of the Work in the Derivative Work (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Derivative Work or Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit. e. For the avoidance of doubt, where the Work is a musical composition: i. Performance Royalties Under Blanket Licenses. Licensor reserves the exclusive right to collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public digital performance (e.g. webcast) of the Work if that performance is primarily intended for or directed toward commercial advantage or private monetary compensation. ii. Mechanical Rights and Statutory Royalties. Licensor reserves the exclusive right to collect, whether individually or via a music rights agency or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover version") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions), if Your distribution of such cover version is primarily intended for or directed toward commercial advantage or private monetary compensation. f. Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor reserves the exclusive right to collect, whether individually or via a performance-rights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions), if Your public digital performance is primarily intended for or directed toward commercial advantage or private monetary compensation. 5. Representations, Warranties and Disclaimer UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. Termination a. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Derivative Works or Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. b. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. 8. Miscellaneous a. Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. b. Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. c. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. d. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. e. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor. Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, neither party will use the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. Creative Commons may be contacted at http://creativecommons.org/. ---------------------------------------------------------------------- CREATIVE COMMONS LICENSE ATTRIBUTION-2.0 CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. License THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. 1. Definitions a. "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License. b. "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered a Derivative Work for the purpose of this License. c. "Licensor" means the individual or entity that offers the Work under the terms of this License. d. "Original Author" means the individual or entity who created the Work. e. "Work" means the copyrightable work of authorship offered under the terms of this License. f. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. 2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws. 3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: a. to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works; b. to create and reproduce Derivative Works; c. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works; d. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission Derivative Works. e. For the avoidance of doubt, where the work is a musical composition: i. Performance Royalties Under Blanket Licenses. Licensor waives the exclusive right to collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public digital performance (e.g. webcast) of the Work. ii. Mechanical Rights and Statutory Royalties. Licensor waives the exclusive right to collect, whether individually or via a music rights agency or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover version") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions). f. Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor waives the exclusive right to collect, whether individually or via a performance-rights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions). The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved. 4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: a. You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any reference to such Licensor or the Original Author, as requested. If You create a Derivative Work, upon notice from any Licensor You must, to the extent practicable, remove from the Derivative Work any reference to such Licensor or the Original Author, as requested. b. If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Derivative Works or Collective Works, You must keep intact all copyright notices for the Work and give the Original Author credit reasonable to the medium or means You are utilizing by conveying the name (or pseudonym if applicable) of the Original Author if supplied; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and in the case of a Derivative Work, a credit identifying the use of the Work in the Derivative Work (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Derivative Work or Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit. 5. Representations, Warranties and Disclaimer. UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. Termination a. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Derivative Works or Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. b. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. 8. Miscellaneous a. Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. b. Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. c. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. d. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. e. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor. Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, neither party will use the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. Creative Commons may be contacted at http://creativecommons.org/. uqm-0.6.2/sc2/INSTALL.mingw0000600000175000017500000000470710543204457013663 0ustar joeyjoeyInstructions for building UQM in Windows with MinGW and MSYS ============================================================ First, download and install the latest version of MinGW and then MSYS. (You can get them from ). You'll need all the libraries described in the INSTALL file in CVS. You should get the 'mingw' development build for SDL, and follow the instructions to install it into mingw. All others will be either for win32 or VC. These are the files you need to download: http://www.libsdl.org/release/SDL-devel-1.2.8-mingw32.tar.gz http://www.libsdl.org/projects/SDL_image/release/SDL_image-devel-1.2.4-VC6.zip ftp://opensource.creative.com/pub/sdk/OpenALSDK.zip http://www.vorbis.com/files/1.0/windows/OggVorbis-win32sdk-1.0.zip http://www.gzip.org/zlib/zlib122-dll.zip You can now do either of the following: 1) Copy the DLLs for each library to \[MinGW]\lib. Copy the header files for each library to \[MinGW]\include, (where [MinGW] is the directory where you installed MinGW) except for the Ogg Vorbis headers -- copy the folders (ogg and vorbis) containing the header files to the include directory. 2) Within MSYS set C_INSTALL_PATH and LIBRARY_PATH to point at all of the respective include and library dirs where you installed them. i.e. something like: export C_INCLUDE_PATH=/mingw/include/SDL:/c/VClibs/SDL_image-1.2.4/include/:/c/VClibs/OpenAL\ 1.0\ SDK/Include/:/c/VClibs/oggvorbis-win32sdk-1.0/include/:c/VClibs/zlib/include/ export LIBRARY_PATH=/c/VClibs/SDL_image-1.2.4/lib/:/c/VClibs/OpenAL\ 1.0\ SDK/libs/:/c/VClibs/oggvorbis-win32sdk-1.0/lib/:c/VClibs/zlib/lib/ NOTE: If you use the 2nd method above, you need to include the path to SDL in C_INCLUDE_PATH (but not in LIBRARY_PATH) The Ogg Vorbis headers want a header that is not included with MinGW. To get this file, download and put it to \[MinGW]\include. Now you're ready to build. Start up MSYS (the installer put an icon in your Start Menu and on the desktop). cd to the UQM directory. It'll be at /[drive letter]/[path to uqm]. ./build.sh uqm config It should correctly detect everything, and give you a menu. Next run './build.sh uqm depend' (just to be sure) and lastly: ./build.sh uqm If you did everything correctly, it should now build successfully. To run the built executable, you should copy all the required DLLs to the same directory the executable is in, or copy them to your Windows directory. uqm-0.6.2/sc2/build/0000755000175000017500000000000010552600273012605 5ustar joeyjoeyuqm-0.6.2/sc2/build/win32_install/0000755000175000017500000000000010552567174015311 5ustar joeyjoeyuqm-0.6.2/sc2/build/win32_install/ultron.bmp0000600000175000017500000006233210543202111017303 0ustar joeyjoeyBMÚd6(–9¤d  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúÿüÿÿø¾ºÆ4+Ë=>Ôleä4:·Ã¼,$±2,›4%S[Êˇkb7:'ÒÀ©ÿñÚÔ΋'42J¥SBâwÿª£ÿ¹«ùÁ¨è²±ôµ±ä›—Î…²~xm^[u‹‰¦Ö×›äìŽÒÙ’ÊÏCF¤¾¾öÿÿýþúa[V)O[d†“Zw€_rzeqwADH€}ÿþÿúøøÿÿÿÿþÿÝ×Ü?8=>3;H=G@2=L2JN4L[DZL7M?,?G5F-, $3+<(*5  {WW®||§qvru~bbnb`XUQ ?-DYI`E5L*3%  /(/@7AA5A<-;@.?I6IY:[\=^^?`^?`\=^]>_aBceFg]=UdD\dC^`>\_<^b=ce@hbl`6_gFhQ9QOBPºÁºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿûúþó¼¸Ä /2ÎBDØŒ…øAG¾"$ɽ%¬1(4+Pd  ¸¾‡UR3@0)ÛÍ»ÿïÞÍÌ,')i2%›H9«IAªOK·miÅŠÓª§á±­Å‹…ŒRLˆ^WcWSFXWHnn,5QXc”/PS§¼½ðûùùúöÍÊÅ7A/FN-@G7EK3TUBU5#4 :+@2(9:38)3;'E (;%*!   I@U=1G>1GVF]\JaA+C8 8N6N3$2  -,A/@G5FF4EC*FG.JK2NL3OI0LF-IE,HE,HQ4KZ=T_@[bC`cBdbAdcAf`=ea6ag@f^?^`Jb FIGõûöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ýøüýóľÉ"5#ÎHJذ¬ÿNW¿*,ÐÀ#¬3(¢ =9Sw ¡ª‚;:&?31âØÇüíÝÍÊ“(4.9(EQD?0 A*(A$=5C(9/($"AVWNox‚¡ª‡¡§)>@}ŠŒï÷öýÿþôõñöÿÿøÿÿï÷÷ñ÷öûÿþýÿüÿÿüôöðñêñskr   % #@&>Q:PO:PA.A 7(68)>;(9S?L( ?17d]` &.T]fXeuX`q?AS,&9D3HbH_dD\Y5MaB_`A^S6P86 8$;<(?A-DD0GF2IG3JH4KJ6MW9R\>W\=XaB_aA`_>`eDffEhnJnX7YZ?Y<(; ÅÆÄýÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúþùÿÿ÷ØÐÚ7&ËMQØËÇÿZb¼-0Ï Ä%°8*§ DAQ€ ¢¦ƒ93 D8.éÞÃÿîÙÕΕ!.#/kkGJ< >%"   ( OH?klhëóò»Ä;ÈÏ®·»°·ºæëìûÿÿøûùýÿþÿùùÿúùÿûøÿÿüÿÿüîðêûÿùýÿûrfr#"bPaYGXF2EC,B' %B+AD/E**('7(6=.<K4J_@UfCW[AO '4*;H(>J#=I4P[EcnNlwRp{GmySu‚Tkz@M]+)<%+B+AoRif:af=bfAcbBa]B\S[^@]Z)?9&9G5FF7E 6%:P6Mf@VlE[J,?)/*:F8Yb>kxEq~@jw6`mBlyO{ˆHt:gt:pw7hpAjsVtSdq&-<  ]8Z`=_eCbeFccF`_E]ZBZXAWSCUJ:L=-?.0!# 34B'AH-GZ?YaG_^D\gMecIaU@VN;NSBPA:?ÿþÿÿÿþö÷óÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúû÷ÿÿõÿüÿ')*9'Àdiäëèÿ‘˜×9=Ñ',Ç//±?7› F17\ ™—x42 :;+±¼›±¹¨ ²‰-SE([LtV¿“(Éž=‚j6 øÿÿûÿÿùúñÍʼ0+€zm}xoÿÿûÿþÿÿþÿÿÿÿõóó÷÷÷ùùùÿþÿöøùÿÿûÿÿüÿÿüÿÿþÿüýùöøš™*,XBZhOiS8R`B_bCbbAcdCefLdP6N@)?<'=<)%AR9UUB\\¡Ëº‘¹¾ŸÑÇ.<1]T » 1¶›3RNöüÿ÷ùúÿûöļ¯QH:zsdtpeÿÿøûÿúñòîÿÿþéêèÿÿÿýúüú÷ùýúüÿÿþÿÿÿÿþÿöò÷¶±ºKEP,%4W>XP4Q]A^gHgZ9[a=ajFj^9_Y?WfLd_H^I4J3 34"3>/=4%3L9NG0FC'>L/H15=7NPXo[nƒNlwOeq@KY(   !-5CO)0- I5HaD^eBdi@e]>[]>[_@]cDafGdfGdbC`^?\S9WhNl`GaZBZO9LA+=?*9&   ·²´ÿþÿÿÿþüø÷ÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýúëÿþÿbca   ]bÕèäéÊÑÿNRà1;ÎW^Í‹ŠÒ’›¤}Œ?LJ0=M‚ ›4B7ftŠÊÊp±Íšåó *)9d,é¸TР@YA ÍÏ×÷ôöÿÿûŽ‚vG:,wn`‚qýüòúÿûøÿùîôï111urt³®°çáæ÷ÿþ²·¸MPT  (?4H=2FV:WaEcbCbgFhbAdc>d`9_kCl]C[W=UYBX_J`?,? *):+9A,BE0FJ2JB-F (C=VIMf#,G  3(J(9S3DL1AN7FS-?Y7HN3C@-<=3@/-9"   C?pBljBeg?bd<_e=`h@ciAdh@cf>a^Db`Fd56  A-:>*6  ¾¹»ÿþÿÿþÿÿýüÿÿþÿýùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøï÷ðúÿÿ…†‚bGDÝ×ÔÏâçÿejÝ!%ÑETØ…žÈœ¨¬zp‡VPQ&)-Yœ,:1_qRÌÚ`´ÎT¬Ê  ‘]áÈ‚½¥Q>&ÿÅÿÿÿÿÿûtvjBE6NOEyÿÿþøÿûùÿûõúù  )(  3-E0?N9HN9HJ5DaB_aB_aB_aB_aB_aB_aB_aB_a?g^?d^Ab_Fb\G]G5F      M.KW8UbC`fGddEbaB_aB_cDaaB_aB_aB_aB_aB_aB_aB_aB_F1G''  RFRSDRPN7MX@X`F^bGabC`bC`aB_`A^`A^`A^`A^aB_aB_aB_aB_aB_aB_aB_aB_aB_];ZcCbgJd\D\F3F0!/!#2&2  --Q7OhMg;0@ JBMÿüÿÿýÿíííýÿþýÿüÿÿÿÿÿÿýýýùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùüóöÿüõøýôñí9`]ØìáÿúÿÿÔÜúgeÝ,%Ì37®*0Y<@ Ošœ4ht_m[ÎÙj°Ç;œ° ;µçУ¯ QQKãßåÿÿÿÿÿú@B6adUCD:~~xÿÿþúÿþöûúüûÿ/'1#"WBX_E][>XdGhaDe_Bc^Ab]@aZ=^T7XO2SaB_aB_aB_aB_aB_aB_aB_aB_a@cbAd_@a]>]^C]^F^VAWL7ML2JK1IN1KR4QZ:Ya?^d?ad?afGdcDa`A^`A^aB_bC`bC``A^aB_aB_aB_aB_aB_aB_aB_aB_d;`c=ad?abBadFc[@ZA)A(')(G7HB2C*) #"@,?ËÄËÿýÿûúüýÿÿêíëøýûþþþûûûúúúýýýÿÿÿÿÿÿþþþüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûöþþýüÿÿÿü(gcÍããûùÿñôÿÿ„…ç*)Í-5¸'2d%MRSšž0ku^kmÓß„½ÓB¢²íÖÞÿéÎÁ­l^T$þúÿÿÿÿýý÷')vyjEF<€€zÿÿþûÿÿûýþÿýÿ7-9%$W@VcF`cDaaAd^>a\<_^>acCfcCf\<_V6YaB_aB_aB_aB_aB_aB_aB_aB_dAcfCebBa^?^^?^_C`ZA]S:VI+HH)FI)HP.MZ5Wd;`h?el@gdEbaB_`A^aB_dEbeFccDa`A^aB_aB_aB_aB_aB_aB_aB_aB_e`]<^\;][:\aB_aB_aB_aB_aB_aB_aB_aB_fAahCceCb_?^^?``Ab[>_U8YF)CK-JV7Tb@_hEgjDhh?dd;`aB__@]`A^bC`eFcfGdcDa`A^aB_aB_aB_aB_aB_aB_aB_aB_dBahFegEdb@_a>`fCefCec>`VBU6"5  SLSÒÐÐÿÿÿûûûûýýûÿÿøýüúÿÿïôõÿÿÿýýýüüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ýøôúÿúöÿÿüøjeV&"tššøãåÿÝ×ÿ_VÜ%Ø$FÈ%K{+-4eo[›/fs@€‹žæò¹Ñç[­¹ >6)ÿè×ÿ÷ÂßÃo‡t7+ÿûÿÿÿÿÿÿûƒ†w78.~~xýûúÿþÿÿýÿÿûÿ9*8/._D^aA`dBafGbbC^^?Z^?Z`A\aB]`A\_@[aB_aB_aB_aB_aB_aB_aB_aB_eA_gBbe@`_<^_>`bBe_>cW8]K3KQ7OU:TZ=W]>[`>]b@_c@baB_`A^`A^bC`cDacDabC`aB_aB_aB_aB_aB_aB_aB_aB_aB_Z@X\BZ\A[_B\bC`dDccA`_=\fOeXDW7%6D5C”žàÙàêéíÿþÿÿÿüö÷óýÿþûþüûÿÿúÿÿòúúøÿÿûûûüüüüüüûûûþþþÿÿÿþþþúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøþùøþÿûöÿÿÿûº³¢ ]=5‹€àˆsÙ5$É (ç?ÀJy6UX4eoZŠ–2gtU‘¬ëùÅÓé^¬¹ @8ɳŠÑ³f´›3‹x-N;&ÿýÿüúúÿÿûŸ¢“:;1}}wÿÿþýüþýùþüóý/ ../dGab@_`=_U5NG'@=6E%>[;TiIbgG`_?XaB_aB_aB_aB_aB_aB_aB_aB_f@^eA_b=]^;]_>aeChcAi];cL8KR=S[DZaG_`E__A^_@]_@]cDabC`aB_`A^`A^`A^aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_VCV\H[cLbbJb^C]]?\bC`hHgU>TaLbYGX+,LCMÊÆËÿþÿüþþÿÿûÿÿûýÿüõúøúÿÿùþÿøÿÿøÿÿþþþÿÿÿÿÿÿýýýýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûüøÿÿÿ÷öúÿûÿïêùUOb$ÏÒãÚ*!ÌRWÑ8v1uŒ9€„ mt}Mjo_§§ÏãôÀåûr°Èfc^@=8 nkfÿýÿÿþÿöó빸ªtrgЇÿýúøúûÿþÿÿüÿ=)GŠM”˜ ns|[x|Z¤¤Íçõ«Öéb©½ Á¾¹ñîéöóîÖÓνºµ½ºµ÷ôïÿýÿùóôÍÉÄ»º¬mk`wsnÿÿüûýþýüÿîçîH4G]C[R3PQ/NI1IO7OM5MS;S[C[F.F22:":\D\cJd]D^\@]`A``?aa@beBdaB_aB_aB_aB_aB_aB_aB_aB_Z;X^?\aB_bC`aB_`A^`A^bC`_@]^?\^?\^?\^?\_@]`A^`A^aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB__3\kDj`?aP7Q?/A"$#'TXYûÿüùÿúýÿþýÿþôôôÿþÿÿþÿþûýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ÷÷÷ÿþÿüúÿÿûÿÿúÿ¢¬C;È35¿!'¨!‘ ]1X–ŠS›¢ y~‡‰¤¨M˜–Ðì÷«Þî_°¿ËËÅ÷÷ñÿÿûþþøùùóüüöÿÿûÿüÿÿùüÇþÉǼ‡…{{vÿüûýÿÿôó÷ÏÈÏT@S_E]cDadBaL4L779!9L4LU=US;SD,D--F.F\C]bIcY=Z]>]a@b^=_hEgaB_aB_aB_aB_aB_aB_aB_aB__@]aB_cDabC`aB_aB_aB_cDaaB_`A^_@]_@]`A^aB_cDadEbaB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_i?hb;alKmbIcR?R7-:   ±±±ùùùùùùÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿüûýÿþÿüúÿóðùÿûÿ¶­ÿW[©Q,$*0G/9FtuK–ž z|†¨¾Ã[ ßûÿ¦Ýæ^µ¿æçãÿÿüÿÿüýþúúû÷ÿÿüÿÿüúòüÿþÿÓÐÌ__SPNF„}ü÷øýÿÿúùý¾·¾ZFY\BZhIfiGfU=UX@X?'?--D,DYAYT`\;]gDfaB_aB_aB_aB_aB_aB_aB_aB_aB_bC`bC`bC`bC`bC`cDadEbbC`bC`bC`bC`bC`bC`cDacDaaB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_nGm\8\]=\iMjN8PB2DH;I!$ž›ÿþÿÿÿÿÿÿÿñññÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÿÿÿùøúø÷ùÿþÿúùýÿþÿõòÿ¨¯Â–§°ÁÍÓÛÚãâáñfs‰-KdE–žpnzµÄÇr­©ç÷þ—ÅÌa²·ýþüÿÿþÿÿþÿÿþúûùÿÿþøù÷ÿûÿÿûÿ¾¼» GH?²°¯ÿÿÿùûüÿþÿ®§® \H[VV9!911A)AN6NO7O9!9/0M4NeIf`A`^=__>`eBdaB_aB_aB_aB_aB_aB_aB_aB_`A^`A^`A^`A^bC`cDadEbdEb`A^aB_aB_bC`aB_`A^^?\]>[aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_\8\kJlQ2Q[?\[B\>(@E2G;+=[[[­°®íðîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿúúúþþþÿÿÿûûûÿÿù°º®¾ÏÁ÷ÿôÿûúòëøpwUlŒiÂÌ LHT»¿Äqœ™ääêÃàå†ÅÉ ýÿÿöøøòôôýÿÿýÿÿýÿÿûýýüøÿüúÿÿÿÿöøòÿÿùÿÿûÿÿþ÷öøøúûÿþÿ~w~ZFYbH`eFckIhgOgU=UcKc_G_22))A)AE-EU=U67A(B_C`cDcbAcdCedAcaB_aB_aB_aB_aB_aB_aB_aB_`A^_@]^?\_@]aB_bC`aB__@]bC`bC`cDacDacDabC`aB_`A^aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_^=_jIkZ;Z_A^fJgN3MC*DN5OH5F9&7+)+#* y|zûÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿþøù÷ÿÿüÿÿüÿüü‡ˆ„¬·­ûÿùÿÿüÿýÿq}‡CaliËÓTMZµ±¶63,(15HKñöõûÿÿûÿÿûÿÿñöõøýüûÿÿþúÿõòûúúúÿÿûúüöüýùÿÿÿÿþÿýÿÿöõù?8?ZFYfLdU6S`>]W?W\D\W?W`H`aIa77''N6NV>VF-G?&@S7TdEdcBdbAceBdaB_aB_aB_aB_aB_aB_aB_aB_aB_`A^_@]_@]`A^_@]Z;XW8U[C$AI*GQ2OV7TaB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_[<[_@_]>]`A`fGfX8WG'FK+JM0II/FA.?  ‘‘‘ûÿüùÿúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûü¬§¨Ù××ÿÿÿÿÿÿýÿÿ~ƒ‚:?> Öá#.06=õóóýÿüõþûøüýÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÿÿÿûûûüüüÿÿÿþþþüüüÿÿÿÿÿÿy~M;LLc>$<,,R9SZA[Z>[cDca@b^=_c@baB_aB_aB_aB_aB_aB_aB_aB_gEd`@_]>[_B\`E_\D\YBXXAW[C[[C[\D\_G_`H`]E]V>VP8P2423T9SaEbbCb`A`aB_aB_aB_aB_aB_aB_aB_aB_b@_bBa`A^fIc[@ZF.FF/EA*@D1B1/ zryÿýÿÿÿÿöù÷ùÿúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþùúÿÿÿüüüôôôýÿÿ¢¡ ¨Þé[`C]\A[P8PL5KN7MR4QP2OM/LL.KM/LQ3PW9V[=Z`MbL9N13% &65R6SbCbbCbaB_aB_aB_aB_aB_aB_aB_aB_dBaaA`_@]gJdX=WD,DG0FC,B<.: ïéîüùûùùùöù÷ýÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿýþÿÿÿÿÿÿÿÿÿýÿÿ±¶µ¬âí]{†öôôýÿüøÿþ÷ûüÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÿÿÿýýýÿÿÿÿÿÿýýýÿÿÿÕÕÕ,-gSfYBX ¡”œ~}y!¬­c—˜N™—WviI a=ad?ggDf))UR3R_@_aB_aB_aB_aB_aB_aB_aB_aB_fDc`@_^?\eHbU:TE-EK4JB+A%$ ›•šÿþÿÿþÿöööÿÿÿúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûüÿþÿþüüüüüÿÿÿüþþµº¹·íø}›¦×ÕÕûÿúöÿü÷ûüÿûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿÿÿÿÿÿÿóóóÿÿÿÿÿÿwww\I\XAWM3J Í¿Å<94.2&¶´z†‡E””TŸ—oU7P_>`U6S:":R9SZA[_C``A`]<^cBdhEgaB_aB_aB_aB_aB_aB_aB_aB_hFe`@_\=Z\?Y[@ZU=UQ:PN7MS;SR:RO7OJ2JF.FG/GM5MR:RB/DH5JS=UX?YS8RJ.KM.MU6UaB_aB_aB_aB_aB_aB_aB_aB_fDc`@__@]bE_Q6PF.FK4J9"8vvvÿÿÿúúúÿÿÿÿÿÿÿþÿú÷ùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿþÿÿþþþþþûûûõ÷÷ÈÍ̪à눦± ¼ººöúõõþûúþÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûÿÿÿÿÿÿÿÿÿõõõÿÿÿØØØ!!!#'cOfZBZI-D̾ÂJG?38)ÜÕ´¥£s‹ŒTš—j 8"._E\[AXM5ML3MY@Z`Da`A`bAc`?afCeaB_aB_aB_aB_aB_aB_aB_aB_`>]aA`aB_Z=WL1K:":&% &'I6KA.C@*BK2LW]P1N<932=%=O8NYBXUKWQGSPFRRHTPFR@6B&(02E/GG.HH-GO3PQ2QH)HaB_aB_aB_aB_aB_aB_aB_aB_a?^aA`aB_^A[L1KF.F@)?rzsúÿûùÿúýÿþÿÿÿóðòÿþÿûõúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿüüüþþþþþþýýýþþþµ±¼Êçë‘™™ÿûýÿÿüøÿùÿÿùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿùûüöûùúÿüüþþñéó A'?dG^[>W^E_VAZ vqz¡¤¢ ÿí½ÖǾ¹zÆÆŠ^Y2'hFee6naB_aB_aB_aB_aB_aB_aB_aB__C`[=ZbCbdCegCgiBhc9bkAj_BcL.Q<FiKtT6_Z=dZ?a`EfTC^SC[[KbVD[ZD]`A^mEh[/TZ6b?B7 /G3@M:KH3LW@`aB_aB_aB_aB_aB_aB_aB_aB_i=fh?eb=_\>[O8NG7H))ðððöööýýýÿÿÿÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÿÿÿÿÿÿÿÿÿýýýüüüÿÿÿ³²¼Êèí ˆ‹ÿúüÿÿþøÿùÿÿûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿùûüùþüúÿüùûûļÆP6NhKbbE^\A[_Jc=5?ååå©•rÇ»‘ÊÇ”³¶„igE!`B_c:maB_aB_aB_aB_aB_aB_aB_aB_^@]`A`dEd^=_Z7Yc?cjCid=c\C_X?[nUqP7QR;Q7!3;$2  @(:C%BwVx];cX9Z[AY5/:%4<(;P:S\EeaB_aB_aB_aB_aB_aB_aB_aB_f:alChfCeV9S;&VkSkYAYV;UZ>[]A_aB_aB_aB_aB_aB_aB_aB_aB_f=be@bX9VL2JG5F-!-CZe@`bAc]A_WB[-',ÿÿþïæóRPV"!—Ÿ˜?DB  VEZY?]aB_aB_aB_aB_aB_aB_aB_aB__;_]9]_>``A`X=W\D\bMcVCX  ”}½½•¶¸}¢£_Œ‹A™™Mš˜J’Ž?™”E¯©bÁ½ˆ@B%]dar{‰ UBUcMeZA[Y=[lMlW7VhHgaB_aB_aB_aB_aB_aB_aB_aB_e@bb@_Q4NJ3IJ:K «§­ÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúúúýýýÿÿÿÿÿÿùùù   Wo{«âçašœ-3÷õûûþÿúÿÿÿüýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿýÿÿûÿþöýøýÿÿ%'22Y?We?]hCcX5WdGhZC_8(9¢žÿûÿýüÿûÿÿóùø  gRheGdaB_aB_aB_aB_aB_aB_aB_aB_kDj]9]kJlaEbZBZjWlH;K ¤Ÿœ£¤ŠÇʘ§ªeŒŽB›™K˜”F“‘Wš–U§ŸY¦œVüƒXW5OWMîùÿlai UAXYA_Y;^fEh^;]iDdaB_aB_aB_aB_aB_aB_aB_aB_b@_bC`P5OD0C2%3 ùøüûýþÿÿÿÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿþþþÍÍÍ]aB_aB_aB_aB_aB_aB_aB_aB_`6_f?efEgV:WfSh1$4  –‘šýùÿ˜—“ ¹¾‡·ºu¥£\˜ŽN³¥jàÜ×ÿÿòÿÿÝðܬ½­~ÄĶöþþÿÿþw~'-S:\];dc>fd<_i@_aB_aB_aB_aB_aB_aB_aB_aB_bC`\?YB*B6$5|x~øúûûýýþþþüüüüüüþþþÿÿÿÿÿÿÿÿÿüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿþþþûûû.yÁËhÁÅV[àæíÿúÿÿþÿíÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýùþýÿÿûÿþúÿüõ÷÷,$.00cIaG0FiRh]E]gLfYYe?]aB_aB_aB_aB_aB_aB_aB_aB__>a`<`c=a^>]_H^ ,4-ôÿõÿóÿ‰z‚cXBºµ~ÆÀuǽi·ªTξkõíÈÿÿæüøÛÜÚÂtvc óúóúÿüôÿûion L3McBd_9]fBfbAcZ;XfGdcDa\=ZbC`eFcaB_dEb_>cW;XH5F  îðêûÿü÷þùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿÿÿÿþþþùùùõõõ%CT‘ÌÖ}ÇË5eiÆÉÑÿìôüö÷íÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿûýþúÿýùÿûûýý4,600_E]@)?V?U\D\`E_]@ZfGd_?^U3R%$+(<):_E\gHcd?_nFiaB_aB_aB_aB_aB_aB_aB_aB_eDgiEi^:^hFeW@V Œ’ñÿòÿ÷ÿ›‘—™—gÑÏŽ¸²kÒÆ€ÕŃÊâÜ׸áÞ‚l -1&ûÿûòùöïûõ*./bIcdAc`<`_;_bAc[=&<^F^[@ZaD^fGd[;ZgEdUHXNAQS@UcKckOlcBd_;_hAgaB_aB_aB_aB_aB_aB_aB_aB_Y:[_>aa=akHj]C[ ›››úÿùýûÿÔÑÓ,. ±±ƒ¾ºŠ½´ˆ¾²Š½¹˜]ZEssgÛÞÕýÿüöûùúÿÿ 0 1eIf]9]gCg_>`cDc]>[bC`bC`aB_cDa_@]]>[cDa[Ca46 äáÝÿÿûûÿúûÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿÿÿÿþþþúúúööö|xƒCPX4MQ—¨«ÿýÿÿýÿóóóñÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿüþÿ÷üúöýøýÿÿSKU++`F^H1G%$`H`_D^`C]bC`W7ViGf_Jc\F_[B^\@^\<_^&60C:,$ ððäüýôÿÿûýÿþ÷ùùÁÂÆ M:ObCb[7[`<`]=\Z>[aB_aB_aB_bC`bC`_@]`A^fGdK9P$(}yxÿÿùÿÿûøûùüþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿùÿþýÿðøøúþÿûö÷ÿþÿùùùóþûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿýÿÿûÿþ÷þùýÿÿphr##dJbSVeJd_B\_@][;ZdBaW:[\?`\?`[;^^>ab@edBggEjaB_aB_aB_aB_aB_aB_aB_aB_^Ea_@_gDfY3WcDa30 ÑÌÎøÿÿïöóûÿûÌÒÇ‚†{……ƒ€||vw……yËË¿ÿÿøÿÿùüû÷ÿÿþíííÊÊÊ'* aHbeDfiCgZ6ZdEd_F`dEbaB_`A^aB_aB_cDaeFceFc4*; PKMæåáúúôÿÿüÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýýýýÿÿÿÿÿÿÿÿÿÿÿÿÿüûÿÿþÿýüÿÿþýþüÿÿþÿÿþ÷ùùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿýÿÿûÿþùÿûúüü™‘›aG_XAW=%=cHb`C]`A^bBacA`jIkhGieDfhGikKj`@_[<[eFeaB_aB_aB_aB_aB_aB_aB_aB_`GaiMjb?agAe`;]^AZ#9.8ãèæûÿþùþüýÿÿýÿÿôóõÿþÿÿüÿùúöÿÿü÷øöýþüþþþïï C.DjKja;_hAgV3U`DaYAYdEbaB_aB_`A^_@]eFcdEbX9V¾¾¾ÿÿûöùðÿÿüÿþþÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿúÿùÿÿùÿþùÿþùôøóöûùúûùÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿýÿÿûÿþúÿüûýýƾÈVWdG`aB_aB_aB_aB_aB_aB_aB_aB_Q;SdHe`=_nHld?ahIdO9L &'%×××ÿþÿòñõÿþÿÿþÿÿþÿÿüþöúûûÿÿóõöýÿÿêéëTQSJ7LeLf^=_^7]b;aa>`cGdYC[bC`bC`cDa_@]^?\fGd]>[B#@(,-øü÷ýÿùûþõüû÷þûýþúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿýýýúúúóÿøûÿøþüôÿÿûûÿüúÿþÿþýÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿüþÿøýûúÿüýÿÿäÜæ K1IbKa:#9N3MgJd`A^]=\cA`iCajDbgD_cC\aD[cH\aFZYASaB_aB_aB_aB_aB_aB_aB_aB_ZD\bFceBdc:_lCh_=[jPg[HY]W\¾Äüøþÿýÿÿÿÿÿÿþúþÿ¸½À”—›YZ^   @[eFcV7T0.€†…ûÿüüÿøÿÿùþýùÿþÿÿúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûþþþþþþÿÿÿúúú,,,q=la8]-+K?KaO`]@ZkFhaB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_VJV=1=    '(G.J]@a_@e\:baB_aB_aB_aB_aB_aB_aB_aB_pHdd=]a:`lJrR7YTCXH=Eéééÿÿÿÿÿÿúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿýýýþþþÿÿÿlllg9cfAcH.F!" ?>aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_ZGZVCVNE4BL9JR=SZA]_BcbAfb@haB_aB_aB_aB_aB_aB_aB_aB_d;ZhAakGkU4Y\DbaQc \\\øøøÿÿÿÿÿÿúúúüüüüüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿüüüöööÿÿÿ··· ]7[cCbcIaS?RB/BE.D[=ZnKmaB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_ZU\AUaFZSAR[HYaLb`H`Z>[W8YZ:]_=baB_aB_aB_aB_aB_aB_aB_aB_g@`kFfb?aZ=^^HaC3DÁÁÁÿÿÿüüüÿÿÿúúúüüüøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿýýýúúúÿÿÿèèè[>XbH`cIa]E]aG_hKedEb];ZaB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_`9_d>bgAegBdd?_b>\c?]d@^U@VXCY^F^`E_`A`_@aa@cbAdaB_aB_aB_aB_aB_aB_aB_aB_mEhgBdX8WbGaTAT ;8:üüüÿÿÿúúúÿÿÿúúúÿÿÿüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿþþþÿÿÿÿÿÿûûûÿÿÿQQQ0/VBUbJb[>X_?^dBacA`hFeaB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_iAje=fb;ab;ad>bfAce@`c>^^Ea\C_^B_aBacDceEdeBdc@baB_aB_aB_aB_aB_aB_aB_aB_b<`]:\eHbS=P>/= »¹¿ÿÿÿùùùþþþÿÿÿùùùÿÿÿÿÿÿýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿÿÿÿÿÿÿÿÿÿøøøÿÿÿ²²²>1?`H`cA`f=bb9^\9[fFeaB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_e@hd?gd?eeAegDfgDffDcdBa\?`\?`^?`^?`_?^a?^b=]b=]aB_aB_aB_aB_aB_aB_aB_aB_aa_?baBcbCdaBa`B__B\^A[]>ca@ecCfcBdc@be@`hCckGeaB_aB_aB_aB_aB_aB_aB_aB_eBjeFgW>R@19"ÒÐÖüûÿüüüýýýÿÿÿûûûþþþÿÿÿÿÿÿûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÿÿÿüüüÿÿÿÿÿÿïïïÿÿÿv{y_X_\E[h?de7bi;ejEg^?\aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB__De]Ca[A_ZA]Y@ZY@ZX@XW?W^fa?d`?b_<^`;[b>\f@^aB_aB_aB_aB_aB_aB_aB_aB__;e]>_E/A ywwýýÿùøÿüüüÿÿÿÿÿÿøøøÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü¯¡§aM`[>_`?dd@d_:ZkF`aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB_aB__B\S8R20*)Q=PiVi^L]P@QaD^_B\\?Y[>X[>X^A[bE_dGa\E[ZCYYBX]F\`I_]F\Q:PG0FV;UcF`gIfbBab?ahCei@eh?eXD[N=R"#<5:éäåÿÿüúúôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿuqm-0.6.2/sc2/build/win32_install/orzshofixti.bmp0000600000175000017500000045565610543202111020367 0ustar joeyjoeyBM®[6(¤:x[  âÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓãÝÖÞÝÏààÐÌÌÀƒ€|,**:87šœ–×ÓÈãßÔâÞÓáÝÒâÞÓáÝÒâÞÓßÛÐâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓäàÕßÛÐàßÑÙØÊÞÝÓ´²ªGFB532E@B]XWš–‘ÐÎÄáàÒåâÔãàÒÞÛÍäÞÑäÞÑßÛÐÚØÎÎÌÄÎÏÆ¾¾¸vxrW[\FFF93.XLB‹yh¨’y°˜z¬“q«–w«–w«–w«–w«–w«–w«–w«–w©”x«–w«”t®˜u¬—wª–w©–{žsQMH62-]TJ–ˆr°™yµšu¯•p°—u¤ f²ÉÀ㙟«y“pys\\WHH<:C:1)5#+=,GH?VQB‚Še¦·„ ¯|¢›p¨˜t°•z³•z°–x­™v«—t¨“t¬—x¬—x«–w«–w«–w¬—x­˜y­˜y¡˜§˜œ¬˜¤«–™¥’ƒ¥“tª—v­—{¯ r£“‚§“°§Ð¡Î©™»¢”˜âÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÛÖßÝÒààÎØØÊ¥¢5331/.tuqÐÌÁâÞÓâÞÓáÝÒâÞÓàÜÑãßÔßÛÐâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÝÒãàÒçæØÝÜÎââ֯ļZYU/-,723>:9TQLœš’ÇÅ»Ù×ÌÝÛÑßÝÓãßÔâÞÓàÜÑáßÔÝÛÑ×ÖÌâá×ÒÑÇ–˜˜lkg]TJo^£Žxª”x«–w®™y«–w«–w«–w«–w«–w«–w«–w«–w©“w«–w«•r®˜u«—t¬˜y¦•{Šyd;76;5.pfU£’w­—s±—r²˜t¬“sª•y¥±}¸Ô˜®ºŠ¥Ÿzž™r—‘lˆ|`p`PQUB@M=DD>>51@<1ZWHxl`–…k£v©“z¤t©•v°|«–v«“u¬—x­˜y­˜y¬—x«–w«–w¬—x«–w¨˜£“¦”¥¬—·¨•°¥˜©”~®šq£–p¡‘‹«™¸¤—Å –Å¥™ÃŽ›âÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓàÙÖâàÕßßÍßàй·¯GED-++VWSÈĹßÛÐáÝÒáÝÒâÞÓàÜÑäàÕàÜÑâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâßÑâßÑàßÑÝÜÎÝÝÑÐÎÆ~~x421OMMTRQKJFIICZXPtqlž›—ÄÁ½ÑÐÆÜÛÑâàÖÞÜÑâàÕßÜÎäáÓÚ×É¡£ki_f\K’€i­—{«–w¨”uª˜y«–w«–w«–w«–w«–w«–w«–w«–wª“y¬—x­—t¯™u©•rª˜{žŽwqbO943YPFi¬˜y¬–r¬–s®™z¬—|®’ §|²Ë“´¾¤œw¢™n¬v®–x¤Šr‡€esqYlbQ`TJEB:?:7OAC[KEbVLkcRqhTƒxb™‹t¨”{³„©”u¬—x­˜y¬—x«–w«–w«–wª•v®“x§’w¢•‡¤˜¤¨—¼ª˜½§–£ “…¨–w©˜‹¬ž ‘Šqpr^\bSKUâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓߨÕäâ×ÞÞÌßàо¼´WUT,**GHFÿ´ÝÙÎáÝÒáÝÒãßÔàÜÑåáÖâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÞÐâßÑÞÝÏåäÖÜÜÐØÖΠ šB@?EFD‚€¬­©y``ZED@A??OJLVWNopg©¨žÑÏÄáÞÐßÙÌßÚËÍÆ·€w\VIxkU¨“w®—w«–vª˜y£•x«–w«–w«–w«–w«–w«–w«–w«–wª“y¬—x¯™v®›v¦“pª˜{™ˆs`P?A:7ul_Žt«˜w°x«˜w¦“x§•~®–rŸ©m¤Á|°½‡¨Ÿy©™t«–w°|´–{¥“v ’u—ƒjs]eeSOVIDB:C8@=89@A8?B3GD5ZP?l\Km\¥q©”u¬—x«–w«–w¬—x¬—x«–w²“t²›u«›vœ’€œ‘›§œ½¥›Æ”Š´¤Œx¤~v`SQF@;FD9PLGáÝÒäàÕáÝÒÞÚÏáÝÒâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓàÞÓÞÜÑæãÕàÜÑÊȾ|zr-.*697º·²ØÖÎÝÛÐâáÓßÞÐàßÑåáÖâÝÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓÞÚÏàÜÑâÞÓæâ×ÞÚÏÇøb^S8::`_[°­¥ÕÏÄ»µ¨˜”‰fe[DD>7244/00,+QNJ——‘»¼³¶·­Ž…Z[W_YLŒ~g¨–y¨•z¨•z§‘uµ™z«–w«–w«–w«–w«–w«–w«–w«–w¤—}¤“xª–w«•r­–v­œvl[C>5AG6{j¬x²—|ª•u®—w«—xŸ•w¬—x®™z±œ}±œ}¯š{¬—x«–w«–w±’y±“z°•{«“w«–{ ‹ur_Pn\Qe[I[Q@KD5=9.75-6738::9>=SGCneWŠ€h¤s¶•{º•y°•s¨šp®”v²™w­—nª˜o¤™y˜•–•·~¼st~RVKLC:R@?TONcjs‚}’âÞÓãßÔáÝÒâÞÓæâ×âÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓàÞÓÜÚÏàÝÏáÝÒØÖÌŽŒ„340031ª§¢ÕÓËÝÛÐàßÑÞÝÏÞÝÏãßÔáÜÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓãßÔâÞÓâÞÓáÝÒâÞÓáÝÒÜØÍ“„@@@IHD…ÑÍÂåßÔâÞÓÌËÁ»¼³Ž‰ˆ^ZY<950-):72BB4:7255/=2.63+;;/VPC}m`˜ƒt¡{£˜}¬—w§’r©’r¯›x¢”x†|rhapPJmD9SKG<_VBugmŒ…¨™œÏœ™×äàÕâÞÓàÜÑáÝÒäàÕâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓßÝÒàÞÓßÜÎâÞÓÍËÁw673031–“ŽÕÓËâàÕáàÒßÞÐÞÝÏâÞÓáÜÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÝÒãßÔäàÕâÞÓâÞÓàÜÑäàÕ·³¨XYWA@YRC‰{e­˜y®˜u©”u¬—|¬—{¬”v«–w«–w«–w«–w«–w«–w«–w«–wª–w¬—w­—t¯šz¥”z€tbJA7@:3upWŸŽt°˜|«—x¦•tª•vª’t®–zª•vª•v«–w«–wª•v«–w«–w¬—x§›w§štªšu¬™v¥–v€fZR;yu]§–{¥”zžŽw“†pƒwendSZQCLE6I?8961-20,21120?;6XSJlg^ƒg™‰r©–¡Œv}lRYK8OC=ZNTp^“‹~˜˜”‚™’ ”Ι—ã’’ÒäàÕâÞÓáÝÒàÜÑáÝÒâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓßÝÒäâ×àÝÏæâ×À¾´qog895142|ytÐÎÆäâ×àßÑàßÑßÞÐâÞÓâÝÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓãßÔâÞÓâÞÓäàÕßÛÐâÞÓÈĹxwsA>:da\·´¬ÚØÎÝÛÑçåÛáßÕáßÔÝÛÐÞÜÒßÝÕÄÁ¼ƒ€|SONJHGvjXœ‹p¯–t¯•q¯˜x©–{©”xª•v«–w«–w«–w«–w«–w«–w«–w«–w­—t®–r«“o¯›|™‹xbZM92)PI@Ž„f¥“v®–x¨•t¦—v©šy«–v²–w«–w«–w«–w«–w«–w¬—x¬—x¬—x¨•t©•rª—r©”tŸvugUNH5mlW§’s§“tª•yª—|¦•{žu”†oŽ€iwl^`WMLIA?B969034+830721DA3SMBi^VdYK[P‰wf¨’v¬—{«—xª–w«–wª•u¬•u­—t­—t©’r¯—s®—w§”‡¥“𢓛ŸŽ…›‹n–ˆl„wgf\\TMTDCG865;72F=9>;,=<>D9Y[N\vseˆ«£”ØãßÔàÜÑäàÕÞÚÏäàÕâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓàÞÓáßÔáÞÐäàÕßÝÓÊÈÀjkg/20;83«©¡ÓÑÆÞÝÏâáÓÝÜÎãßÔâÝÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓåáÖãßÔâÞÓáÝÒáÝÒåáÖâÞÓãßÔÜ×ÎŒ‡43/EFDº»·àÞÖäàÕåÞÏàÜÑçãØÞÚÏãßÔÝÛÐÝÛд²¨ig]E=6WH8Žy^ª“sª•v«™|¨•t¬–r«–w«–w«–w«–w«–w«–w«–w«–w¥”z«–w§’s{m[41-=;:€se­•w©”x«–z±”y¸–x¦—p¡±|Âß ¢½{¬—x­˜y­˜y«–wª•v«–w¯š{²~¬²ƒ¶ÇŽ²Î’‘®}:I.[WEŸˆrµ—t¨•z¨–yª•yª–w«–w«–v­–v­—t¬—x«˜w£“| •˜¦œº©¹¥—‘¤”o®™f®™z ŠšŒ˜‹ƒŽkfhVPKI@769=68274=;35C3431=ÝÛÑßÝÓáßÔáÝÒäáÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÝÒáÞÐäáÓáÞÐâàÕáÞÖ°¬§B=:1/.dc_ĺÚÙÏÝÛÐÞÝÏáÝÒãßÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÜÓ³°¨FC?310‡†‚ÐÎÆßÝÒáÞÏáÝÒãßÔáÝÒâÞÓÞÚÏãßÔäàÕÈĹ’’ŒLLF2/*D?6kbT›w¬š}©”t©”u­˜x°™y¬•uª“s©”tª–w¬—{¬–s¤“yrgYD:3ZQGŠ‚k¡›v¥¡p™¬sª¤uª›t«—t±•r°¯}¼ßœ©Ó†º¡«”z¦•z¡›x«¸„²ÑŽ±Þ•®ã™©Á€”©rkvV=;1UPAŒe¢¢r¡œu¦¡p§žrªšu®–x³•z³•z®–x«˜w¯’w©—x › œÞ ”æ¡”¤ª™x®•{¬—w­˜|§š´¥›Ý¤™©¥—z«–¥“t¢”}ž‘ƒ†…¥qr¬nfgaTFD@EÛÙÏâàÖáßÔÞÚÏãàÒâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÞÐãàÒáÞÐÞÜÑåãÙÇþ\WT0.-CB>¿½µÙØÎàÞÓàßÑáÝÒâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓÄÁ¹c`\/-,_^ZÆÃ¾ÞÜÑáÞÏàÜÑâÞÓáÝÒäàÕàÜÑÞÚÏæâ×ÞÚÏÄù|zrHEA2-,<3/e\On¤—}§“t¬—w­—t­”r³šx°šw§’s©•v«—~‰{hQJ;MC9{n^œšx§¶}³ÓŒ¢ï·ã·ÎŠ«®w§™h¥«t³Ú–²à”¨¤–z —u ¬z·Û™´à™¤Ã„ ®x­¡ˆ€cQF8NC;„‡g±É‰²Î‰²Å’°ÏŠ±Æˆ´¹†°¨€¯œy°—w°”u°”r²–w§š„žš¾ —ò •Ó£–Ž«˜uª“y¯–t§”¤•Θ՞–—©”x«–w¬—{¢•u¬˜†¢›¾–ë›–—œt‡‚ÚØÎßÝÓßÝÒáÝÒáÞÐâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓãßÔâÞÓáÞÐäáÓÜÛÍÝÛÐÔÑɈ„20/762¬ª¢ÕÔÊßÝÒáàÒåáÖàÜÑâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓãßÔÒÐÆ‰†310DBAµ²­ÝÛÑâßÑáÝÒãßÔàÜÑãßÔãßÔÞÚÏàÜÑßÛÐßÜÎÂÀ¶˜”“idfHAD<61TNA…l¥”y­›~¬—w®•s¯—s­—t­™z¨–y–…x]UDGC1i_N“…n£¤x±Ö޹ûœ¢õ’¶õ™¼÷¢®â”§Ì‚žÌ£ã‘«æ’¢£{¦šv©˜q¦§u®Ç‰¡¾¡¤r³™u†vjYLN;6qaUŸ¦y¹ÜŒœÀtž¯|¯€¨¼‡µÐ‘´Ó«Æ†§¶}¤¡u§”s¯™už˜“˜”Üž“ùŸ–·¥–|«–w©•v°˜z¦“¨¢“ä™–ÇŸ–Œ¯—y­•q©”y¦—w®–~¢•µŸ’øž˜¬žzž•‹ÑÏÅÜÚÐÞÜÑæâ×âßÑâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÝÔãßÔáÞÐäáÒâáÓÞÜÑÝÛѱ®¦97610,‚€xÊÉ¿ÞÜÑÜÛÍåáÖáÝÒâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓäáÓÚØÎ©¦¡=;:643—”×ÕËâÞÓãßÔåáÖàÜÑàÜÑãßÔáÝÒãßÔäàÕáÜÍãÞÕÎÉÆª¥§„ƒVRQ96.FD9~s_™‹tª—|®™y¦o¦’s­œ™‰r_TL@8+[UBƒv`¤“x§­|»ìš¢÷‹Æ‚£È€«ß‘¬ð™·õ›®õ•¤ö“§ì‹¯²ª˜o³“p·£z´½Š¬ÄŠ­¹…£pznbC=0RI@‰{i§­|Áá’›µo›s¯–|¢–r£ªw¤¾~¬ÒŠ³Û”¨Ê‰š¸}§žy™–¬˜”ôŸ—ꢙœ¦”uª’z§št©•ƒ£“£–ì›–µ¢—¶}³šr©”y«–{¯–| •¯’󜔛®™y “ƒ¿½³ßÝÓàÞÓåáÖáÞÐâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓàÛÒåáÖâßÑßÜÍããÓâáÓÞÜÑÁ¿µOML,+'YWOÁÀ¶äâ×ÝÜÎáÝÒãßÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓäáÒÝÛо»¶MLH/-,nkgÇļáÝÒßÛÐäàÕãßÔáÝÒâÞÓâÞÓãßÔåáÖãÝÒæáØàÝÕÓÓÍÇÆÂ££he`<9194+_VH‰|f§–{¬™~§˜~“…r`VE7.*F?0v`›Špªš}£¬zºîšô†­®„¨¢u¡®v¥ÄµÚбê¯þ—°û‘­ÆŠ¡£u«˜u«˜u¡¢v«¿Š²Í•‰¤lIL=0:)ffV›z§­~Áß–©¼}¬›z½œ{¯–v©›w¡˜r¤ p±º°Ð‰¬Ü²¶ŸÏ—“ò—È¥™‡¬–z¨“}¤™sŸ“‘Ÿ’Ö¢—àž–¢”w±˜x±—r¦“x«“}¯–‚¥œ¶¡˜è£•™¯—{¦•‚£¡—Ù×ÍâàÕáÝÒàÝÏâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÜÓáÝÒãàÒÝÚËààÐááÑÜÛÍËɾ{yx0/+B@8­¬¢ßÝÒâáÓßÛÐãßÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓãàÑàÞÓËÉÁdc_.,+GD@±®¦àÛÒÞÚÏáÝÒãßÔâÞÓâÞÓáÝÒàÜÑàÜÑäÝÔáÜÓáàÒßàÐÛÞÏÒÒÆ¨¥qmh:<<63.VO@‚tašŒv„r^VI2-$950e]LŸv«•y«›~žªz·êš«û®ª¯™uª—tª x±­z«É‚°õš±ý—¶ó©ÓŒ£³~Ÿ™p¡–p£¡yŠ•oF\9)-!AM9or\…o—žs°Ô’²Ë²¢}¨—l¤žu¯°ˆ®¦®–r¶u®¨y§µ±¿¹ž¤å—™çž™¨©˜}®—}¨—}¥œ{ŸŸ­ž—衖Ψ™‰ª–w­–v°—u¨•z©‘{©“‡¢›¼š—Ï¡“¬‘v¨“~ˆ†|ÉǽàÞÓáÝÒåâÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓåà×ÝÙÎåâÔáÞÏààÐááÑàßÑÛÙÎ¥£¢98486.…ÌÊ¿âáÓàÜÑäàÕâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÞÏâáÓÑÏÇwvr0.-1.*¡ž–ÞÙÐåáÖàÜÑßÛÐàÜÑâÞÓãßÔâÞÓâÞÓäÛ×àÛÒààÎàãÍÞáËääÔÛÖͼ¶±…Š>A?61(QG6l`N_VH1/%22,KIAuc«–z«“w§™|¦³…»éœ®õަ²~°¡z«”z©‘{ª”x¢²}ªé™£ðª÷ˆ²ð’¬Îˆª«yº¡¢‡rj^T,/-MJBluabeL_R;7b_[zh¦•z®|®—w­–v¥¦t¥Ï¯ú’³ä˜¢°z¨œz£“v­§~¾Æ‘®¶¤œm¿–¯—s”‘ekrOCI837+agN¬¸Žµ»€© u¬‘v®’zª›{¡›xœ—xˆ}guf]bWIHN7;S5>R5TP=ub[Šuw‰¬’³ “‹¬—x´”®˜¥¡©¦Æ¨Ï¡’®–l´˜o¦“r¨ž|©œvµœ|Ÿ”—®™ºª—ª£˜}«˜u®•{¨’v¹·­‹°®¤ÚÙËßÞÐáÝÒáÝÒáÝÒáÝÒâÞÓãßÔãßÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓãßÔãßÔâÞÓáÝÒàÜÑáÝÒÛÚÐÁ¿·\[W&$#RPO¿¼·ØÖËãàÑâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÞÐáÝÒáßÕÖÓË~y2/+0/+š™•Û×ÌáÝÒáÝÒäàÕâÞÓãßÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓãßÔÞÚÏåãÙáßÕ©¦žb`X><4<94ZL@{o]˜Šs¥‘x¬—{¡žrœ¸s²å¯ô™¨Í…¦¥s¨–q¦—pª£x£˜r­˜xŸŒ}€uaYT??<-NG>um`–”u­³‚°É‹¨£|µ”¹’ƒ¬—x§œvµ¡‚®y¬”vª’t˜mybp`ZeDID5B96;@CTOXf_P}rW}pŽˆ}–›ž©­ÖŸ•¬§•„ºŸs²™q¥ y²¾Š«®}­€¤—­©–¯¦–¥–o¬—q°–~­˜}Åû®¬¤ž“ËË¿ââÔãßÔâÞÓâÞÓâÞÓâÞÓâÞÓãßÔãßÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓãßÔãßÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓÞÝÓÎÌÄ€{643532š—’×ÕËâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓåáÖâÞÓàÞÓÜÚФ¢š63.10,nlkÒÎÃâÞÓÞÚÏäàÕäàÕäàÕáÝÒáÝÒâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓæâ×ßÛÐáÝÒàÞÔÔÒȵ³©ƒ‚xVUK?<8=:2NE;qaU”r›u¤w»Ñ–©ù”±áž¤i®›p²œy¬š{ u”l__S=?377+]SIym©“z§œv¥©u®Ü”£¬z¬“y¬“y¢£w¤µ|±¹„¬¡u©’|±“z¬Ÿy§½ƒ¾æž¡½{|‚SnkL[WEWLHJA4D@(BB2ACCZ]kuv˜”‘¡’®“yžr£¯»Û”§ºƒ¢›ˆ§™µ¢”˜¥”«˜r­—nª“y¨“}ÐÍÈÑÎɧ¥ÁÀ¶ÞÞÒãßÔãßÔäàÕãßÔáÝÒàÜÑáÝÒâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓáÝÒâÞÓáÝÒáÝÒâÞÓäàÕäàÕâÞÓááÕËÉÁƒ‚~NLL-++c`\ÉÆ¾ÚÖËâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÝÔáÝÒÞÜÑÞÜÑ¿¾´NKF/-,<::¶²§ßÛÐßÛÐäàÕãßÔäàÕàÜÑãßÔâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓßÛÐÞÚÏâÞÓàÜÑâàÕáßÔ×ÕÊÀ¾³‘•ijfD?<:.,F82YMAyt_Ÿ¡ƒ¨æ”»åž§¬y¯›x¦’y”ƒp…uecXJPG=HE7b^LŽ„l­šw­œq¥ o®³€¬Ø‹¡¯u¬žt¬¦yªÅ†©à‘«ä£Ñ~¤®ƒª§{ž¡o•·q³é–³ØŽ£©x¤•{ s’{ki]mcKZZBEF@B<<6;G8FTP4vhQ˜‚i¦y§”¨œt«šo,-+*,,*,,-///11FDCwsr¿»äàÛáÞÖáÜÓÞÚÏåßÔäáÒàÝÎàÝÎãàÑâßÐâßÐâßÐáÞÏßÝÒáßÔáßÔßÝÒßÝÒáßÔàÞÓÝÛÐáßÔàÞÓÞÜÑÞÜÑßÝÒâàÕâàÕáßÔãàÒâÜÏãÞÏäßÐàÜÑåãÛ¼À»afe41-<6+kaOŠ~f‚waQJ;ONJ¶¹½Û×ÌâßÑßÞÐßßÏÞÞÐßßÓáâÙÛÛÕãßÔãßÔáÝÒÞÜÒàÞÔàÞÔàÝÕàÞÖÞßÕÜÞÒÞàÔÚÜÐÞàÔÀÁ¸jjd.-)643©¦¢ÞÙÐåÝÐìåÖàÚÍæâ×áßÕáÝÒáÝÒâÞÓâÞÓâÞÓáÝÒáÝÒàÜÑâÝÔâÝÔâÝÔâÝÔâÝÔâÝÔâÝÔâÝÔãÞÕáÜÓáÜÓãÞÕåà×áÜÓËÆ½®© ‡‡nmiONJ;98532977C@BMJLwiV”‡q¤—}¨š}²¤€·¨° uª›m¯–v¬™v¢šr¨®}±Ì¤Ò†š×¦ì‘ªä–¦¸ƒ­ž}®±ƒ·é›«ø—œÖ~·Ò´ÚŽ´Ñ’¨®¯ y¥¡pŸ»y¸ä—²ÚŒ—º¡¦y®–z•”n¬tv™wooi^ZOHF>6;2;<3[NFrbV‰ƒp˜“z;:6+,(*+)-.,./-*('FDC‹ˆ„¿¼·×ÔÌàÝÕßÚÑãÞÕÝÛÐäâ×áßÔÜÚÏßÝÒáßÔàÞÓàÞÓàßÑàßÑßÞÐÞÝÏÞÝÏáàÒãâÔãâÔÝÛÐÞÜÑáßÔäâ×âàÕÞÜÑÜÚÏÝÛÐãÝÐæàÓßÛÐäâØßÝÕž•OOI/1+A:1h_Q–‰s¤–z—‹s\TC>;6‚„…ÔÐÅßÛÐâßÑæãÔåâÓÜÙËÝÙÎàÛÒãßÔãßÔäàÕåáÖãÞÕàÞÔàÞÔáßÕáÜÍæáÒèäÒãßÍãßÍÞØËŸ™Ž?8/.00~zÏÌÄßÙÎæÞÑåßÒßÜÎÞÜÑâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓâÞÓßÛÐàÜÑáÝÒâÞÓâÞÓáÝÒàÜÑßÛÐàÜÑãßÔäàÕáÝÒÝÙÎáÝÒãßÔÞÚÏÏÐÇÁ¹¦¦ „„~feaRQMFDCA?>C<3NE;YQDmeTˆk˜Žvž“x£˜|«w¯”z§’r¨¡v¹ÄŒ¹Û”±è“µøœ«ó¨Î‚ª³z¤¹z®å«èŽœµq²¢w§­v¨©}ªž|ª—v¨£v¨¼ªÈ‡ªÂ‚·Ï»¾‡±¡vª³zµæš«Ð˜®³“©¬…•™uˆg^aGVJ8QA5OF9SK>·µ­Œ‰„a^YBB<44.20/)'&310A@<^[V‡…}¨¦ž¼º²ÇŽØÖÎÝÛÓÜÚÒàÞÖÞÜÔÜÚÒãáÙßßÏààÐááÑââÒààÐÞÞÎÝÝÍÞÞÎåáÖâÞÓáÝÒáÝÒàÜÑÞÚÏáÝÒæâ×áÛÎçãØÞÜÔÓÔС¢žMMG0.$@:-ykYšŒv«š§•v ’vukYGB9PNM¬©¡ÚÕÌäàÕÚ×ÉäßÐëåØåßÔßÖÌÏÍÃÃÁ·¾¼²Á¾¶ÃÀ¸ÃÀ¸½º²²¯§ÆÄºÔÒÈÚØÍâàÕàÞÓàÞÔµ²ªNJE(-,\][Äľäâ×àÝÏåàÑßÜÍåâÔãàÒãàÒâßÑáÞÐáÞÐáÞÐâßÑâßÑäáÓãàÒáÞÐáÞÐáÞÐãàÒåâÔæãÕàÝÏâßÑäáÓãàÒáÞÐâßÑãàÒâßÑÞÜÑáßÕÞÜÒÕÓÉÇļ±®¦Ž‹ƒqnfTTTHFE;98;84@<7EA:CB>FEALKGSRNYXTlkg„ƒ¯­£º¸®ËÉ¿Ù×ÍßÝÓÞÜÒßÝÓâàÖáÝÒâÞÓãßÔãßÔãßÔãßÔâÞÓâÞÓãÝÐàÞÔÒÓÏŒ‘=@>,*"RI;}r^¢Žu¬—{«–v©•r¨–w•ˆriaT<6/eccµ³²ÞÛÖÏÍÅ¿½³¦¡˜{un_WPIJH>?=;<8;:665165176232.+,0245355JLLZ\\dfgefj<=@>>977993?92MC9iZJqZ‹€`š˜o³µ‡µèŒ°Õ…ºÛ±è‘¨ø“­ü›©Ö¦®£ t¤£w³¸‹ž«wŸ±v´Á‰¬¥z¹¡œo­©€£®|¡Æ€¯×œ¨t©œv¨›o£·v½Ê’¬«£”t§‘xžŒu‚kâÞÓäàÕàÜÑÓÑÆËÉ¿¾»¶°­¨Ÿœ—‰‰ƒƒƒ}ƒƒ}ttnbcZRQMBA=;:698432..-)/.*0/+732=98IED[WVplk‹‡†©¥¤À¼»×ÕËÞÜÒâàÖàÞÔÞÜÒáßÕáßÕßÝÓèãÚÕÒÍŠ‹‰BDD43/XREŒi¦•z«•yª“s¬–s°šv©–u¢“yŒ€nZQD768SRTjkied`LKG;84510510*,-*,,.00000,-+-+*0/+.-).,,0.-32.FF@RRLSRNXVUSQP::4HHB””ŽÑÏÇàßÕÞÜÑãàÒßÜÍÞÜÑßÝÒàÞÓàÞÓáßÔáßÔáßÔàÞÓÞÜÑßÝÒßÝÒßÝÒàÞÓàÞÓàÞÓàÞÓáßÔáßÔáßÔãáÖáßÔÜÚÏÜÚÏàÞÓäâ×âàÕßÝÒßÝÒàÞÓàÞÓßÝÒÞÜÑÚÝÎÓÖÇËÍÁ¾¿µ°®¦žœ”}zuXUP>CA.31,/-=;:OID_TL{k_˜…x©«£žw¤¥y »{¡Þ†ªô”«ê”±Ý–«Â„£º|µÐ¯Õ§Îƒ°Äƒª¢s¬p¯¬€··²Ê”¬Ý“¯Ô¢£w©”t´›y¡Á€±Â‰¤£w¨—v±–{³™{¬™vÕÒÄÑÍÂÓÏÄÚØÍäâ×âàÖßÝÓÞÛÓÞÛÓÞÜÔàÞÖÝÛÓØÙÐÄÁ¼·´¯¦£ž†ƒ~_\WJGBC@;8501,.2-/3.04/14/1724<79B=?MKC^\Tqog€~v“‘‰­«£ÄºÏÍŶ³®}|xED@,)$RLAŽ€m¤‘v­˜y¬–z­–v«•r­—s©•r¦”w¡‘zŒ}jUPM84/63+=;3@>6NKFLHG42130,;83D@;HE=PKBZSJa[Pe\RvfUwgV}oYqZs\ˆzc‰{e„ub[RHlf[¯­£×ÕÍáß×ÝÛÓÝÛÑåáÖàÞÔàÞÔáßÕáßÕàÞÔßÝÓÞÜÒÝÛÑâàÖâàÖãá×ãá×âàÖàÞÔÞÜÒÝÛÑÝÛÑÞÜÒßÝÓáßÕâàÖáßÕåãÙíëáëèàæãÛäáÙäáÙâàÖÞÜÒÞÜÒáßÔääÒßßÏààÐâáÓáßÔÝÛÐÑÐÆÃ¸Ÿ›š………gklNSV:=A659?8;G<>\RKqaZ‡wj™˜v®Áˆ¬Êƒ¤»w³À‚ºÁˆ¤ªq§¶xµÚ’´ä–®ÔŒ¤¹‚š¤z¢¡o«­­Î‹²ï•³Ü‘«°}Ÿ–j¹©~¯×§¹|¡œo­šy°•z°’u¨–qãßÔâàÕÚØÍÐÎÄÌÊÀ×ÑÄâÜÑçáÖâÞÓÞÜÑàÞÓáßÔÞÝÓÝÛÑÝÛÑàÞÔàÞÔÙ×ÍÍËÁ´²¨˜–Œ€}yspl^[WLIEB?;>;7;8485121-21-10,0/+/.*10,762<;75770.-FC;pgZŒ~k¦’y±œ}¬“q¨“x«–zª•u«—t®šw­˜x©”x£u–‡tzlYodPulX‚ziˆ‚umf]HB;VJ8xjX’„qœz¢‘|¤’{§“zª–}¬“y­•y¯˜x¬–sª”q°šw¯˜x¥ŽntfT[N@_VL]WPnkf†ƒ~Š…’‡š•¢Ÿš¬©¤¸µ°Å½ÑÎÉÚ×ÒßÜ×ÌÉÄÐÍÈÖÓÎÙÖÑÕÒÍÍÊÅÃÀ»½ºµ±®©©¦¡›˜“‘މŒ‰„ˆ…€ˆ…€Ž‹†Ž”’‘›š–Ÿžšœœ–šš”Ÿ —¨© –”Œ‡…}trjda\UUOPPJUTP\[Wgcbhffjik_abPRSIKKGHF<=9355857>67ME>liT€~`‘†j­™€¬¡ª–w¨w¯¼ˆ«ËŠ«Ç…³É²È—«¥|«¢|¦Ã~µô”²á’µÌŽ¡°sª²vµÙ“¤°v¤˜n¬—x«“w¯–v¥ußÝÒáßÔÝÜÒÝÜÒâá×çàÑæßÐäÜÏäÞÑãàÒáÞÐàÞÓáßÔåáÖäàÕáÝÒáÝÒãßÔâÞÓáÝÒãßÔÝÜÒÕÔÊÌËÁÆÅ»Äù¿¾´±°¦£¢˜…ˆ†mpnRUSBEC8;9031/20253.23CDBf_V{o]“‚h¦‘rª‘q²™w§“z©–{ª–w¨“s©•r«–v«–w®™z©‘s§’s¥‘r¡‘t•ˆni^HF<+TK=z^§‘u°˜z¬“s¯”r±•r°”qµ˜s«•|«–{¨“w«˜w­šy¨•t¨•t©•v£Žy‡wfui]RJC?<8A=;7851851851851962;84<95=:6@=9A>:C@GD@IFBJGCKHDNKGPMIOLHMJFMJFIFBIFBNKGKHJEBD><<<:9=;:<;7;:6::4546324/.0-,../3./3-.2-.2-20,/-310510830GE=PRFLO@KIADBADCG6<94850=:5C?:JD?^UQdWI]PB]OC^RF^RFcWKg[OdXNWSNRNINJENKCOLDPJCNHANHAKH@RMDYTK_YNbZMe\Ni_NlbQpeOpeOrfNwjP…tY’€cš†g™…fœ‡r—‚l€f„y^nfO]VGSMFNIHB=<=87<74@<7JD=TOF`[RieZˆz^™Žp­ª„»¾Ÿ­wž¶v±Î‰ºÛ‘¬Å‡ ¤s§“t´”©‘{Ÿ˜q©µ{âÞÓáÝÒÜàÔÛÞÏäÜÏäáÓâßÑáÞÐáÞÐâßÑãàÒãàÒâßÑæàÙãÝÖáÛÔáÛÔãÞÕäßÖãÞÕáÜÓàÞÓßÝÒÛÙÎÜÚÏáßÔàÞÓÞÜÑàÞÓÏÏÁ†ƒ{JD?A8/ndRˆ}g„vcnajgba^YPMH?>::9576223123163+:4-D>3SK>`WIncUwl^zoawiWcYHLD7IC8TM>vkW•‡j­y¨’o­—t°™y¬—xª•z§–| z—ˆuˆ{m‚~kwu]xjT|gXvfZocWm]QqaTvfYzj^{ma|pf€tj€um€umk‚o†zhƒyhŠ€oƒq–ˆu™‹uŽƒh„i‚gu]wjTm^Km\I€n]’ƒi•†l›Špš‰o˜‡m™ˆmŒqŒqž‰j‰jˆl›‰l™†k•„j–…k–‡m™‰ršŠsžs¢‘w¨•zª—|¬—{ª•y¢•{£–|¦˜|¨—|¨–y©•v¬—x®™z¯–v°—w®˜u«–v¨–w§–{›‹tŠyflgh\XWGCB;6373.85-:5,;6-G@7NH;^WF{dŠm šu©£zª¤y¨ x¬™tµ–w²•v¦™s¥«zªÁƒàÝÎßÜÍÝàÐÝÝÏâÜÑßÝËáßÍãáÏãáÏãáÏâàÎâàÎãáÏâÞÓáÝÒàÜÑáÝÒãßÔäàÕáÝÒÞÚÏÝÛÐãáÖåãØàÞÓÝÛÐÞÜÑÝÛÐÚØÍ£¤ QMHJ?7l^L˜‡l­›|¤“x¦”}Ÿ‘~ ’›zƒq‚vdsgUi]KdZIVMCPJ?C>563+63.984786555843?<4RM>qkTŒ‚d¦™s«šs§•l±•r±˜v«–w›ŠpŒ}j{n^i[OYIBSMFWdNUjJKT:KC6I=;A85=5.<8-<8-<7.=8/@;2C=6B<5?92@:/C>5:7/74/961;83IF>[VMziTˆwb–†oŽt¥•x ‘qœl§™u¦”uª™x«˜w©–s­šu±›w¯št¯˜r¯—s¯—s¯™v¯šz®š{©—z§•x¤“x³šx°—u®•s®•s¯–t±˜v±˜v­–v©—x¦”u¥“tª–w¬˜y«–w©”u©”u°–n°–q¯–vª”x¤w—‡p|nW`T<@;8>96A;6HB;RLE[TKYSHUODJEBHA>?62F:4J<6UC9SOJmgZŒ‚j¤•t¦•n­št®šw­˜x«”z£tŒ|eqcP\P>[N>rcSˆyi‰r¤y¼~¥mj{VjfSngTuoXuqXtpXrnVrlUtnWyqZyqZwoX_YNRMDC@8DA<<;787352-0-%:1-@73I@7TJ@e\NohUunZ}yaˆ{ei‚k—ˆn¢‘v§•x¨”u¬˜y©—z¨–y¦”u¥“t¥“t¦”u«—x®š{¦‘r©”u«–w¬—xª•y©”xª•yª•y¬–s­—t¬˜u«–v©”u¨“t«–z¯š~­œ{ tn}oc`VOD>797/;<2OD6_TFti[‰|l–‰yœ~œŽ|˜Šxˆxg‚scodV`VLKC<:52<78?==KH:d]L†}bŸšy±²Šµ¶Ž®¦RJCRJCQHDMJFKLHMMMTTT\\\fffrrr†††žžž¯¯¯»º¬À¿±ÇźÎÌÁ×ÕËÝÛÑÝÛÑÚ×ÏÅĺ½¼²¾½³¾½³»º°¶µ«ŽƒRQG>=Ae_Z‘¯š~°—u­•q«—t¬™v«–wª•v«–w¬—x¬—{«–zª•y¨“w´™w®–x¨”{›Œyyo^SJbXG~p]•†l¡r¦“r§”q¡¯u¯ß°ê™½‚—˜q¡o§”q§˜x¨™y©—x§•v©•v«—x¬—x«–v¨“tœ‡k”ƒi–†oq[€r\„t]vfOQRHB@8;5.A84D;8?55=55>89B<5F@9JB;OF=TKAYPCi]Q~se”…kžr©—z®š{°šw²˜s³™q³™qª•y«–z«–zª•y¨“w¨“w«–z­˜|¯—s±™u¯™v­˜y­˜|ª—|¤“yžŒu|xfd^QLD=@:5=63B<5WSHpm^–ƒhŸŒq¨•z­˜}¬—{«–z¬–z«•y¬˜yª–w¤”wšsŠi{t`qmZ^\JFK@-DJ7Y[Gzs`@A=:;7=94E=6B=4<76;65943832943:54<76=87HCBKEFOIJUNQ\UX^W\VNULDKDD>DD>CC=AA;BB3YN@xiV“€e£Žn°˜t®˜u¯™v°—u®•s­”r°•s²—u³˜v¦•t©–u­šy­˜x­—t°—u´šv¢ˆd‡ysgeZRJGB3;4,7-5;0y“†u‚y~o‡ygŠzcƒvfrb{n^yl\wjZsfVl_OfYIOLGOLHIFBB>=?:;?:<=8:8274213101/.20/3100.-421?=>7.93,OC7l_Oˆ{eœ‹p¨•t±˜v²–s³•rª–s©•r¬–s®—w¯˜x°—w¯–v®•uª–wª–w¨–y¥“v©–{¡t™…l…qXZMEP@9I93A7067.;?3II;Ê·¡Î»ž«•§—z²–s«—xª–w©•vª–w«—xª–w§“t¥‘r„‡q‹y‹z~oooaffXbbV_^TWVXJIKA@B=<>879657324.-/-25'-,'1+(0/*-5*)283475+52*96.<94:72:72>=9>=9540;6-=70MJBhaX{q`“f¬m¹™n¤’shbRFE:6B?7RUEs~^¦¶¾á—ª¾}žlª—r´—|­‘y§‘x¨—|©˜}²¢}¤§p®È‚¬É€ h¨˜t­–€¬™v«˜u§—s¤—q¦œt©¡yª¤y§¤x®•s±šz¨“w u‡w`‘ƒm|nXL>(><2[UH‰m¤˜|Ÿ–p­«{¹¿ˆž¨l²šp±˜p°™s«—t©–u©™|£•y”ˆl‰yhƒscpcUWMCC;4941843644.23133540:7/F@5[RDwkY‹}j§“tžŒo“‚h~p]ZQC@90EA<\YU’}h¡t©—z¨—v¥–v¥”y£’}¥“‚¨–w§•v§•v«–z«–z©”xª“y­–|°—u¥p‹z_k`LYVH=@7074&1//3.B>9dYQznbwo^sa”€n¨±–€ÜÃ{ÖÁ™˜ƒ°šw¨”{©–{«”z¬“y¬”x¬”x©“w©“w¥˜ˆ™¬›‡Ñ·œ©‘ “sŸu½Žrš—{Ÿˆn—‡pŠ~l{lcZGBlWVj[YZQNLL>AA586.<94882+3),8,'5)7)/1,-00*=1'/2# 3$0+(/(+.-////,,,,-+32.;84D?/VY@†p^¤ƒsª¯|²ë¹ç›£µxžšq£˜z§–|°|³¯­¿„¬Ñ‰®Ó‹°Õ®ÔŒ«Ñ‰©Ï‡§Ï‡¨Ðˆ¬ÈŒ§»†¡­y¦–r®“~°}±Ü“©´|¨™y®›x«™p¦”k¨™xweA=8437bSC‹_«—t¸‘{¨•r›¿}„°™°švª’t¯•}§’v£›s¦®y¬Å‰¤Æ‰ªËŽ¥Á…¥»š¦r„†\„z\‚q\oZK\UDYPGQH?JE6;:0-,.126253^P>€ugsmfMID>81[Q@y`¢‰i®”p¨“w¤”}§–|­–v±—s¯˜xª—|±˜v¬–s¬—x¥“v˜‡mj…xbseRPRR?@>12021-63.85-E@7TOF‚mM“~^¥p¬—wª•u©”u«–w£’…ˆº®ŽÝÏ¢² «’x¯št¯—s­•q®•s®—w­˜|ªš}¨š~š§™Ò½™É·¤š‰£•y¨—v³•xœ”w³—x¡“v˜œƒ‰Š6ZJMps¹¨z̹t¸­xµ«s¦Ÿt–•w‰Šƒ„„~znn`dXNVKNLDUKDZOKKRKCSLGLJF@5A<3@<7A<9>98<7472//+&@2,[MG|se‘Šq§’}±š„©¾‡­õ•ªÏ‰ ¬r¨™r®–x®“x³y¬­{¡º|ª¼¨º§»€«Á†°É´Í‘±Ë­Ç‹¶Ë†¸ÇйÁ„º¯}µ¥{ ¿zµì•¦½©˜}¤’s­™v«šy„lZSD;5.TMJŽ|k¢“s­šu«”t««}­Ð¡¹±›®–r®–x®˜|¦šx±®‚´·…³³ƒ«¨|ª¬~¬¯´¸‡¶¹‹«¬€¦žy©—z«“{žu™ˆs“…sˆ~libSQJASLCSM@XOAZREHA8D=4aXKŠ|i§”y°˜z¯–tª•y¦•{©”x¬•u±˜v«–z›w†t|raldSb[LSM@EA6@;297-A;0G?2UM@h_Qxn]„xfo˜Šw¤’u§•x©—z¨–yª•y«–z«–zU?:M[Zd—“Ž¢–ª˜‡¦–r«˜u­šw­˜x§”s¤’s§šz®£ƒ˜Å«‘·¡œª’€·œ³’q³”s®|¿•r±•v¥›ƒ‚ˆu.B5Tvk‹À²–ÕÅ‚ÑΆÙׄß܃äàçâêá‚êßyâÕ’Ì´‡®•–•€˜Šx—‹’­¤ÚÒwº·œ’zŽ„r…{qpgcJC@30+89/?D5rbK’}hª—|©œvª˜s¨wžÂ|¤ú޽À¬¢zª–w§–|¥”y§˜w£ tŸ©t««{ªªz©§w©£t©¡r®¡s²£u´¤v£¬s§§y§¤wªžt©Ÿw¤Ç„²ìžƒoŽl•„j©–{•‰q]WJ64*LC9ƒvf«’~­™z§–o£¡q®ÉŠ¹Û•¥¬y­—{²™y­•w¤“r¡ t¯½‡ª´¬¡u·›y¯“t¯™vªw­§~²¬ƒ¬¢z¨–q±˜v´˜uª”q§–{—ˆuzlYs\–ˆqjic\IB9DKM7IH:QMV{ahu€§ŽŽ²š˜²šª’Ÿž„ —|¦•{±–{®–zŸ©’‚Ô¾qâÔ˜ÔΚŸžtn[IA45-&A;6VXLyˆm‘«ƒ‡ªxcyVnjWq^OydO‚jV‡o]ŽlÀ€Ÿ t¡£u²µ„¼¿´½…¨º©Ä…º×˜²á’°à‘®á‘­å”°ëš±ï®îœ©ë™ÈÙ¦ºº– Ÿyœšr¥¢v®Ì…§ÕŒgwUbUEƒtdxl`@81.+'ZULŽ€j¨“s±–|§—s©¥u±É‰«Ý®Î‡«¦u«—x¥’w©•v¨¢u­Ã‚ºî›±î˜¬Û¢¿€¤žu¤™s§—r«—t¬•uª•v«—x©—x°”u¨–wxdZNBgXH•‡kƒibUG74,aYL˜Št«–zª”q°—uª“s©”u©”x¯˜x¯–t°™yŸŽtnbPIA4JE<{jP”ƒh¥“v§“t«–v¯™v¯–t®–r¬—x«–w«–w«–w­–v¬•u­–v¯˜x¯™v²œy²œy®˜u­”r­”r¯–t°“x¯‹y“–†Š°ž‚‰|~rfocWXLBF82:/+81.:65<::fQB|uf›’ˆ–ÔȆæÜÐ͉ÜÔ”¤£Ÿ‘t ž†¬ž_vq6RRXxwXyO€rLQT6BF,BG9\`W„‡o¥¥}¶³ˆÄ¾›®™¦Ÿ„°˜zªœ…ŽÆ³€ÚÍw–•\PP64,=94KE@]WP_`PQ]?Pi=aK~¨k‡•l‚f‘†f™‹n¡Œv¥œz¡®v§¨v®»ƒ¹Ñ‘¹Õ´Ô©Î†ž»vš®m–‘pŠ…dxwUopNkqNlsPisOdpL^oMfdLhgMvrZ}u^}_…¨oŠo‡zdzraVOF93,TKA†xe¥’w±œ|°˜z ˜p´¹†¹ËªÎˆ²Ò‹§­v¨–w©—z§•v¦ u©¼}¨Ø† Û†¯æ—µà°¸‰£¢v¤™s°™y­’w©vª•z§–{¦•{‰}kTPEPG=ˆzh›‹te[J73.SK:Šk¬›©”u­—t±›x«”t®™zª•y«–w¬—x¥’w|p^I@2JA3wm\Žt¢“y¥”z¦“x©—z«—x«–w®™z«–z§’v§’v«–z¬—{©”x©”x«–z°˜t°˜t¬–s¬•u¬—x­˜|«–{²•vº—}¥¤ˆš¸›£œˆ§’v¨“x¢w’~l{k[aUIG@752*;-'+4*070+^WO‚…o¯°}ÝÒ©¦¢¿›}®–~š‘ƒ_\W564HJDX_RT`LX`UQYOKUO>IG-;:(87=ONcxuƒÈ»Á©«¤ƒ©‘u’•…k‡1IG/-,873C>;QG@]SIg_NlkQ„‹hª¸¬×ް»‰«¢€ œy”’s„n…~cnuJa]\ZbXQ]KIO8LT=N]HBL?99348326123/21-30,4/,3.+3.+-7';1*?6-@96C59;H0Hf=pye‹cc_LA?7TMD‡vc¦Žp©’r§•x§–u £rµÃµ»Œ¨µ}²Ô¦½§˜x­˜x¨—v©¢{±º‡©Á’­k¢¶{³¿»¸Œ¨¢y£”s«•y­”z¬•{¬—{§•vn[UJ>;3e]Lœ‹p‡u^JA7387pVŸŽs¦”w¥‘r­˜xª•u¨“s®™y«–z«–w§’v†xeSMBC>5lbQšŠsª—|¦“x¥’w©—z«™|¨–y¨“w©”x­˜y«–w«–w«–z«–zª•y«–z­˜|ª•u§“t¥“v¥–|¡”~Ž‚ph_Q”s¥›y«œ{ž¡«©–q­—t­—t«”tª•v¥“v–ˆl†z^mkaVPERLA>>8999+B=8VCykU§i¥•xŠ„qID;@6/UG;ƒtaŽg‰|fo^sbUcRIXJDOG@EC;JMDjql“™†•‘uyt_EA;7TNIaTLfTIscS‚taza}y`p‡SlgNcNFSH@=:6807@7:54*C84AJ=CX?K[=><9:8635612;65E?:SJAcYOreWreU{t[št‘·}šÈ€®ÔŒ²Ã„¥£s¢•o¯y²—}©”u¬œx§™u¨–w®–~®‘|§—s«—x¢‹qœ„nžˆo’„g•p©§~›‹nheVEH9~w\¡”t¡’x¨•€°•{±˜x±¢¬|­™v­¥}¦µ‚¸Ö›’­n­˜y­{®ž¥¶}¨Ãƒ›¡pª˜y¯—{²™q¬˜u©–{«–z©“o¬™t¨˜{ŠiDFFD;-pV£“|sk^@=8PH;‰{e¬—xª•v©•v©”x«—x­˜y­–v±˜v¯—sšŒvjd_843C:1{mWp¤•u©•r­™v®šw¦‘q­˜x¨“sª•vª•v®–r°—u®˜u«–vª–w¨–y t˜‡meb^MJE=:2C<3NF9YPBoeT¯—y­•y­•w«–w¨”u¤—w²–x³•z£’x‹}giWwg¡“°”u®™z§˜x¡—y¤œ¡–{‹~dxgM_P=ZSD@A8-.%ME8†wd§”y§•v§”y­˜|¬—x¨“s©•v§˜~—Œxyhf_VMG@30+,*)532EB=UOH^WN\SJTKAPG=I@6NF9OG:YQD]UHoeSsjVv`Ž‚j–ŠnŸ‘t¥–v¦—w©—x§¥}¤´¤·~¤¯w§¢uª™x«•|°—w®—wª•u©–s©–s§”q¯™v²™w®™zª“yª“}Ÿ‹yrbQaVBgaJŽs ‰oobT[OC’}b¯“q®”v­•y²“r©•r§›y¥›y¥”s¥u©¶€ÂÚ™¢¸p«˜u®’z­™z¨±y·Ê‹¨¨xª—v«–w±›rª•u£Žx«•|°—w¯˜xŸŠum]Q540YO>–…k›‹t_WJD?6lcUŸx«–wª•vª–wª–w«—x¬—x«–v®—wª•uq^NHA941ZPF‘jª˜y­šyª–sª–s®™y«–v®š{«—x­™zª–w¬—w§“t¥“v¥–|Ÿ‘{†{gcYHG?.G>0PG9`VErfT‡xe™‰r¤’{®”v®•u°—w®—w¬—w¥“tÁ˜‚³‰}sc\D@;>,+D0/MHG…pZ—†l£•y¢•u£”s«˜s±—r²•n¨š~oeT3/*41)g_N˜‰o©–{¨”{®•u¬•u«”t¨•t¤—w•x€{b\ZB@=8/,(/.*@?;LIDROG[UJ\TGmdWlaSxk[sa‡ycŽ}c›Šo¤‘v¥’q©”t¬˜u®šw­šu­˜r¬—q­˜r®–r¦•n£šo¦œtª˜s¯”y­’}§}ª—t£‘r©•|¦‘{±›‚ª”x¨•p§—l­•y¦u¨—}’„qOG6NH;HD9gbY•~hcTKgYM…i´—p°žu¦r¥œj«˜s¦“r°˜|°“x©™u§°}ºÖ”¥Ë¥u¯—{¬”v«ªwÀË®ªz£“o§™u§Ÿp®¢€¯š„±—±“v«u…ueC99B<1|n[©–{‹{dKB4OG:Š~l­šª–w©•vª–w¬—x«–w«–w¬—xª•v‘jWM<:3*OG@~qa£’x­˜xª”pª–sª•u¬™x§“t¦’s¨“wª˜{£u¢“y™‰rŠ}gvjXZQCGA4HD9VQH{jPŠy_š‡l¢q¨“t±šz°™y¯˜x°—w­”tª’t«–w¬•{«†x„bb?46...G==>52%,'82-93,GC8ebS‡nœ‘{£”z¥”z“ˆmWOB.)(KE>Ši¬›z­˜xª’zµ™v®•s¬—x¥”yŒihaNIE353!A<3OH?ZTIh_Uul^€scˆzh“„qš‰t Žw¦•{©–{©”x¨“t­–v¯™v²•zµ˜}°•z¬‘v¬’t®”v®”v±—y®–x­™z«—x­•w´–{³•z©“w¢”w›qtgQbUGbOG”{q¨~¨–w¢—q®šw©™u£˜xˆ‚eWQ:e^MUKAWLD~s_IG=d^S˜‹k«žp¬³€¤»„£Á€¨¯| q®™y³’x¬•u £u¨ÊŠ¯â˜¨®}¬|ª•u­©x¾Ä‹¬§z¡˜s­¨ºÇ²·Š¦ }©•v°—u‹njcT8;9maO—‡p¥”zrdNF<+bYK›‹t¬—xª•yª–w«–w­˜xª•vª–wª˜{£ulaS@7*B9/pgYš‹x«™|¯–t¯•pª•u«–vª–w§’vª˜{«˜}¡v’gucndR\R@VL:[Q?i_Nud’ˆw§’v©”x¬—x«–v¬–s®•s²˜t«”t¬•u«•yª•z§“z‹|laNI?049/5ZQMtftmZYZFD@?75410,11+11+86.NKCgbYd]LGC>A<>iaZ›v°x¯—s®“x«‘l¬•u¡v‚scTJ@;1*A70RHAmaOƒubŒ~h•ƒl¥’wª•z¥t¬–z«“u±™{®–x©”u­˜x°›{­˜x¬—w§w«“{¬”|ª’zª’zª”{«–{«–{©˜ƒ”‡q†xae¨t°—w§—r¢›p–‡mkcLUQ>XQB“ƒs®–‚«–{£”s©—nª™r¨šv ”r‚e–‡m’‚k—„ozp^@=5d`U™Žn©¥t³Å³Ù¹è£±ëš°ØµÉŽ®µ‚©®{š¬qœÀz±å—«¾‡£x¥“tª§z´º…¬©}ª¤µ¹»ËŽš­t j£¬z²³‡‹†eQP96(.K4Bv_c›†w®š{¬™x§’v•‡uƒvfpfU_VHPH;B<183*4/&;5(:61EA@c[T†xb™…f¤Œn­–|­˜x«š‡{iRI@:1-LA=td]“€x©•|«–{¬”v¯–v´™w³˜v¯–t°—w¬•u­–v¨“t¬—xª–w«—x¥“v§•x©›¢”x¤”wªš}©šz¥–v¦•t¥”s•‡uf]IPK6qgOœˆo²—}³–{¬‘v¬z‚hvxZrsS™‹n¬Žu±x´“°’w³“|µ’~´~³’~ªŒs­–v®šw„p^F;3m`Xˆl¥”i¤¦xŸ²£¼€¡Þƒ²å¹ê˜±å—±å—°ß­ÞŠºñš»Ì“«£~§”y§¡x§§y£œu£™w¥¦|£¨q ³t©Ë…µØ˜§½lqRMF2tjX£Žr¦•{†xeD;-IA4Œ€nª—|®•s©–{«–z¬•u®˜u¬•u«–zŸx}pZMHEYPC„v`§•x¨–y¨”u«”t±—s«–v©•vª•yª—|Ž~go^I_P=j\JpdR…wd˜Šs¥’w§’r®”p°–n²–m¤“x¥”y¥”y¦”w§•xª˜{¬˜y©—xs‚vd[QG<3/A09sEX¥c|¸„‹²•€«–p­•q¬’tª’t«“w¬–z§‘x—…n‡ycxjWh\JNB6GA6A<3E?4TG7fUBzkXŽ‚p yŒ€nYSH74,OIB|qc‹t®˜|«–z¨“t­”t±—s°–r®•u¬—x«–z£“|‹{d‹z`¤“x¦”w§•vª–w¯œ{–‰svjRsfLe¢“s§–u«˜u«˜u†pwkSa]Dyp\¢ˆ|¼Œ‹È‡Ì…•ÅŠŽ©…}~t\|wX¥ŽtÁ‘…ˋ͊™Ç’ËŒ–͈—Ê…”ÈŒ’¹Œ²—|§–oykUA8/mbZ§u³•r¬˜u¦šv©s¥i¬´w±Éˆ«Ø­á”¶à“´ØŒ®Õ‰®µ|«˜w«w¦•t¢™s¬˜yª•v©u¦Ÿx¾Ì’Ä嚵ؕ‹t[WDhXH™†qª“s£’xqgV;6-VPE’†t©–{¯–t§–{«–z«”t°—u¬–s¨–y”†pcWEB=0:4/@;<}UgËp‘ëzœÒ„°y¨—p®šw¨”{²™y®•u¯•w®–z«”z¨”{¤”}žyšˆwo{tcohYfZP[NFWNEZXM~qa_WJ53)=;3urd”y¨—p²›k«–{¬–z­–v¯–t¯–v­—{¤“yœ‹vxpcF=/MA/Œ~g¤“x®š{¬˜u§‘m†xlSC7K;+ziV¡Œw­—~®˜|­•y³“v‰jwpUym[§ƒƒÌˆŸß~ªîµÜ…§¼‚”ic~n]«…y͉”Ø£Üz®Õ‚¢×£ß€¬ßƒ¬Õ…¢¿‰Ž³–£˜rmlR48,cbX£Žxµ–w±“x±“z¶”v·“ƒ±x§–u¤w—§q¦«t®¬v¤¦r¥¢k³–w¸“¬”x¨•r´—|³’x±—s¡š´¾‰©Àv¢³s†ƒdgTM…od y­–vœ‹q[SF;80d_V–Šx©–{¯–t¦•z«–z«•r°˜t¬–s§•xŒiRH6KFEtgW¥q±št§”q¨˜{ª—|ª’v®™z«—x¨•z’ggVAugU€pŽq¢m¨“s­˜y«—x¦”w¦“x¦•z¨—}«•r­—t¯™v°šw®˜u¬–s¬–sTEB<1;7;0VX;‚obÕ€–ûo¶çw¦ºŽ¶“´”}¦™s­•y§—z§™u«–w¶~¶‘}¬–s§˜q§—s±‚¼‹·†ˆ®}¢n™„iŽksx]XRM62-?;0ynX¤‘n°™s®˜u¨“w©•vƒm~ve›Žx®—w®”p¥’wzp_C?:>;7?<8sk^¦•{«•r±™u«•r¤t†u`g[IwiV¢t°™y­˜xª˜{¬–}¥Šp}pZ~iZÈ€Œå~±Ó~°ÆŠ”ψ˜Ôn¨’cs|ei®„èz´ÌŠ–ª”‚¡m§•~Ć–ây²Û}´¶’Œ¨šp¶“yobT38/xdR±“x¬z­“u®žt­’w§u¬”v°–x©™t©–u±’}­˜}£¥w£¡~§—z¬™sŸ°m­Ö‹¥¬y®—wž–x®˜u®˜|ª˜y§™u—†kxeX’~l£”s¯—{rbFB=?92…vc¬”v§’s«˜}®•s«–wª•yª•v®—w§’vˆ|jJD9OF8sa¥”z¨“t¯–t²™w©’r­˜y«”t­–v¤‘v‰{hUM@ypb–…kž…c£Žo¨“t«–wª•v©”uª•vª•v©”u¯–t­—t«–v©•v§•x¦•z¥–|F:0RDFecQe²Š…ãy ûp´à|Ÿ´‘}²”{²“|¨˜t«–w¯”z­–v¨˜s¡™t¢˜v®–x¹’|¼Ë‰ŠÛ‚œä}£Ý˜ÖЇ‘¯†ƒxq]@7393._[P•Œx¦”u«“o¯˜x¦‘vz^qcPUL>ˆzg¬—w°–r–„gcWESK>OJAA;4d[MŒr¬–s±˜v­˜x«–{|gj^LzlY¡Žs¬•u©”t¦”w«–zžlwrY…ci×u£éx´Çƒš±•w¾“„Âv–…bftd^­„â‚«ÅŒ¨’€«™p²“~Έ™ä}°Ø€¨´’…¨˜s´’zlcV.6,ufS®“x«“}­˜y¤r©•v¦™s«“w¯—y¨œt§—s®’zª›{§±|ª§®œ³ z¨½yµå—­º„´}¤™{ª–s¬–z©•v¨˜t™ˆmwdW‡ud‘o®–x}n^@<7C=6Œ}j®–x©”u¨•z¬•u«–wª•y©”u®—w©”xlLF;LC5sa§—€«–w®•s±˜v«”t¬—x°™y®—w¡Œpq^WOB|seh™‚b¨“tª•v­˜y­˜y¬—x¬—x¬—x¬—x­™z«—xª–w¬—x¬—x«–v«–vqdN‡wk˜Œt²”{ÍŠ‘ôr¯÷q³×‚˜±”y¬—w®–z¨˜t«–w¬”|ƒŋ…°’¥™w®˜u²•z«•|Ä€Ô…“瀥ëzŸí|žéƒ¦®m‚fJJB7/ld]Œ…|…tš‡l«”t¬”vŸŠo‚lSm^NH?5‡{i¬—x³™t¨•tŒ€h†wdwfYQDbXG—†l¬•u«•rª•v¬—|jk_M}o\¢t«”tª•u¨–y©•v—ŠjslXŠ\rØqªß}§ÀН–v¿‰»zybZtaZº€‹å®ÈˆŽ´¼“}ÃŽ„Û‡ æ®Ï„™²’§˜x­’xneX070ykYª”x«”~¬›z¡¡s©{«˜w¯—{°Ÿ~ª£xªw®–zª£|­Ç‡­¦©—z­x¥Á|±ëš«¿„²œy§•xª–s«•y§“t§—r›ŠotaTueU”‰k¬”vzlZ;72IC<’„n®—w«–v¨•z­–v«–z¨•z©”u®—w¬—xnQI1wm\¥•~­˜|«”t®—w®—w«–w­–v°™y¤s|nXXOA{rdŠ|f ‹l«–w«–wª•v©”u©”uª•v¬—x­˜yª—|¦”w§“t­˜x³z²šv°–rp¦”}«™zºzׂ–ýo¶ôt¯Õ‚˜µ’~¦šr¤šrª—t¯”z½‹à™èzžÄ‰«–z®™s«—t™™u®–r±€º‰¿Š‡Ë‹µw‡rHYE47oaU}rjaWPE9-q_H¥s«•y§’w¢ŠrˆxkJA8„yk¨“w°–q¬˜u¢•{©“wœ‹veXHaUCe«–w©”t©•vª•z‘€ki]Ks`¤‘v¬•u­˜x«™|ª—v™ˆmsfX‡ZmËxŸÎˆ•¾‘†Á‹’Ó¤¿|™x`Zy]\Êwžîy¶Ø~›Ïˆ’ËŠ“Õ„—æ®ä‚®È‰‹¯”z§–{¤sj[R993}n[©”u«“{ªœx¨­z¬¡{¯—{±›²©ƒ««{«¡y¬—x§ª|±Ûޝ©~¨–w«žx¢Æ€¬ñš¨Æ…²œx«•yª—v¬—{¨”u©—rpp]PcSFˆ€c«“u{m[<91MH?“…oª“s¬—wª—|¬•u«–z©–{©”u°—u¬—x“…oUL>@:/h_Q–ˆr©–{¬•u­–v¯˜x«–wª•v­–v§’v}oYWN@wn`Š|i¦“x¬—x«–w«–w«–w¬—x«–w¬—x­˜yª•v¬—x­˜yª•uª“s©’r¬•u¦“p¨–w¬™v¾}Þ€Ÿüqµìw¨ÛœÄ‹Š¨˜sžlª—t´~Ï„’å~šÞ€™ºŒ‹­“‚¾Ž‚‹„²‚¬™t¥—{Ÿ”x¡—u ’vmaW<91KQ@ˆwdeWKD;2J>4ziV¤sª”x¬—|ª’zŠzm>6/xob£u±—s¬–s¨—|°—w™…laUC`TB‰yb«—x­˜y¬˜y«–{”ƒnh\J…wd¦“x«”t«–v¨–y­šyŸŽmsiQ‚]gÆw É„™¾ŒŒÅ…˜Ö¡½•x]az\aÅxžÙ¥Õ}¡ç}²Ö…¦ß{«éy¹Û¬¾…®–x¨•zœmfVJF=9‚oZª•u°˜|²¦|¸ÆŒ®¨{®“xª›{®±ƒ¨³{¨¡v«–v¥®{°ç’®®~ª™x®¡{§Ì†©ö›¨Î†² w¯—{ª—v­˜|«–vª™r Žqp^SVH<~y`­–v‚tb@=5JE<‘ƒm«”t¬—w©—z¬•uª•y©–{ª•v°—u­–v—‡p^TC:7/WOBs` u«–w¬•u®—w«–w¯š{¨“t§’sqZRI;h`S€tbv¨“t©”u«–w¬—x­˜y¬—xª•v©”u°–r°—u®—wª”x©–{§—€Ÿ‘{±›x¬™xª—tÃŽ„ây¦õu°à|Ÿà|ŸÙ™³“|¡m¬—wµ‘¶¿Ž€ÀŽ‚½ŒŠÎƒ˜á{žØ€—½‹‹¬˜oª™x¨˜{¨–yŒ{hL@5ykTž‘k¨•r®­{ÁÜš«°y¬”v¥žw¬¼†©¾€©¤w­˜x¨µ¯ï•¬´¦šv®¡{¨Î†¨ùš¨Ô‡®¡uª”x§•v¬—|«–v«™p¤’sweZOB:up[­–v‹}jHE=E@7h¯™v«—t§•xª•vª•yª—|«–w±—s®•sŒrl`N;83JE?=LIA_VH‡w`¦‘uª•vª•vª•v«˜}¬—x¦‘r¦•{‰nb\Q[SFmaOz[ˆi©”u¬—xª•v¨“t ‹l•€ajaTXOBH@3I@6TKAaXNof\­”z¥”yÀŽˆêzªûr¶Ä‹Œº†¼Ž‡Õƒ–ïw§êy¥Ã‰Žš™w¯”y«–v¨˜sª—t¯”y±“z­•w¨˜s®—}²–s§‘uSMF./3NG>•„j§“t³˜s–ŠhokX\QMŒvk¯•w­•qª•y¹”x›tv977\TM°‚wЀ¥Î†©•|­–v¢‡leXH\SJ”zi¬–r©›w®€Ã‹Š¬uŽ[KE‹}fª“y«—t±v«—x«–w¯~ŒyNcwXW­†}®z¯šz¶”wº„›‡vcZLpOVË|¥ìu¹ôr¿ðs½èu´á}­Ñ…¾‹­‘y¥—sª£x©£x]pU3_;•ѵõ•±ù•­ÿþˆ«ôµÚ¬Û¡îŒ®Þ©¸z¢¬j±¹}»ä“ Ö‰©¦y¨š}©µ…³îš©é§­v®”ƒ©“w¬—w©–s©–sª˜y›†qxbV^F@zm]£‘zŒ|eZQClbQ¦’s¬”p«—x®˜u®—wª•u¬—x«—x¬—{¦”w—„iYQDDA9NJE|se«˜}¯štª—q¦™s«–z§’v§•x§—zžtŒ~grdNXJ8YVHdaSspbyvhol^]ZLSPBSPBXREbZMneWzp^„yeŽ€j–†o¢“s¥•xÀŒ†åx¦ós®ÂЉ´°ʉ䀜î|¡à€˜Ë†‰©“z¤–y¢˜v¤—w«“}­’~«•|§—z©”u¯—sŽ{`C>;-.2YSH›Šo®™z³–w˜‰ipkV[RI‰vi®—w¬—q¨–y¹“{§q‚:6YQ@aWEj_KugQ‚r[~d£‘t®“xÍ‹Œð|«ðv¤¼‹ƒ²“~¨™y®•{Á‰„Ù€æ{›í}Ÿ´~¯”z«–w«–w¯”z±“z«–w¦™s§”s«˜uk^H5100/3haR¡Žs±—y´~—†lniTWOBƒta«—tª™r¤–y½ƒ·m‘=4AVPQÆs“Û~«ÄŒ‹¼‘|­’}¤‹wd]NSQFŒ|e¨šp§št±Ö·w•]HGn¤’u¨™r°—wª’zÓžÑv­—]€gOCžˆl¦y§–|³•x­•w‰‚gDI4idU¥„{ĊɓĊ•ÊŠ–ÃŒ¸„±”«—x©—x§•xœ‰n_RJE?:dYKšŠs©–u­šu®–x®—w«–v§”s¨•t«™|«—~¢y‡xhwhXiZJfWGl]MsdTxiY{l\zo[~p]ƒu_‰ybe˜…jŸp›ƒoº”‚Öˆ“íw¨êyŸ¹‘~±–{¦œt q¦—v¶É‡’ׄ»µ“{®—w®˜u¯–v­—t¦šp jª—vœoLE40-/866vo\¨‘w³‘zµ‹„–lkgORK<~o\¨•r©™t¢—yÄ‹ŒÂj˜?5ATOLÑmà}¯ÃŒË‰Ž¾ŒŽ¶ˆ‡nZYTMJ|i«šs¥—s´‘ƒã~«´t‘X@BŠzm¢’u¨šp¯—{³…êx¸áy¶¥kˆZI<—…h¢’u¢–z°•{¬”x‚vd><1wuc¢’u±•r±“v­’~²€±’}«“w«˜wª™xª˜{ª”{ž…qeRKHA>”€o¬™x¨™y©°}Á顺{£¡q®º€´æŽ¬Ï…¨¶€¥»€¬ÉŠ¬í‘¦ð±Ù‡­×Š¤Ýˆ¬÷•¬÷•²Úˆ¢Æ€¡·} ³z¨·~¨±~¦¨z¯ªƒ¨Œ}cTOFXL:šŠs“…rWOBYQD‡yf¡u«–w­˜yª•v­˜y­™z¨”uª–w«—x£Žs|l[MD;D=:JB;wjZ§”yª–s¯˜x®—w®˜uª–sª–sª–wª•y§’w«™z¥“t¡p¡p¢q¢q¢q£‘rŽtŸv£’x§”y©”x©•v«–wZJ>~aX­o}Òu¢Ò‚Ÿ­”z«“u¨•p¦™m£p¦šv¬“°Œ„­’}ª•y¦—w©—z°“~²‘®“~«–z«”z„x`75+/.2EA<…zd²–~¼…´ˆ‡”}mgbMNF9{hY§‘u¬—w¥—{Ì…™Æk˜B7:[RIÕj¢á{²È‡œÖ‚¤ÐƒžÄ‚•{Yd[LP‘zj¬™tª•v»ˆì}µ¬q†O;:{oc ’vª˜s²“~ˆ“òtÆâ~®£uQD<€iŸ“o¡—u°“~­’p…t_C:0|se£”t­˜r¬•u©”~§—s©™u¨˜s§št¨˜tª•yª’|ž…q^QCGA:“|l°–x«”z¬©|Àßœš®s³•xµ¯„¹ß“¬»¬˜u«˜s²«€´Û¤æ§³y§¥}¦¶´ì™¯ð”£´t¡›v¬—|¬—{¬–z©“w¨t®“x¬‘w£‡oiaTMC2†ycyi_NF>1[Q@˜Št©•v¬˜y¦’s§“t­˜y«–w«–w«–w¬—xœ‡qeXJE<8B;8ULB•‡q¨“w®–x¬•u¬–s®˜u®šw¬—wª•v¬–zª—r«˜s­šu­šu¬™t©–qª—r­šu¨–y¨–y©”x¨”u©”u©”t­–v2.)41)H/3g7SqS^‘„n ‹u±“z³—x­—s¨–q©–s¬—w­’x«“w¬“y¶ÃˆŒÍ„”Ð…•χ”¬~j_Q./+0/1SMB‘ƒg¸“…Ɖ“²‰‡yie^KNB<~c_¬‹{²”{¬”|×§ÁmC8:eRMÔl£á|°Ð‚§Ù€¬Ó…Ã|Zd\PPyi°—w°}Ê’î|¸¡rzJ=5i`Vžu®–x¹†Ö§ëxÁÖ„š•xoKC<Œ|l¡“o£—s°•{®“x“|mQA;oaUŠo®™s°švª•y¤—q¨›uªšu©™t©–s©•vª“yŸ‡q]VEBC9|g®™y«•y­¦{¶Ë §t¬˜y§²€¬ä‘ »{«˜u¯–t°§|°ÚŒ¦ã‹¨§u¯—¬ª‚¹çš¯ì’¤®r³žƒª’t«–w©”t©–s®œw«œu¤˜n£—m„waRJ9g]L™‹uŠzcZM=I@3xn]¥t¯š~ª•y§“t­˜y­˜x«–v«–v«–v¨“w‰xc]QE<61C=6ndS¡‘z«•yª•v©”t«—t¬˜u©”t©”u­—{ª”x«•y«•y«•yª”xª”x¬–z®˜|¬˜y¬˜y¬—x«–w¬—w­˜x°™y>81+1&0/%9)011+85-ZPF…ue¢Œz©”~¨”{«–w¯™v±“v°”u²”w½~ʇŠÔƒ’׃•Õ„“ zvTEB0230..dZIˆl¼Ž‡Ð…¡¯‰…Œxfe]LSBE„ak²‡„·‘³’~à{³¸nŠF8>sQ\Ñn¦à}­Ùª×£ÃŒ¯ƒ|nbVTWH‹{d±”y¸„Ï…é{¶›xtLG8VRG™‰r³“|Á‰Žéz¸Ø­¿‡‚€t\FF:‰xk¤t§™u°˜t¬—|•…t\LE`RF˜‡mª—r°›uª–s¦’s«˜w¬—w«–vª•u¬—w«—x ‹oXRE9<3‚u_«˜u©“w°¡z«³~¬¢z¤˜v¤±}­çœ·w¦—v©”u§›w¢É~³Þ“°¨y¬—{§¡|´Ï±Öެ©v­›|²”{²“|®xªu®“y­•y¬”v¯—y—…hd\KOI<—‡pª•v‰yb\SFNE<Œz]¦”w­˜|©•v­˜y­˜x®—w­–v§”s­™v¦‘r†xbRI?EB:IC6|r`£Žs«–z­™z«˜wª—vª•uª•v¬–z«–{«–{«–{«–{«–{ª•zª•zª•zª•vª•v«–w¬—x¬—x«–vª•u”yuugadNRI@DARFB_TL`]HosVŠ’suc’y_Ž€murcMM=qhT›‹nª—tªšu„ziRF4\N;Ž~g¨—}§’vª•v±šz¬–z«–w¬•u¬•u«–v«—x¥”y ‘w‚l{lYeYG]RDULBKCXQ@_XGleRvb„p’‡q…oukZh^MWM“ooÓx©ß¤Öƒªê~©©wLAC[HQ¥u{·›Ö€¨Ù€¨µ‹£‰xo_NoTW¤wˆÉ…œÚ¢ã}¬ª”{sjgXL>D›sx¹‘ÇŠ”çuÂ₦§~|VPEWPG˜Šm¨–q©”x¬”x«˜s”†pZPFXOB•ˆnª—t­—t­•y§’s¬—x«–w«–w«–w¬—x¬—x¥q\WN93(SK:_T@`U?\Q=ZNKA7LB8JA7HA8D?6=:2A>6;<:9:87865645647869:8;<:4@47;5941>;36;,5A-AN>9C7XB7SC8J>8ODtfh†²¥ˆâËijzto9//-:8YRCˆy__XI945„YdÜs¶á~¬ÏˆœÔ§°peEXXNGmqÑz¦èy±çw·Ï†œ ˆtLN:N;D–lsÄŒ‹Ë‹‘Ј”ã{²¾~‘s_NgdH˜Šs»‡Ï…Ú{´Ü¨Å……i]LF;~c¬–s³ÏŠ—â‚ª§|UNEUMF–ˆl¦–qª•y®–z«˜s”†pYOEWNA•ˆn©–s¬–s­•y¨“t­˜y«–wª•v«–w«–w¬—x¥qe^UOG:‚wcx¥—{£”z¥•~£’}¥‘rª–w©—x«™z¨–w©šz¦—v¦—v¯˜x®—w®—w®—w®—w®—w­–v­–v²”y³•x®™s ¦m®Ï„·è– Î‚’µr—¡wi•Œk‹g[TAZS?“‡k©–s«–w­˜|œŒuzlYcUBykU—†lª—|ª•z«–z®–x­—t¬–s­—t«–vª–w©”t­–v¯˜x®—w¬•u«”t­”t­”t­™z«—x§“t¤’s§•v«™z¨–w¢qª–w¨”u¨“sª”q¬–s²šv´šu •zª™x¡«š„îᨭž³ }¦²´Ú“ÌÜ’Ô¸–»›i{ZAK=0>ˆLu´sŒ«—–’űξYli3./6<7rfT–„eZQG857†[h×u·Ò„œ¿‹×£µp•gKQTOFˆnnÉ}œèw»ëw¼ÁŒ˜ŒpOP@P4G¢eÑ‚£Ú©ß¤òu¿ÊzŸyZ[jdQ˜Žp¯–v¼ƒÁ‰–×|­Ïœ’ipPF<‹{d®–z°’yÁ“Ù„¤¤{TOFXMI™ˆn¨–qª–w«–v«˜s”†pYOEWNA”‡m©–s¬–s­•y¨“t­˜y«–wª•v«–w«–w«–w¥qqh^TK=‡zd£’w¨”u¨“s­˜yª”x¯™v°šwª”q­—s«“o¯—s¯—s³™u¨•z¨•z©–{©–{©–{¨•z¨•z§”y«–w¨”q¥¡q¨Á}¬æŽ®ñ•²é”¿äšºÖ›´¼‡°£w¬˜y~p]XQ>wkS Žo«–w§’v©–{£“|}oYfXBn`J•‡q¤”wª˜{®š{¬—w¬•u«–wª•y§”y­–v¬•u­–v­˜x¬˜uª–s«—t­šw«–p®™s®›v¬™t©–q©–q¬™t®›v¨’o«•r°šw®™yª•u©•v©•v¡–{¨”q›¦’uçÖŸ¡Ž²–w§“’ㇸ”ÉnŒ5B:1/.pHaÙb­â€®¿ƒŸ›†«¡+HE311MC<‡yf¤mYPG76:‡\iÔv¶Êˆ”²’{Ñ„’·vhVERV=‚scÄŽåy»ë|º¼Žƒ–ŠrKKEL/F£b‚Ü{³ítÄùqÃ÷rÉÑw¥€YarcZšŒv©–q®˜o®˜t¼ŠŽËƒ¡ši}PG:|]¢›t¥—sµ‘ЄœžzSQFZNJ›†pª–sª–w©–s«˜s”†pYOEWNA”‡m©–s¬–s­•y©”u®™z«–wª•vª•vª•v«–w¤pne[QG6…w`¦”u¬–s®–r¶œx±–t¥”z¦•{¥’w¯šª“y«”z«“w¯—{­–v­–v¬•u¬•u¬•u­–v­–v®—w©–{§•v«§~·Ð”®ß“›Ì€ º~­­ž¿†«³~«šo³•|žˆ}n`ZeWKˆtb¤s­˜|¦‘u¨•z¥”zˆzdfZHvl[“…hŸpª–w«–vª•v«•yª”{¦‘{®—w®—w«–vª–w©—x¦™y£˜x¢—y¬”v¬”xª”x«•y¬–z«–{©”y¨“x¯™u­—t«–v¨–w¦•z¦—}¢”} ¡wž’n ©Ž•ʯ­¡•´Ž‚ɔς¤‡cE6D+10Md`°w†ÿmÇùvÆÝ~«º‡Ž|md;:601-TSE¤ˆp›p\ZBH6=Q{Õ|¨Å†©—xÚz©´ˆfSFTHH€geÈ~–âz·Ì…Ÿ²—už’p[VAB95liª~¹ƒÃŽ‘»‘’¥„ˆs^]scW™‰rª—v«—t«—x²”wª“}†uhXH;‹xc§’v©–u§˜w¯–všˆqZOA\SF‘ƒp©•|©”y¦’y­—tœŒukdUGA4Œm¡‘t¨•t«—t£’x¥”y©”x¬—x«–v¬—wª•u¦‘rogV\P>…w`¡u¬˜y©”u­˜x©”t«–w«–w«–w«–w«–w«–w«–w«–w²“~«žx§­t¥®o¤¢l­—sµ“|»’ƒ¦”uŸ¥t¥Ó†®î•¬Ëˆ³ ²š~˜™m²œy¬—w¬—wª–w¤’uœ‹p†w]iZ@•€j©’x«’r®“q²™w¤qcsgOOPLOLGRLEe\O„uež‹v©’|ª’z©’x¬•{¯—y¯–v­•q°–q±˜p±˜n®˜n°šq¯štª˜s§–u£–v£˜z¤˜|§•v¥•xœuŒkvo\a\MOMBKKEˆnhŸ‚Žª–¤¤’º’†µ€‰™XrH.E006Utk~¼®¥¤¦÷tÅèu¸Óƒ¦ª„„XME.)*<30wkY¥Žtra\GK6>Nv×u©Õ~ŸÀŠßxµ¯wŠcRIPLGukZ»„‡Ø„§ÅŒ®w¢‘vb[JA;6|le©‘yµ“|·±Ÿ„vq`StfSžŽq¬˜uª•u«–z°•s©“z‡xhWH8Œ{f§’v«—x«™z«”tšˆq]P@[N>”ƒn«•y­•w­˜y®‘l¥t}q_J@/ˆ{e¥“v­˜x¨•t©–{ª˜{«—x­˜y©”tª•u®™y©”urjY^R@‹}f£’w«—xª•v¬—w¬—w«–w«–w«–w«–w«–w«–w«–w«–wª”{«¬‚³ÌŽ¸Ý•³Ô‘®Ä‰§¸¡°w«œ|©¼…´ß”±Ð‹§¥u¨“tª“y§™|®˜u©”t«–v«—x¨–y¥”y•†lpV{lY˜‡r«š€®™~¦‘u¦’s£‘t˜†izp^mcQ\RAND3I>0K?3TH83vk]¡’q®˜t®“y±˜v ŽqrgLrgKœl«—t¦‘r§‘x°™s©—zlVJ8‘j¥tª–w¨–w®™~‘ƒmUJ:;91:80;91?=5EB:IF>LIAQKDPJESMHRJCNEOE>DE;FE;FF:HH9QK@„p¦•{ŒrqcLPF<<61?;:<4-†xf©”x¬•u­•w¯–t¨“s¬š}™Špj‘jŽt¥”zyhYM;‘ƒl¤“x©•v°›|¨“sª•u«–w«–w«–w«–w«–w«–w«–w«–w®•u²–wµ–w¸“y¯‘t®§|µÐޝã¬Õ„­Ã‚¶Á‰±Â‰¡­y¡™q«–vª•u«–vª•uª–wª–w©•v«—x¬˜yª–wª•v™†k€s]`VEPH;UL>f\K‡yg¡r§•x¬˜y¨”u§’r«—t¯™v®˜t§•v¤’s¡rŸŒq–…k{dˆu`‡t_‹{^‹{^cŽg‰}e€u_xo[wnZ_UNTJCG>:?94?85@;:E@?ž²ÏàÚäH¨®dvwg\fBHM5BD,7456-)/$0#75-K/;reUªŽv³´”w¯–v¢“rsnUI@6}p`£–v¢“rŒzc[K?aTLg\Tp` Œs®—w«–v«™|­šyžu‹p`UG—†qª•y¯šz¡ŽmphWJD9:5,YRC”‡q¨—}›‹trdQQJAD?KD;‡yc¬—x«”t§’r®•s°›|œ‹qaS@TJ8LB0ZL9ˆ{e‚ziTH6‰{d£’w©•v®™z©”t©”t«–w«–w«–w«–w«–w«–w«–w«–w¢•u©˜w®˜u´™w«šs¨·}°ì”§ÿ”¶á«´{­«{³Ì§Ê‡ ªuªžt¨œr«—xª–w«—x«—x«–v«–v¬—w¬—w¬”p§’r¡Žs•‡q…ygg\NPE7PG:cYH~r`šŒv§–|ª–w®–r±—r²™o­—t«•r«”t¬•u«–w«•y¬–z«–{ŸŠu˜„r{j}m]fXLNC;C92A70:73=94F@9UODi`S~qa‹}kÙèÍæ' ´;bpYX\ƒŽ¢ˆ ¬‡ ¤jttQON172'2/3422440/3444+/)340B::’€o±™o­”tŸ‡sj]UIJ@fdLŸ‹l®•u¤—wµ’~°†z|kXED:peW¥u¬€­•w®–zœŽqwnZPE=‡wg©—x­šw¡ŠtbXGTL?[RH€r`¤t­–v§’r¦”w™„i|l[kaWXL@~k¦‘u®™y§”q¥”z‡zd|q]“…n¬˜y¬—w¦”w—‰r–…po…{j‡yfžŒo±›x­—tª–wª”q«–ziOG6e_R`XKF=/ukY€xgPD2ƒu^¤“xª–w«–wª•u«–v«–w«–w«–w«–w«–w«–w«–w«–w¥—z¦—w£’q©–u¦›u¨¹€²è•¢õŽºÔ˜¢¤vŸ”n¬²±Ð©Èƒ¥«v¨•r­™z«—x«—x­˜x­˜x«–vª•u«–v­šy¯šz¨“s¦’s¨•zžŽw…udeXHA7-G=3XL@ndS…yg‚oŽ€jˆzc‰zgŠ{hŠ|iŒ~kˆ|jucqgUg]KYOHUKDOE>G>:H??C<.2?8;EDFH?B5?969=<:@34212.GC>‘†r¦™m³˜v¤Šyl^XNIFqdV¦‹p­–p¢›p —q›ƒmunUEJ;mfS n¦—w¦œl ˆr‰z`mcRXJD|m§’r®˜t¬•{Œ‡nb_JZTA‚u_ª–w´›yª•u¦”w•€ko^Q]QKXKCŠzi£Žr¬˜u«˜u«“o¬—x§•x¬—w¯•p²˜p®˜u©—z­“n¬—w¦”w¬š}®˜u°™s§“p©šz®—w§•x™‹xWOB_ZQ_ZQUOB‹‚t~veNB0s\¥”yª–w¨“t¬—w­˜x«–w«–w«–w«–w«–w«–w«–w«–w¬’z¯–|­”z±•}«wªž|³Â‰¢ÇŸ§~Ÿ y¨™y©—r­¼²Þ‘©¿…³š€ª–w¨”u¨”u«–v­˜x«–v¬–s­—t¡“wª˜{¬—w²™w¬“q©‘s©•|˜‡r}rjf[SMD;C;4?;6<949848954/,83085121-0/+01-35/260RJ9d]JrhVriUujTƒw_Ž‚j”†o¢Šn«“w°˜|¯•w­“u¯•w³—x´½-O\gy€”§¶ÁÙšÂÛˆ£±?II13-5@=8OQJ`fJW_PYcZTYD8613-2@5IK?›ˆs´”w«”t¡ŒpzkQfXB€r[£u­–v°–qtdNE7cZPSLClcVš‹x¦‘vª“sxrgGA4G?2RI;ˆ}i¢’{¤’u«–v¢”x“…hŽ~a™‰l¨–w«šyª—vª—v¤”wœŒo–„g•ƒfž‰m§’v­˜y®™z¨“s®˜|­–|¨“x¨“x¨”u©—rª›t¦’y¨”{¬–}§’w©’x­—{«“w®–z©˜q¨—v¦’yygo]LpbLŒeŸ–t‘~i^K6ydN§‘x¨‘wª’t¯™v±™u®›z¨•tª—v­™z§“t§’v¬—{¬—{­•y¯—y¯—y­•w­•w°™y±šz°™y±‘~°”|®˜|§™u¥ s¼ÀŒÇЗ£°rª–sª•u¬—x­—{ª”x¨•tª˜sª™r«•|ª”{©”y«–{¬—{«•yª•v­˜y©’|£‘t€`uiMn_LyiX†u`‡y]ukSqfPmbNn`Nn`NqcP{oW†y_šƒi¡Œp§“t§“t¦’s¥“t§–u©™t«–w©”uª”x¬—x¬—w©•r­št¸½!gnXho‰°¹žÁÕ¦ÂÓ‘©E;A88>.ry®µ ÇÒ®¿3™˜;^a@24B73EF=XL@—‚m¡’r¨™˜ŠtvjXcYHvjX–ˆqª•y¬•u‚taUI7NE7H?1siX¡{¬—{¬“qž“odPbWCeWDŽ€i¨•z­˜y²›{­–|ª“yª”x­—{¯™}¬–zª”x«•y­˜x«–v©”t©”t«–v¬—x«–w©”u­–p®–r¬“s¬‘v°˜|²š~®—w­–v«•q¬–r­—s¬”p¯˜r²›u®—q±št­˜rª–s®˜|«•|žŠq›Šo£“v£—u‹„q`VEndS•ˆx}—ˆu‚l”ƒn‹€j†{e{pZodNk`JlaKpeQujV…waˆzd‹}gŒ~hhhhŒ~g‰z`‡x^ˆ|`•Šn›“u ›z¢ ~•“q«—t¬˜u«—t¨“s¬”v®–x®–x­•y©“w«•y¬–z«•y©”u©”u«–w©•v«“{«—x©˜w£•xžxš‰vŒrŸp¥•x¡‘tpžr¡u¤“y¥”z£’x¨’v«–w¬˜y«—xª–wª–wª—v¨—v«–w©”uª”x¬–z«–wª–s­štÂÄŽ6ENxž£›ÁͬÄИ¦¬HAD;6?.cp§¸Úë×ìµ²NP9+/H?<>A8YK?ˆs›y„zikbTPH;KC6e]L‘ƒp©˜}«—x ‘w†xareOf[GˆzcŸŽs­˜x±™u«™z›‹npš‰n©—z©”u®•u¯”r®’p²–t²–w®•u«‘sª’t®–x¯š{©’r¬•u¯˜x¯š{­˜|ª—|¨•z¨•zª™x¦”wœ‹q–ƒn•p“€q“€q•‚s¥’w¥’w¥”y¦•{§–|œsŠzcƒs\‚p_‚o`o_wgWl\Oh[MdWIZM?ED@651=:6@=9=85=55;33D:::49B=??:<946<78:56501612601934<67>89?:9?:9A<;D?>FD:JE1,.15/,6*YRC—…n’‡glbQ`XGXP?e[J‚wc y­˜|ª•u¥‘r¨–w¥•xs§—z¥“t¬˜u°˜t®™s­—s¬˜u§“t­˜y«“u³šz³—x¯—s°—u¯™v­˜x«˜w¨–w¥–v¢”w«–€§’|Šu~k€p_sfVl_Qh]OXUGSODLG>FC;D@;C>;B>=D@?E<9E==F>>B<=>9:83530295:9296052-/0+,/--2/1-+1&#,%(,-.2356-//01/999:88:88:<=?AA@BB@CABFA>B=7;559336425304/-1,*.)*.).2,26003156431040/50/2+(4+(;2/A70MB:XKCl^RŒ|kžu¤•t«›v°šw«•r¬–s­™v¬˜u¬™x­šyª—v°–x®˜u­™vª–w¬—|®—}­—s¯œo±•w²•z±–|°•{«“w¨“s©—r¬›t«˜s©”u©“wª”xª–s«—t®—w«’x¬—wª•vª”x¬–z«–wª•u¬˜uF~‘1ºÂx‚FSavœž—¼Ò•³¾Ucb=:5<3/63/<<6@>49@S '0,2-53(\UFŠ~l¤“yˆi–ˆqœŽwžŽw¡vª˜{«–w«’p°–r¬˜uª—v®›z¦”u¦”u©–u«—t©•r­–p°šv­˜x¨–y©–{¥’wª•z¦u›Šw•„q€mlƒygtmZg`OaZI\PFUKAOE;F?6?92;72961961<<67:17:1:>3=C8AG<@F;>D9:;9:;98979<:@BBEJIQUV]abcgaaf]`gZ_fWZdTT]PU]R[cYdh\gl]pwbu~d~†hŒ”v“š•œ• ›w“Ÿ{š¦‚š§˜¥™¦€™§~šy™uˆ”p„li€gŽhƒj„‹pu~diqZ]cPOUD@D859.14+-0'12.1//823IC>]VGxsZ—”u¨”u­™z¯›|«—x§”s©–u«˜wª—t­”t¬–s­™v©”uª“y®–x¯™p»¦s½¡x³—t®‘v°”|°–~«–z¨–q¦˜n¬™sª•v¬•{®–x®™s³s´œx¯•w¬—w«–w«•y«•y«•yª•v¬—wGKg*—¬±¹"^jUkp•¬Æ™ºÉc|€657:572<<4?<@:5E1>///PSDwcQ§ƒq²•€­˜}©”t¦’s­˜yª•u©’r­—t¬“q­“o¶œx°šw§’r®™y¬—wª–w°œ}­™z¨”u«—x©—z ‘w•ˆrˆ}izo[peQi[HUKKLC@B;8<748302/*30+55/33'55);;/CE9MQEU\O\cV^eXpoZyz`…‰lŽ“s’˜u”šw‘˜u”sŒ”v‡p|‚cv|]y`ˆg’—wŸ¤„¨²ˆ°º±»‘±»¶¿”·Á“µ¿‘´¾¶À–µÀ’µÂŽ³Â‰´Ã‰ºÉºÈ’µÂޝ¸—Ÿzˆk‰dv}ZszW{‚_†cƒ‰jˆŽoŽ”u–|¢©ˆ®µ”´»š´»˜ž¥‚¡¨…«µ‘ª¶’¢®Šœª†ŽŸzkft\WbN?G<04.-.*33-LKAki^Ÿ’|›w˜ˆq¡v­›~¬˜y§”s¬˜u°™y­—t®™y«•yª“y¬”v·¢uÔÀ‰éØ{ÛÆtƱm¹ n±—sª’v«“}®–‚«˜rª•v¬”|®—w²p½¨u¿¨zµ›v¬—w«–v«–w«•y«•y«•y«–wG\¢· Úæ&” IS]x…›–¹Ã|›œ7828=59:;67;7,{pZ¤sµ—|¯w­•wªšv®—w®˜u­—t¯™v²œy±šz¬—x©•v®—w«”t­–v¨“t¥t©–{¨—}§–|Œy†xfmbTXRGNJ?GE:A?4@?1571690:;1>@4FI:SVFcgTot_{„i‰k†r›{™¤ƒ ¬ˆ¤±‹¥²Œ¯¶‹°ºŒ´¾³¾Œ³¾Œ¸Ä”ºÄ™´¾”ª¼“³Ãš²À–µÂ–¹Å•·Â»Ä‘½Ä‘¸Ä”©³ˆ‘›qˆh–žv§°…²½‹¼É“µÂŽ·ÅµÄŠ¸È‹¼Ë‘°À‹•¢v}ˆ`SUIFH<<=39:1762532755:88E>AE>AA:=?8;D>?KEFICDB<=@>6A@6JM>V[FluZŽ™xœ©ƒœª¬¶˜¥¯‘˜£ƒ†rioXLNB@?;B@@|sixobsiX†xe¤”}«™|¨“s°šw©”u§’r­™z«–{«•|­•w±œo˸ûæmûçrõátçÓtÖ¿sÅ­s¶œt®s¬™sª”x«‘y­”r´¡nųvDz{¸ r¬˜u«–v«–w«•y«”z«•y«–w"Ÿ§ ÜëÍÞ¡­9@O^nz•®°ˆ¢œ074=25=08102-85,4-QD4•€dœ–qžšw©•v²™y©–s­˜xª“s­–v¯˜x¨“t¦”w¨—}£”z©”u°˜z¬”v§‘uŸŠo“fp[ugQiZQ_TL\TMROJFGCEICFJDSXOcnTr~b†r“ž}¡¬†¬¸Žµ¿”·Â”±À”²Â“µÃ“µÄ‘¶Ä޵ċ¶ÄŠ·Æ‰²Å’®Â¬Ã°Ç‘²È”©¾‘ŠvgxV_x\\vX[rRyj ²‹°À—©¶Š’Ÿq]lQMZDEO?KSHNWJLUAgsW˜¦„²¿“´Á“³À’¶Ã—ª·‘€‰nX]NMPGcdbddd_^`a_ekgrokwoiztn„y~s‡qfzf[oh^ooevlbscYjUQ]HDPD?H>:??:;?<8DA9SQGdfPuz[•t°º‹±º–š}oocSNOB=:]WRcZPh[K‹ze¦“x«–w¯™v¬–z«—x«™|¤w©’|®™z¬˜iº¨mü×oÿàrÿènûçjøçnòâxãÏwѺnµ¢|¯™}­“{®•s¸¤m˺w˸{¹ n¬˜u«–v«–wª“y«”z«•y«•y°¾1´Â#wƒ"CLTX]©¶ž¾Ëˆš¥39@;:>>;=999:<<:+3cVTŠ€n—Œn§št­™vª’v¯’}²”w°”v±—y°˜z«•y¨–y¦–y¡‘t…|apgSXMEI==>4:938;99>?=HC@MJEOQE\bOy‚hšy›¦€¢«ƒ¯·’µ¿•µÀ’µÃ“³À’§²Š¨ˆ¦‹”™|Œu…†l“”z£©†´Á•®ÄŠ®Èˆ°À‘µÆ“µÇ’­¿Š¶Æ–Ÿ¬†foU]eTs”l†vUdV?K/’œr¯¹diTAB@VZUquzz~|€˜y|‘fhpZXPUSA”Ÿw°¾Ž³Ãª¶„qvWYWMndj‹~Œ…§¡‰«§±©’²©“°­—´¯™µª”°°˜¸¬”´§°¥Ž®¥¯¦Ž°£Ž¯¡Œ­ˆ®™…¨Ž{œoŒwfm]t_PeSEWWPUYSTEC;[]J‚‰n𥅩µ‘“¡}lnZBC:?>B^Z_[UPƒuc­˜|¬“s­™v®™yª–w§•vª˜y©•v¨“sª•uѽhóÝsÿçoÿâoúásøçoÿílúåaüãuâÎi˵m¼œyÀŸxØÇpÓÌk·¦u¯“t¯˜r«šo©™n¨˜sª—v©–u9IY?CUEDNnmo«¯ª™½Í¥ÄÓŠ ¬CPX06;7:>UYZ?DC;9/WSH`YJj_KŒ|eª•z¯—{±—y«œ|¤”wš‹q~kwgZ\OGL=:A4250/50-63.>=3ORCelWzƒh†r‹™o—¥{¡²†¨º‹®ÁŽ³Å¸ÆºÇ‘ºÄºÅ¶Ã‹¸ÇŽ›ªwp~UVbD>H15?.5?/5C.‚‡jµ½•¹Ã•ºÅ“®¸Š·¿–ª°uz]gmVovaU^J9SA4F9;E8S[D›£~–sIL=HIMx…’Ÿ­“ º‘Ÿ¼›¨Â‘ž¬mxvDNBjrS¦±‹³¿•‹‘rTTHkbl“†œ§˜³§š°Ÿ’¨™¡“‡›Š~…zŠ…zŠƒxˆ‚t†„vˆ†wŒ†zŽŠ~’’…›œ¥¤—­§–±©˜³¨—²¦”±§•²¨”±œˆ¥Žz—l`rdZgWOVMIHII=PU@v~`¡ª‰¨­‡ŒwKOC?>:KGBlaS‘ƒg©—r¬–sª”q¨“s«—xª–w§“t©–u®™y¼¤nÝÆpýäpÿåmõÛoï×sóÝsÿçuýÜnûäpóáväÊ}àÂ{êÖqßÏo¸¡q¯—¬”|ª”{©–{¨–w¨•t«–v£²Žž®Œ¢®—¹¿ ÍЦÄתÈÙ ºÊ„œ¨o‚Šjx~{„‡49:79-RRF<8-A7-l_OŒw¦“x¢ŽopiZ^XKKE:?:174,2/*651A@B=u‚Š•¢°›ª½†”«hx‰O_eDSKCQ?„g²¾”¨³djSFBA‚xˆ¡”¬š§…€‰hclLGP@<:@EBKSPY]Zci_lwl|ˆzŒ“ƒšŒ§§•´«–·¥²¢­“žƒrmauYO[EA@BB4WYE†l¤­Œ™{agTGF4@J>@J=KUE[eUQXIFLAPRLFGCTgV`qcpqu‚tftb[mVVlPIaA:?405/.0:9;DFFHKIFKIEJHFHHFHHFHHGIIDFG@?A657/.0635;5:>7>G=IXM]uf{Ž~•¥£‘®©–·¤³Ÿ‹®œŠ©ˆyŽ`U_<67<@'flMž©ˆ «‹s{dFF875*jf[£Žo¬—w­–v©’r¬•u­˜y«—x§•x£Ž´œxØÀtöánýçpëÑsαnçkÝ»yæÓrìáhüêuÿèuÿçkÿçqò×uáÊ|зqÁªr¸ v¬“sª’v¯—{ŸÇÌ ÇÏ ÆÒ¡ÃÓ¤ÄתÂÖ¤ÂÕ¡Å×—ÀÏ¥ÈÕ™³º_kq.15]TFyllf[^XQEB>;99546@?CQRBqs_“šª´¯¾’¯ÁŒ¬Â‡¬Ä„ºÈˆ¸Ã‹«´‰•vmnZNN@>>299-2872=;7HE5LH.MF3TM9\R8[Q;LH6EA2@:29423/7327/05*,/).7-36*05)/4/14:9:NI;VM<^T=XN3D;?ICYRWwl|•…œ§•´¨“¹¥¶£±–… o†GF<:=-z‚d­º”§µŒt}b>>882=}mV¢‘w±œ€¨“s¬•u­˜xª–w«™|£•yª“y»¢pàÌmýëpøäuÜÂu»žkª”qµ¥p´lßÉw÷Úwÿákÿékþëlÿênùáië×lÓ¼pµœp®“y¯˜~°Ç׬Æ×§Â×­ÃܶÉ䬯ס¿Ò¢ÇÛ™ÁÓ¥ÆÕ’¨³BKO/.0fZV]PN=41<74?@7IPAZgQqg¥±¯»‹·Ã“µÁ‘±¾¸Å—ºÇ›²¿“®±Š…‡iSUB261&00&57*?=/FB6oVY–|wºzƤuÈ¢zÒª{Ô©qË ƒÏ¦tº•`¢M‡jOiS}kCgY:]O;I>=H>:E;9D:9JAAZPSwkLwjX‚qLn]?XDeq]”Šyƒ‰p‚‹q{{ituaqs]tx_hnU\cNPUFEJACC=@@:CC=EF=KMAY\LjoZ{h‰“u”Ÿž§Œw|m?AA-,5::@[\`vy‹Ž–œ¢§¡ª­¢®°£±°¦´³¦·´¤´³£³²¥³²¥³²¦²´¦¯² ©¬ž¥¨—¢ ˜ Ÿ•›š‡ŒŠiljIJF45100*:57NFPyo€•‡Ÿ ¯¬™º©–·¡®khj882_eN¥±‡³Ä‘ ®…sxi206F>1yo^Ÿxª•y±šz®—w§’s¬—{ª›tª•z©’rưnê×núçtòÜ}Óºr§˜~§–{¨”uÁ¦séÍvýáuùâtõäoÿâeÿëiþërãÐuÀ§u¯“{«“{¸ÌœÁ×–¿Ö ¿Ø©¿Û¨ÇÖ¡ÂÒ ÄÖ¢ÃÖ«ÅÕˆ™¢49<501>67A:7NLAikW‰j›©€¯¾’´Ç–¨´Š›s{†`v^„Œm—žƒ–}syb;>508.#4+<3'RE@xed§ŒÉ«wÚ¨†ë·Šô¿€ï·~﵄õ»†ø¼†÷»ôµö¹ð·xä°yß°xÚ®vÔ«wÕ¬€ØªuÏ¡oËœmËœrËŸxÌ¢‚Ï©h°ŒVsc0G89F8VXLB@6/.$58/.5.50/41-/0'34*,0%+-''($310*/.'*(-0.-1,)-''.'*2(09/342@C:JNC482*+/EFPtu™œ¡”¦§œ®¯œ°±™±¯šµ±›¹´™º³š»´™»´›¼µ¾· ¾¹ »·Ÿ¸´³±›±¯¦µ·¤±³¡­¯¢«® ¨¨’—˜w{|dfgED@644=:<[S]wm}˜Œ £•­‘‚WU[,.(`gL¨µ‡¸Æ±À¤¯‰jqV/0.EB:i_Ne¨“t¬•uª’t«–w¯™u«—x§”y²œsжpïÖtùäwîÚo³£u«–v°“~Á¦tãÌpëÔqÔ¼pͺvçÈyéÐzãÑxÍ»tµ s¨’vª•yMOYsˆ•ºÂ¡ËСÉΠÂÏ§ÊØ¡ÂÕ¨ÆÙ«ÂÒz†-.2;65V[Lu}f§²ŒµÃ“´Á±»Œ›£{uzZRULJMDMQFQUISXIX^MJP=+2,755JAJo[iŸÌ ˆè²„ò·€õ¸„ô¾‚ò¼~ðºó½†öÀﻂ브óÀ‚ñ¹„ó½€ï¹ƒñ½ƒò¼ðº†õ½„ôº‡ó¿„ó¿}ó¾}ó¾‹öʼnà´p°Œ0aA*7/'-(8437,.9,.;65./+,3.>9:=<8@C:FJ?@F;KNEFG>GH?DEABA=EE?CA9>?6AD;:>8593:7@<<<8;2-2)DIH{~‚¢§ª©®¯š¸³ž¾¹žÀºœÁ¹šÄ¹šÅº—ŸšÈ»—Ⱥ˜Æ¹—Ÿ˜Ã¸šÄ¹œÄ¹œÁ¹›À¸¡²µ¦¶¼§µ»¤°¶¤«´¥©´ ¢­—™¤“ŽstpGHD=;:@;=XQXndqF:L+,0:>2†n³¿¶ÄŽ¶ÄŽ·Å¦µ|UY^9:8DK~{‹ž©±˜¶±”¿²’ɶ“Ê·“˸’͹ϹкѺŽÒ»ƒÖ¶‡×ºŒ×»Óº’Ò¼˜Ð½˜Ìº–Ç·šÇ·˜Ã´˜½³›º³Ÿ·µ¢µ¸¡±·ž®´¤¨­¦©®—–švqsQLM865586BGEKPA~‡l¦·‹°ÆŒ³È‰¶ÇŽ¶Â’´¼”–ŸwX^G961IDA{sbœ‘s­™v¯”r­”zª•u«˜u¬˜y®–x¼£qÞÇqüêuóâiϳr´•tdzyÞÑuнl¶œt«Œƒ¯–v®˜t§—s¦•{¨’€«”tÁ­lM^a+7;#)..16B?Htˆ“ µÄ¥ÃÔ™ÂÑ‘­¸OSX2/*mte°½°ÀŠ³ÅŠ¹É”‡‘mWXHYVRmhiƒŽ†‡‘e`i835.2-5N@R„l~Á¤â´ñÁ‹ò¿†ð»…òºò¹€ò¼ñ»ˆëÃâºz×°yÒ«xÏ©wЩyÔ­}ر†é¹‡ð¿‚ñ½yïºxó»wò¸xò¶|ô¹|óÀ|î¹ôÁ‡Ö¯H|e,F928-<9+_hN{„i™{”|’šu– vž©{Ÿ©z¡®z¡®z¡®z¡®z ­y ­y¢°z¤²|ž«}Ÿ«¡«¦°‚ ¬z›©y¬†‹š{GUI#0(=JHr~‚”©ª›¼µ›È·›Ï·”Ô¶–Ö¸—Úº—Úº•Ú¹“Û·”ܸ”޺߼à½ß¼ŒÛºŠÙ¸ŠÙ¸‹Ùº‹Ùº’ζ•ι˜Ï¼›Ì¼šÄ¹˜½µš¸³¸µ¦¶µ¦´³¦®®¡¥¦’’’nnnGII/43QRI~‚o¥°´Á“²ÂŒ³Á‹µÁ¹Ã”°»„ŒnED:B>9ZRE‚k©–u²™w¯”zª•uª—t©—z©‘y²˜tɰráÊtùéqãÍuÀ¤n¼ w˳¾«n­˜k¯”°–x¯™v©—r§•x©”~¯˜xìt•²»l†9jk[¢…±º’·Ã“ºÈ’¶Ã‹·Ä«´Œjn[HF>IA:viY r¨”q°•{¬•u©–s©–{¨~ª{´švÀ§uâÐsðÞyÙÄo¾žs³”}®˜uª™n­—t­’w®˜uª˜s¨—v¬–}­•y¶žp`r}‹Ÿª–¨¯jy{;HF(.-7e…r‡Ë¨†å¸}ë·ô»€öµïµà³h´”M‡oCkY7RB6I:*84&40'2/.744;8497/42,1/70-4<5-N?Aybr»›“á¼Û²ÉŸj™y;^C#6#02,/(+A>:mud‡˜wls^T\EQZ?enM†‘iœ©{›ªwž®yž¬|«{Ÿ­}¡®€ ­ž«Ÿ¬€¡®‚ª|¢°€¢®|ž­t¢³z—©zv…j9D:8<6j~r‹µ£ŽÑ´†ÜºÞ¹…彀ฆ㾆㾇⻆ẇ้⺋ä¼ç¿‘âÁãÁäÁ‘åÂ侉Ṉⷋ庄ළ⻆㼅߻†Ú·Ö¶•Óµ™Ñ´•̹”Æ´˜Ã´žÀ¶£ºµ¦¶µ©«–™dbhCBF310WVL“z­µ²¿‹¸Ç¶Å‹·Ã“™¡‚VVJGARXAŒ”u™¡ƒW]JOQKTVW459///HNIw‘”Ê­Œà¶†êº‡î»ƒæ´€Á¡Yu9`P&>6'62.<8,;3/@5+Q;8_IHr[Uj\Šs\ŠsQiFv^=JB6A9,7-)7,4D9CTI?SF1H:62'65'77'@?5GFB<>83:+3=&A@{€e¤°†ºÉ–µÂŠ¶ÄŽ´À–w}fQMHE97}p`£•x¯–|«–w©—r©™tª˜y©–{¨–y©•v¯’w¿¢vÖ½uÞÍvŸt¨˜t§’|¬–z®•{­˜xª—r§•pª•v¬•{®–zcdhHFL989:79SDAa[Pnv~m[cXPULVUKPM>>=9:9576212.3407;68<7;?:PU@[aJhnUs{]€ˆi‘›wž©ƒ£®†£°‚š§{Ÿ¬€ž«›¬€~n1@26BBm·™‰Óµ‹Ñ³„ħw¨’c‡wMbY?KE48959:7;<:?>>CB@ED?DB>CA=GA9C=4>8,91'6.+;03D9;LAB[GPoZeŒvu©‘æ†Ôµ‡Þ¼ƒá¾“ß½‘ܼŽÖ¸ŒÏ´Ë¶™Í»›È¸”¼°›¶²Ÿ´²y…‡EJK01-69*ajPŸª‰µ¿¹Ç‘·Ç’œ¨„a`VH@@^UH“Šo«–zª–w©–s©—rª˜s«˜uª—t¨•r¬™t±’}·˜wʵqÎÁrº«s¬˜y«•|«•y¬—w«—tª–s¬—w®˜|®—}ÊÞã¸ÄÈjqt,/3EHM;?:36:Sam‘¬ºnƒ‹475xyeÊÕ´Öܽ®´•u|aQWFCGB378+0.T]S†¥–˜Æ³˜Û¾‹×·u¹šL|d/H:2=5287>SKOyhi«ŽÒ«ƒÞ±…ä²é¸‹í¹ñ½‹ó¾…ñ¼‚ñ»„ó½‡ó¾ˆò½{õ¿ƒð¿ƒ×­l¥†IhS.<002,>;7ad[’ƒxluxi‚‰ntza[`KGM<8?204.150/4223123101//0,02,35/58/7:1@F/DH5TXEbiTny_QaJ0A4Ygel¦Ž[ŽzCjZ;8<6292/:20D83TECvbf§‘…ҷڵ޹߼ŽÝ¼‘Û½’×¼”Ó¹—Ó»—Ä´šÀ´—±«~‹‰INM#'";@7ryl²º’»É“¯Ä†«»ŒswdGBALC:…~e¦•t¨–wª–wª•vª•u®—w«–v©”tª›t¬—|©w³špÁ¬oįr¸¥z¨•z©”tª•u¬—w¬—x­˜y¬—x©•vÅïöÓô÷˜¬­SVZRJQBHC6;>AO[Š¥³g|„9=7••}Ñß¶åò¾ÞêºÖ༢“CEF'(2MQV•œ™†Ç±“ÚÀ‰Ï±_–{7XC,:/9>=HKPL’suąᲄ쵂ó·ò¸‚õ¼ð¼„ó½‚ò¼~ó¼}ô½~ó¼ñ»„ð»ˆò½~ñ²ö¹‚ñ¹†é¹…Ъg”yBUB47(#6%:I4RYDDD6USKLPJ6D8I_L¡°}¯¼Ž¥±‡Œ—vp{aajV`i\W_TPSJFI@BC023DHI¢ƒ²¿‹³Éˆ°Ä˜DA=A:1nhQ¡“o§–u¬—{®•{­”z°•{°•{¬“y¦–y¢™n¥™o±—y·”r¾¡n¿ªw«šy¬™t«–v«–w¬”xª•v«–v«˜wÈçðáøôÔîô»Øæ°ÐÕ©«³9AHcpx”£¬`lv6<;žŠáá½ßõºÕ羘žgab=47GLJz—ŽÀ´ˆÑ·ŽË·Z…v.G=-A47[CR•poÈœzé³}ì¶ðº„ó½„ó½„ó½ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼‚ñ¹‚óº€ò¼ƒò¾„ネçºmÁ—4‚Y2+:.16364>74@42?:7IJAcfWu]˜x˜~alX>J8HVDXfTM^Iyc£«¡©Š‹•qšr‹—m„gŠd~‘f‡”nŒ’s…‹tQXI04/605;-9&90=VLW{mm‹~·¢…ëˆÉ°Ð¶×µŽØ¶ŽØ¶ŽØ¶Ù·Ù·ŽÚ¸ŽÚ¸Ú¸Ú¸‘Ø·’Ö·‘Ôµ’Ò´‘Ñ´“дŒÊ²…¿§†»§‡³¢m‚IbX/D;)92;:6:MDOow¦„Þ»„áºæ¾‹á·Ù½“Õ¼–λ—ö•±«wˆ…IQQ245alX£±²ÅŽ´ÃŠ§¬…fgS8:4BGE˜†o«•y­”r°—w¬—{£’w¬˜y°˜tª•vª•v«–w«–w¬—x¬—x­˜y­˜y«–w«–w«–w«–w«–w«–w«–wÐñÿÝ÷÷ß÷÷àûÿËé꣨9BFlx~~‰‘Zaj8=;ª­—ãèÁÝñ¼½Ë©bf[@;=FCEzˆ„•»¯˜Ï¾˜Ø»l ˆ1YG7[Jd’||¿Ÿ„ᴂ﹂ñ»„ó½„ó½ƒò¼‚ñ»‚ñ»‚ñ»ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼„ó»†÷¾ƒõ¿€ò½컌ïÁ“ìÀÕ«Ro3H?01-:<6U[PZ`OTYDHN7GK8HK=5;:9?>7@=TXEot_„o‚ˆqˆŽuŠ‘v—|¤ª‘ ©ˆš¥…•ž„…r>E8)!+:68NI\†uz¨•ȳ’ÓºŽÕº‹×¸ŠÙ¸‹Ú¹‰Þ¸‰Þ¸‰Þ¸ˆß¹ˆß¹‰àºˆáºˆáºŠá»Šá»‹àºŒß¹‹ÝºŒÜ¹ŽÛ¹Ú¸‹×·ŽÖ¸Ó¶’ϵ“ɲ»¨pš‰Nue2J>)9.,7/?[Ne ‹~Ô²ആ淓ã¸Ý·“Ú¹•Ò¸—ij™¶­w†‚:BA>E8Š”v³Á‘ºÈ’³½“†‰s<=4>?=Šyd¨“x¯–t¯–v«–z£’w¬˜y°—u«–w«–w«–w«–w¬—x¬—x¬—x¬—x«–w«–w«–w«–w«–w«–w«–w‡¬ÆÍëöâüöß÷ïÁÝÝWcc;EECJM9?;?=Cw~ »²™Ë¹Ô»„ʦTpDw[q«ŽŽÛ¹†è¼ó¾~ö¼…ô¾…ô¾…ô¾„ó½ƒò¼‚ñ»ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒð¸ƒòº€ò¼‚ô¿‚ñ½…ð¿ŽñÃì¿zÞªVn2C8192P`OŽ¢…• v}ZikXWXHFH@4DF:DG8=@024FK6CJ;2:/'3'A\Ld•z½ ˆÓ³”àÀ”æÃ‰á½‚߸†ä»†æ½†æ½…绅绅组鼄鼄鼅꽃꽃꽃꽅꽄鼆辆潆潇弇㺊潌㽈ݷ‹Û¸Û»Ö¶‚Ȫz´›[n=H@12.5F=O~hr¿šˆå¸‰î·ƒç³ä´‡ãº‹Ö¶•Ͷ‹® Tlb895lp]¤¯‰­»‹¦³‡¡©‹VXL=:6tfT Œs°™y­–v«–z§”y«—x­—t«–w«–w«–w«–w¬—x¬—x¬—x¬—x«–w«–w«–w«–w«–w«–w«–w!Mv‡¯ÈàþùàûñÁÞâsXca378POS^Z_CD;©³•ÝïÀÎ×¶il\435ORZ—©ª›ÄµÐµßÀ…ܰtÈžx̢轎ñÃﻃô»ñµ„ó½„ó½„ó½ƒò¼ƒò¼„ó½„ó½…ô¾ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼†ó»‚ñ»~î¸ñ»‚ô¿‚ñ½î½‚í¼}ö²{Ú¨i…8I@/9-l|d´Å ÕÛ²ÆÐ¦¼Å§¯Š–Ÿ~˜z‰’w‚‹qy‚htydsybrx_diTBE6-/#X[KPU@##PQG4;4,$B_Psª‚ذƒì»‰ë¿…ç»å¶ç¸„í¼…î½„í¼ƒì¹ƒî½ƒî½ƒî½ƒî½‚ï¾‚ï¾‚ï¾‚ï¾€ï½€ï½€ï½î½€í½‚ì½‚ì½‚ì½‡í½ƒé¹ƒç·„ç¹„æ¸‚ã·…ä¸ˆç»Œã½Ó±iªFfU>D959.3SBr®–zÞ®„ï¾~î¾zì½å¼Þ½‘βpŸ‰DJI>A8_cJmxPxˆY“¢|qub=72ZQD”ƒn®™z¬•u«–w¨–y«—x­—t¬—x¬—x¬—x¬—x«–w«–w«–w«–w«–w«–w«–w«–w«–w«–w«–w =od‘²Ñô÷äÿüÐîó¨·³KTQMOO¦ ¥kdgBA7¯¼œØí¼Å̱SUI:9=dkt™¶³‘ȵ‹×·æ¿Šë¹„êº}ê¹îºð¸ˆö¼‚ó·‚ñ»‚ñ»‚ñ»ƒò¼„ó½„ó½„ó½„ó½ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼…ñ¼…ô¾„ô¾€ò¼ó½ó¾€ò½„öÁ‚õ¶…ô¾Ö°Z†u8B<>?5„ŠqÓàºâðºçõ¿áï¹âðºãó¾Ýì¹Ùç·×ä¶×âºØå¹Öã·ÆÐ¬u{b#(t{`q{W?@<#-'0L?k¤‹‰á¹‚ñ»zò·€îºí¹„ð»‡ó¾‰ó¾†ð»ƒïº„ð»†ï¼†ï¼†ï¼„ð¼„ð¼…ñ½ƒñ½ƒñ½‚ñ»‚ñ»‚ð¼‚ð¼‚ð¼‚ð¼„トハò½‰ñ¼‡ïº„íº‡ð½‡ð½„íºê·€í½uë¸{î½~Ô¬g”yCRD.746DCPŠr~èŒäÀƒéÀ|庆æ½ã½{Å¡Ria,82AC7sx[™¨|𫀋’wD@5GA:„xfª•y­–v«–wª•yª–w­—t¬—x¬—x¬—x¬—x«–w«–w«–w«–w«–w«–w«–w«–w«–w«–w«–wBp¡ËèÝþÿÚöö¶Ó×u€}NUR   ÑËÐfacJKA¯ºšÛí¾ÆÏµNPD>=A‰š¾¸’Óº‰Ü¶ƒß´Œè¹†íº~ð»ô½…õ¿„ñ¹ð¸„ø½ƒò¼‚ñ»ƒò¼ƒò¼„ó½„ó½ƒò¼‚ñ»ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼‚ñ»„ó½†õ¿‚ò¼‚ò¼‚ô¾~ðº~ðº‚ó½‚콂Ӳ]s882??1ƒ–{ÏܰæóÅæõÂäô¿åõÀáñ¼ãò¿åóÃè÷Ääõ¼áò¹Ý꾂Šl$*ƒŒky†Z#";-_–}ˆà¸„ñÀ{ð·}ô·€ñ¸ƒòº†ó»„ﷃ봅ﺉó¾…ñ¼†ð»†ð»†ð»†ð»„ð»„ð»„ð»„ð»…ñ¼…ñ¼…ñ¼…ñ¼…ñ½…ñ½…ñ½…ñ½‡ïº‹ó¾ˆò½„î¹í¸í¸ƒïº„ó½}ó¾ô»õºzí´ç·h±‘6VK389/;5HdWm¤‹ßºïÁ…뻌îÀ‰æ¹n‡2KA150ggU„gn€Q†lRP>>;7tk]¢t­–v­–vª–wª–w­—t¬—x¬—x¬—x¬—x«–w«–w«–w«–w«–w«–w«–w«–w«–w«–w«–w0]~ÊíûÚôû²ÇÉeytMRQ~€€âáãÛÚÞfbgNOF¬´–âòÃÁͯFI:<;=Š–š–¿·Ò·Œâº‰ä·Šçº‹ï¿…î»}ë·‚ñ»…ô¾‚췄ó½ƒò¼ƒò¼ƒò¼„ó½„ó½ƒò¼‚ñ»ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼‡÷Áñ»‚ñ»€ï¹ðº‡ö¾„õ¼ƒô»ƒñ½€ðºö¿ì»~˦Pt^1?3=H@‹•wÈÓ³áîÈáðÄâòÂäòÂæôÄâïÁàî¾äô¾åõ¿ÎÙ±V[Fv|cy„\#'Dt\Õ«†ò¾|ñ¸~ﶆò½|ñ¸€ñ¸„ð»…ﺆð»‰õÀ†õ¿ð»„ð»‚ñ»‚ñ»‚ñ»ñ»ñ»ñ»†ò½†ò½†ò½„ó½„ò¾„ò¾„ò¾„ò¾…ñ½„ð¼ƒï»„ò¾†õ¿‚ñ»î¸ñ»…õ¿î¶€î´ƒù¾úÂ~ë»uÞZqD^Q(Q?5UXIYaC4')6J>q´”ôÁv챃÷¼‡ó¾‹ï¿€÷À~ðº‚ñ»‡ó¾…ñ½€îº€ò½ó¾‚ò¼‚ò¼€ò¼€ò¼ñ»}ò»}ò»}ò»ƒò¼‚ò¼‚ò¼‚ñ½‚ñ½€ò½€ñ¿€ñ¿‚ñ¿„óÁð¼€ï»€ò½€ò½ñ»‚ô¾‡ïºˆô¿ƒõ¿ñ»~ï¶…òº‰ò¹|櫉ѳmÀšpÒ¤î¶~ô¹ô»ƒò¾„êµYv/69C77~}a™§w§¶Š„Šk7;<`YP”ƒi®—w®—wª•v«–w¬—w¬—x¬—x¬—x¬—x«–w«–w«–w«–w«–w«–w«–w«–w«–w«–w«–w°ÆØŠ’’††€`d_GNQ>;=866ÊÌÍceeLPE«³•Ýê¾¶½¨AG<<>F<‘–ÏØ·ÝñÄØï»à÷ÁãõÀÕôÁà÷ÃáñÁËÖ°EO84B67G62<6p¥‘Ü·‡ð¿Šóº‚ó·ô·‚ò¸„ó»‚ñ¹‚ñ¹„ó»„ó»ƒòºƒòº„ó»ƒòº„ó»ƒó½ñ»~ðº€ò¼€ò½ð¼ò¸ñ·ñ·ƒó¹‡ô¼‡ô¼ˆó»†ñ¹€ðÁ€ðÀ€ðÀ€ò½‚ò¼‚óº‚óº‚ó¹Šñ·Œõ¼ˆóº„ñ¹…ó¿„ñÀñÁö¹„ôº‡ñ¼‚ï¾~ñ¿~ô¿…ô¼‰ð·‰ê¾k¹+P6>;-އn¨¸‚£½}–¥lEOBRPH‘†x¨–y­–v®’z«“{§”q«–w«–w«–w«–w«–w«–w«–w«–wª”q©–{£•¤”}«“u®”p­–v-Hc /86;::=;387?>@YYY–˜˜ÀÂÃeggDH=®¶˜Ýê¾·¿¨=D75=<„œš—ʼ‹×¸Šã»Žë¾†ë·Œí»ä¸ŠÐ«~¹šk›T€iRycRt\KfVGXM:H=/<..>-4F97JA5lQZ•y~Á¡Û¶Žè½ˆì¼‚ð¼…÷Á‡ó¾†ó»†ó»ˆõ½‰ô¼…ð¸†ñ¸‹ö½|ð»„ò¾…ñ¼†õ¿„öÁ€ï½‹íÁs̤Owk+H9;K9x…m¶Ä¨Æ×¶ÁÒ°±¿›‰™™›™–’€[UNGCB771=kTz˪ƒóÄ‚ô¾ïµð·‚ô¾„ò¾ƒó½‚ò¼‚ò¼„ô¾„ô¾ƒó½ñ»€ðº‰ñ¼ˆò½ˆñ¾…ñ½…ñ½†ñÀ‡òÁˆñÀˆó»‡òº„ð»ðº€ï¹€ï»‚ñ½‚ô¿ˆð»ˆó»ˆó»…òºƒòº‚óºô»ô»ö½€õ¼}ò¹}ò¹€óºò¹ƒòº‰ö¾ó·†ñ¸Šï»†ï¾ð¾~ò½ƒô»‰ô»õÆ€Õ©EpU?>4…~k£°„œ¯|’šqV`PPNF‚t§•x¬•u®’z¬”|¬™v«–w«–w«–w«–w«–w«–w«–w«–w¯™vª˜{¤“yª—|®—w®•s«–{5X/BWCMTRWV@A?59:&+*?AAnpqkkkDH=­´™ãðļ©=D5185v‹ˆ›Ï½‰Ù¶’辖弙߻q±ŽP„f536415/>G=>RE@cOPƒh_ €m·“|ͦxá°ì»…ó¿‚ò¼õºø»|ö¶|ö¶~ö¼õº‚ó¹ò¸{ó¸uð¸}õ¿|ï½Ò·U{3PA7?4HG=FA8KE:RJ=?A;;?44>.1;/>B=2*+F>>:;2S™q}ß±}ó¾‚óº‡òº†öÀôÂ€í¿„ò¾…ó¿…ó¿‚ð¼í¹€îºƒñ½†ôÀ}ñ¼}ñ¼}ñ¼}ñ¼}ð¾}ð¾|ï½|ï½í¸…ñ¼†ôÀ†õÁ€ô¿|ò¿yð½wð½ƒò´†õ·ˆö»†ó»ƒò¼„ñÀ„ñÁ‚ï¿ƒì¿ƒí¾ƒð¿…ó¿…ö½†÷½ö¹|ñ²ƒòº‡òº‹ð¼Šñ¾ƒñ½~ð»~ðºƒô»€ï»ˆæ·Zs6=6c]Ps|[\lCV[¦¬“áïÅÓÛ¼txl/,.?HE|´—‰ä·r¸”4I:DgL†§…¸Ö­ÁÛ«ÃÚ¤ÈÛ¤ÇÚ£ÉÙ£µÇ’‡’q9?.x€iÏݳÞñ¸Þð»äóÇàóÂÜì½áðÄçñÇÞæ¾ØÜ¹Îѱ¿À š—‰spbZXMJI?>?6=?9:>9<9072,/-*/.%,/'37)P;>cO`Šs„¾¢|Ï©~ë»wòºv÷º}ò»„õ¼{ð¹…îÃw°›096%$MohxÕ¨„ñÁ€óÁ„óÁó¾zöÀuô¼|ó¼†õÁ„ó¿ƒò¾…ôÀ†õÁ„ó¿ƒò¾ƒò¾€ô¿„ó¿…ð¿‰í½‹ï¿‹ñ‰ñÂ„î¿æ¹}ß³yجtÍ¥mÀ™a®ˆSœvHŽj]~iOkW9Q?,=0+3)/.*4,,5++1-,30,55/05,$3%'A/Rxbˆµ›‡àµð†÷Å|ó¼~óº‚óº‚ñ»„ó½‚÷¾„ó»wÅœB^JotY¤°€«¼ƒ§³ƒ†’tOME]TQ†zh¨™yª–w¬—x«•r«–w«–w«–w«–w«–w«–w«–w«–wª–w±šz¬•u©—znZP?ZP?ÅØÛáûÿÛûÿÕöùÜûúÛõõˆ›=GG459LFK=:5”šÒà·àèÉ¢£™>7>287gŸ‚€Ý°g§‰8?8o–i­Ñ¢Â⬿؞ÉÚ¡ÌÙ£ÐÖ¥ÐÕ¨ÁÉš„…k?<4ŒŠØÞ»çó¿èóÁçïÇêöÆåóÃçõÅçõÅáñÁáñÁãóÃßòÁÖè¿ÌÞ·Áѯ¦´˜‘š…w~oTYPIMG::4KVL?UIVJ>UMB\V[{v_“‚^–Y›~‡Ýµ‚ëºñ»‡ô¼ô»ñ¼…ô¾€ï»~ß·W‡u/-,-21^‰€}ݧ„ð»ð¼‰ïÀ‰ë¿‡îÁˆè¿–å¾x»œn±’j­Žq´•v¹šm°‘[žN‘rNˆkQ‡jQ~dLsZHoVFmW=iR4bKGcPB\J4J?Avl[¤—w¦•t­˜y«”t«–w«–w«–w«–w«–w«–w«–w«–wª•u®—w¨”u—‰si`SQI8Š‘„Îà¹Þó¼àô¿âðÇåñ¿æòÀäóÀâóÀâõÂßõÁÜó¿ÝôÀä÷¸äö»äô¿Üë¿×âÁ©´šbkWHO@?xWs¼–xШ~׬È¢[o0W=2TqÆš†ò¾~ó¼…ñ¼ˆë¹„ô¾ƒð¸„ó»~á³=mS01'(6*k¦‘tæ¦|õ¸ï¹€Ù­e«‡Bz]1S;?PEK\QN^ST]STULNHCLC?IE@A@<784244133222422724:57>7:?8;6=66>4>FE8-7*3@&ej…Ò¦‡ì¸…òº†ó»ˆò½ˆôÀ†óµ‰õºvÅž@]NbbVjoRS^>OT?_jIIH>LDEvk]£˜x¥”s®™z­–v«–w«–w«–w«–w«–w«–w«–w«–w­˜x¨“s§•x~r`E@7]WLŒwÜùýÜûþÜùýÙöúÁÜàJTT109>79†’~Óä¸äð¾çñÆåîÆåó½ãó¾ãôÁåõÅâôÅâòÃáñÂäòÂèôÀâò¼ãõÀâê²°˜YcS=dOf©Œuê³ðº‡õÁ„óÁyجO“pCtXBqW3}YZ‡m3F5t¤ˆƒî½tð´ð¸„ò¾}î‚ò¼ò¸Þ±@`O9-+.A2h»•xå­‘îÁy¼¡Oui/C>'5/1H9JjR[ªƒgµ–v‡P{`_ŽxGPFmœ·‹²»´½’³¼‘¯¸ª³ˆ¦¯„¡ª¦{‘šrnn`984KQ>kxR|Ša„l„‘kkk]]]OSTDVXEdhOszY{…[‚Ž^Œ˜h” n™¦rªv§³¤®ƒŠbW^;58(@@:nŒyæ´yö±xò¶ˆñ¾ñ½…ö¼„ï¾yĤ>`HaoSt„[„•b™¤l…nX\I>;3th\§‘x«’p¯š{©”~«–w«–w«–w«–w«–w«–w«–w«–w²—r§”y…|nNH=ZP?e«–wÚùüØ÷úÚùüßüÿÇäèm{z*-5?9>yupopl9>=bi\ÂΪàîÊØàÖƒ€‰+0.9WDt¬•?s\^g»Ç—ÍÙ©ÏÛ«Ë×§Ë×¥ÊÖ¤ÌØ¦ÌئÁÍ“ƒŒr8@9Œœ…Ðáµâñ¾åõÆÝïÀæöÁäóÀàï¼Þî¾âòÂåóÃâðÀäðÀâöÁåóÃãèÁ¨¬ScLHpWr¹˜‡å¼„ó»‰ñ¼Šñ¾ì»‚ì½~à²}׬xÏ£‰Ô´lš„1H9\s|ß±€õ¼‰øÀ„ð»ñƒó½‚ó¹zÙ¬Em[3/.(>2k¹š…×­U”t,XA1SBDn\_™€o¼—…Ù¯}æµ|ɧT{b5iKV‘u8P>œ~¿ÑœÇÔ ËØ¤ÍÚ¦Ê×£ÆÓŸÇÔ ÉÖ¢ËØ¤¹Ì›|ƒn=>:io^’œx–¡y‡‘g]„Žd‡h‘™tœ¤¥®†ª´‰«·‡«¸„©µ…¬¸†«·…£¯}”Ÿq…e{‚_v|]X[E><2KbS|Éö¹ƒø¿ˆôÀ…í¶{ó³…ð¿t¿Ÿ7XCiv^”¢€¦±‰©¯††n_dOA?5ocW¦’y®•s«–w¥‘x«–w«–w«–w«–w«–w«–w«–w«–w²˜t upgYPH;qeS r­˜y×öùØùüÛúýÝüÿÐíñ¦»¹e£…‰æ¹~ñ¸~ò·ˆó»}í½ƒòº†ö¼xתEs`&-*4IA^‰Ls];eLR…ixº—}Ó©„êº~ð»€õ¾wè¶Z•v4Q:J†g`¤…,P8“ª„ÃÔ•ÅØ¥ÅØ¥ÄפÃ֣Ũ¥ÇÚ§ÅØ¥ÁÔ¡¶Ê•x‚k,-)GK@fmR‰m˜¢tš©l¥µx¥´{¤±}œ¨vŽ™kˆ“e‰”fŠ•g~…dy€_szWowRkrOpwV„ŠkšŸ‚‚‡gOJ;5B4e¥ç²î¼…òÁ…õ»{÷µˆóÂq·™;[Hq~h–¡‘šy…‡ijtPTZC>=3i`S¢‘v­—sª–s¨•z«–w«–w«–w«–w«–w«–w«–w«–w®—w•…nZQCZQCŒ~kª—|¬—xÙøûÜýÿØùüÕô÷ÜûþÁÚÖP\`BEIº»·¶ºµ<@ANRG»Á¢çóÃèïàÍÉÕICN*52^q/P;¤„ÁΚÊ×£Ê×£ËØ¤ÍÛ¥ÊØ¢ÉסÈÖ ¶À–ajUKTG²¼žãìÁåí¾àï¼ßø¼ãóÄáñÂåóÃçóÁäï½åð¾èôÄçòÄÔ༙EXEFt]wʤ‰÷Àõ¾~í¹Ù®tÅža¢‚Sq`°{ç¹…÷ÁuÜ¢Dl`#B3a’|…Õ²ðÂ|ñºyò¸‰ò¹ñ¼„ó»ˆö¼‚ß²Q…n(4.GRO>`V;`LX”vzÓ¨÷‚ð¶„ò·ô»zñºqÇŸ=VB>UFt¶™a˜=S@¢·‘ÆØ›ÑØ¥ÓÚ§ÓÚ§ÏÖ£ËÒŸÍÔ¡ÐפÓÚ§½È–{53378438)ekRž¦}®º€¥´{˜¦p‹—e…b€Š_|…]~‡_z‚]‚‰f…h‰’j—l“žpœ¨x¤°€§³ƒ¥­…piV4:/[Žr„ൄíÀƒð¿€õ¸zû¸Ší¿h¥‹B^Jqbzˆ_mvNquR€ˆc_eNCD:c[N•†l¨•p«—t­˜|«–w«–w«–w«–w«–w«–w«–w«–w©”x…waRH7ndSŸx©”x«–wÜùýØ÷úÛúý×öùÚ÷ûÏèär~‚;>BŸ œº½»HKOGJA±¶™èôÀéðáÞÜèbYf'+,EZQ/E3š¨ŒÃÒ™ÊÙ ÉØŸËÚ ËÚ È×ÊÚÊÚ³µ˜SVFY`Q¨°’Þã¼ññÍëòÇè÷¾ßðÄâòÃéõÅæñ¿âì½ëöÈãñÇÈØ¯zNcMDx`tË¥ƒò¾xì±xÝ©mĘ`¤…KˆlK}eT…oN•zhͧê½fÖARI0M=w»œƒè»€ï½yô¼{ö¼Šóºô½…ô¼‰ô¼‡å¶a+?3HKIBIF\Ÿ€ƒÛ³ï¹~ø¸„ö¶‹ò¸ˆñ¾xæ¶_–}6;2Xykp¹ŸAcRVUK©¯–Ë×¥ÇÓŸÊÖ¢Ë×£ÌØ¤ÍÙ¥ÍÙ¥ÉÕ¡ÄМ®±Š{{m6;3Q„i‚Û³…îÄóÁø»wô¶‚ܱU‡o@X@{dŸi‘Ÿi¨²„™¢zflUDE;_YN‘ƒl­™v¬˜u£p«–w«–w«–w«–w«–w«–w«–w«–wŸxqcPUK:†xe©–{¨‘q¬—xÝöúßúþÙöúßüÿàûÿÚï졬°GFJ…„€ÀÁ¿Z]a=A;§®“åñ¿ßéÙëë÷˜›A??2LYI\kO…qÉɱæéÉæñ¿âñÅäñÃãï¿ãí¾êôÉàðÇ©¼›f|_BWAa‘u|Ñ«†÷ÅvïµjןqÊ™m¹_¥†a¤…_™|TŽqU•xy¿¡u²–CsY3>4>kQ}Ö«†øÃ}ó¾xðº{ò»‡ò¹ô½ƒòº…ð¸ˆíºzÉ¢=iR4B7?@<`¦‚–ïÃò¹tò±}ø¸…ô¼Ší¿{ر=fW7;6c—†`µ•,R<=>5LRAamIirXenTclRhqWqz`t}cktZ_hNRaB8M>2TIqŸŒIvc;.BL?ƒ„j¢¯{¬º„©¸­¼ƒ¯¾…¨¶€©¶‚ª¶„§¶}ª·ƒ©µ…ž¨~Š’mt{ZdkJ\bCKW3GD5)2(O†k|ݱƒïÁð¾ô·~óºzƤBdS?Q:Š›oª¼§¶}§µ…Ÿ§gmV?A;MG@{mZ¥’q¯›x¬—x«–w«–w«–w«–w«–w«–w«–w«–w“…r[Q@bXG•…n®™z«’p®™z¯ÃÈÝóøÚó÷Ùòö¿ØÜ¿ÍËÂÆËc]bzwÂÂÂehm6:4¡ªäïÁÝêÚëðùÏÇÑwsr;C<=G;ikXC?>@<;51041-;84DA=MJFJGB>=36A7}—…g†i9Q9]eZ¡¦‘ÙâºÞíÁæóÅäïÁæñÃáïÆ°Ã¢i‚h>ZFU™v‡Û±‡ð¿yí¸ð¾|â²…ã´šõÄñ„î¿ê¹€æ¶‡àµp¯.RA%=17WDa®‰~í·ƒ÷¼﹂ð¼‡ó¿…òº„öÀ‚ñ»~íµ‡÷ÁŠóÂn¼—AlW';/^s—⼇õÁvö»x÷º„ô¾‰í½vÔ«9`Q;B;h¥‹wÙ­_£€Izf2]H:_?DUJDUJ?PE8I>7H=?PEK\QTeZM|[P‹ocµ’‰éºpÄš=p\)80UOB“Ÿm«·…¨µ¥³}§´€š¦v—l€‰au{\hmPY\FPR?NO?SUB^`MfhTguYIJ@/@7X›{|å´òÀ…ó¿‚ô¸î¸f¦‰:MDW^O–£}¦³—¢tŒllsNMR=261<74l_OœŠmª•u«•y«–w«–w«–w«–w«–w«–w«–w«–w‚xgSI8ym[Œr¯˜x®•sª•yVin¾Ò×çýÿÆÜáXnsFQN‘‘—^W\€yvÎÌÌux}9=8¡ªÙæºåôæäëôñíòþ»Z^X.6,>=/IL6beOtwaw{bosZmqXx|c~ƒh9=7&90}£‘•æVye4F?>G:juT¡®‚ÏÚ¬çñÃÝ缩¸’WmPEaM{œŽ{æµðºƒð¸‰ôÈîÄ„êÁ†ñÀyê°‚ò¼ñ·ƒø¹|ô´á«a—t#8)U\Wjž†…ê½vñ³ƒò´‹ó¼ðÀŒï½ƒò¼ñ»‡öÀƒô»yôºpíµŠóÆÂ¥El\9`Jk±’zã¶õÀ…ﺎð¼‰ð½oâ°Gk[59-RŽlyä«…ì¹sÙ¶~Ó·ƒÉ¥vϤyÒ§wÐ¥lÅšb»e¾“s̡حŒØ¯ƒß¶xî¹tø²‚ò¸t·š8KBB81gpH˜¡y›¥{†fv~YekLcfPdfSdiNimTosZy~c†l•žv©yŸ¬xer\=B99QGr¼˜„ô¾}ñ¼‚ð¼…ó¸|ä¯SŠq7@=fg^ŠjnxNbhIW_NkqNX\I>A?@<;uhZ§”y¬—xª”x«–w«–w«–w«–w«–w«–w«–w«–wvm_PG9‹m u¯–t±—s¥t)9;W^¿ÜàÎâãp||SWRlnnMNRnntÌËÍ…†‚48,¤ª™ßì¾åïÑíìöîïùåèì’ŸCH9WSYnƒb˜©‡¶Ä ¹¿œ£ „}yahdQJJ8:,04LBpºœè»vÙ«c«‡ElV8L@GJ:yvg³¬›´±œPaF4FoTÞ±}õ¾„ó»‰ñ¼ƒò¾{Å©Bj^@H=}^”jƒ”a…˜e’¢lŸ©t|…dBI:=<2tkW¨–w©”t¬”xª•yª–w«–v¬—w­˜x¨”uª—|˜‡ma_Uf_N”‡mª•u¯—s«˜w“‡o9+@`޼×á”§®JMK˜ššmnrƒƒ‰×ÖØ…†‚6:/™ŸŽÝë»âíÍééïëë÷îñöÒÞÀˆzFEA61253210,24.451-0./11045=WGeœŽíÁ}ñ¼zì¶’î¿Õ°v¯Pt\1Q87T:v˜z€¯Ž‚É¡ˆçº„óÁðº€ï¹ï»‡ó¿‹ñÁ‹ê½‘ì¿™ïÅ‚ë¾óÃó½rðµ„ó¿u¸˜5RC3A=X«„„ã·…òÁó½ò¹…òº„ó½„ô¾†õ¿„ó½„ó½ƒò¼€ï¹…ô¾†õ¿|ëµy»žKz`/N9>bJc€wɦ~Ú±Šé½Õ³Hx[3O2]–pyÝ­~ùÁ}õºƒô¸ƒò¼ƒò¼ƒò¼ƒò¼„ó½„ó½ƒò¼ƒò¼òÀ…ô¾„ï·‚ó¹ô»†ì¼~Ä Q|a4<2`ePœ¤|«´‚ª¸‚§¶ƒ¨µ‡¬¶Œ¦²ˆ§´†§´€«¹ƒžªxŽ˜ny‚aHO45;6,I9y¾€é¸€óº†ñ¹†ð»}ïºu³•5VGAH9Š‹k¦°Ÿ°„¤²ˆ§°…˜žuu{dBFA=:6lbQ¢sª•u¯—yª•yª–w«–v¬—w­˜x¨”uª—|–…k\XMsiXŒr­˜xª“s™†ksa!> "B)C^~••³ÆGJHÇÉÉÒÓ×ãäèø÷ù‘’690ƒ‡{ÜêºâîÊêììííûêëõëöÜ´¾ OU>>66643.96";1C32`JW…oy¤|Èž‹ç¸ˆøÂyôº{õ¹ò¸‹ó¼ˆí¶ŒÚµc°‹L—qwƎ绌òÂ}ñ¼vò¼}ð·…õ¿ˆôÀ~à²h¾–R™xQo_–{{Ì¥‘溎õÂ{÷Á|î¿u¸›C\N;A0U’vzà¶}ò»„ñ¹†ñ¹†ò¾zç·\…j0F3^cNŸ¥‚©„”kr{ZdgGVY9EH9/12:57k_S¥’w­˜x¬”vª•yª–w«–v«–v­˜x¨”u©–{’gYQD‚tb¤‘v¬—x ‹pp]e\O"5 7!<2PJh…BDD¸ººïñòýÿÿ÷öøŸ ž682y}r×åµåòÌíòéðïÿèèöéñàÍÚ´”ŸwSXCHVDnŽ{€º…Ú®‡é³Žò¸’ñ¸ˆóºƒòº{ì³€ò¼…úÁzðµ{ô·~ù¹†î¿‰ñÂyã´|é¸~í¹~ó¼zñº{ôºƒö½ï¹í¹…踀ٮl¶’Gˆh/jK_0:)hlS‡ŽkfwLWg>ahEmnN‚‡`rwbNRMA=THc™‚~ä»ò¿†ò½€ñ¸…ö½†ñ¹‡ñ¼‚ð¼€ô¿‚ñ»…ô¾…ô¾‚ñ»ðº„ó½…ô¾ƒò¼‚óº„õ¼ƒó½ó¾}ñ¼{ð¹‚óº‚ò¸zÝ«ƒÍ£{»—^¥„Yœ|iž}_¤vÜ­ðº‚ñ»ƒò¼„ó½ƒò¼ƒò¼ƒò¼ƒò¼‚ñ½‚ñ»…ñ¼„ó½ò¹|ñ¸|ôº{ó¸‰ñ¼o¸0R:GO>ƒˆm§}©¸¬¼|µ½€´¹†£¥bgR-<.-M01.*cfPœ¦|¨µ‡§¶ƒªº„¨µ«´‚¬ºzž«dmX==/iaJª˜y¨“t«’x«–z©•v«–v«–v«–vª–w¦“xƒrXe\O}f±šz¥txk[RLEJE<ýþúÏËÊa\^&)1,6@245¹»¼ñóóýÿÿýýý¢¢¢888BAC´½œàîÄäôËðó÷ìêýëéõåïÑæôÄàóÀ´´–eYO8<1f’sä°ˆô¹ð·ƒó½Šï»–ò¿›÷ÂŽò¾÷ƒﻃ칂ñ»ƒò¼„ó½‚ñ»ƒò¼…òº…òº†ó»…òº†ó»†ò½wà¯fÉ›[·Œf¾–”çÁ‚ïÁ„ô¾wæ®Z³ˆIwd5QDh¥‰}캋ó¾„ó½ò¹…õ»…ð¸‰ó¾ƒñ½~ôÁðº„ó½…ô¾„ó½ƒò¼ƒò¼‚ñ»€ï¹}ò¹ô½|ñ½‡öÀ€ï·€ñ·ƒø»uø¿…÷Áƒïºzò»xó»ñ»|ëµ€÷Àƒò¼ƒò¼ƒò¼ƒò¼„ó½„ó½ƒò¼ƒò¼ƒòºƒò¼ƒò¼‚ð¼ƒñ½„ò¾‚ò¼ƒó½ñ»Ú­Jƒd.F46>3QTDiqSŒd}‚ccfL>D1"4#$I5PŽpÕ«‰î»}ﺆð»‡òºƒö½ˆñÀ…Ê©/L<(.)68,xƒ]¨¹€­¼ƒ§µ¨¶|©¶~­·ˆ­·‚”žzY`Q54*aWE¦”w©”u°—}«–z©•v«–vª•u«–vª–w¦“xnT\VK‹}f¯˜x£Žri_NGE;WQDýýÿÿýÿæßä^bc(44356¨ª«óõõøûùÿÿþ­­­-,.<;=œ¤†âðÆãõÆéíîèç÷îëûíöÜáîÂÒ÷¿Øà‰{u50-1U=pÀ•컀ôÅ€ò¼‰ô¼Œð¶÷º„ò·€ô¹€ðº‹ôÁ~ó¼‚ô¾„ô¾€ðº„ô¾ó½|ñº|ó¼ƒôº€ï·†ï¼ìÀ‡Ü¶Z¢„7u]VŽyzూê³dÍ”R¨~u¦’;WJg€ƒâ¯…ﺇö¾€óº‚ò¸…ð·ŽöÁ‚ñ½|ò¿†õ¿ƒò¼ðºƒò¼…ô¾…ô¾…ô¾…ô¾‘ñ»Œñ½†ò¾†õÃð¾‚ð¼‹÷ƒð¸…îÁŠòÀù€ò¼…ñ¼‘õÅŠì¾…ô¾„ó½ƒò¼ƒò¼„ó½„ó½„ó½ƒò¼†ó»„ó»ƒò¾ð¾ƒð¿‰òÁ‡ð¿‡ð½}ôÁ„꺈Ωl@HG62721-XK3XDEcpÉž}ë·z︇öÀŒð¼ò¾ùŠæ»Jqa40564*bvS›§u¦²‚§²„”uy€_eiPXZGPPBbiHkvV\dS:54p`Y§•x­šuª–w©”x¬—x­–v¬•u­–v«–w§”y‚qWGHF„vc«’pž‰mME8GD?ukZÿÿÿþþþüüüÿÿÿúúú¶¶¶ÓÓÓøøøÿÿÿÿÿÿÃÃÃ<<<...‰’wáîÈãñÈìñâïìûíéüíòéßîÈßñÂëùÉÊÚ±pve/)*O^V‚Ë£{ö¶‚ò¼ƒò¼‡ó¾‰ó¾‡ñ¼„ð»‚ò¼ó½‚ñ»ðºðºƒò¼„ó½…ô¾„ó½‚ñ»„î¹sÕ¡nÊ™„䵇ñÂᅦê¼}שtÏžxͧ\ ‡M}k9cLJƒb‡à´€ò½ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ó½…ñ¼‰ñ¼‹øÀ€õ¾õÀƒì¹‡å¶›»¢uwQaO>E656,74/762/0.=1/2,'1;/ImWo²’Žè½öÆí¹}ñ¶ô»‚ô¾„ó¿…ó¿‚ñ»€ñ¸€ö»ó¾„ì½xÉ¢€Ö¬‡õÁƒç·Š×±„Ôµ†Ó®‹Ù´Šã¸ƒë¼}óÀ}÷Áñ¼ƒì¹~ñ²ŠÿÅä¶RŠu/=934+u{d’œx’žn{…ZajBX_3DRGOeYUujUzpKujN_\FKI=85:807J;>nV[¤„{Ò°~ôÃ}óÀ~î¸î¶…ó¹‚óº|ñ¸{ò»}ï¹oÅ›3^C;kOlÒ¨vôÀð¾‚ï¿}÷»zí´ƒñ½…ô€óÁ{ñ¾}ìºøÅ{ø³„ìµv³™.<;2/+Y\BŠ”j˜o‡n‡ŽkŒ–k•¡ož¬v¢°z¦´~ª·ƒ©¸¡³~n|Z98*sfV§–u©–q¬—{©”x¬—x®—w¬•u­–v«–w§”y‰x^@=8~p]¦‘r~dNF9^[SlþþþþþþÿÿÿþþþýýýÿÿÿýýýÿÿÿÿÿÿúúúÓÓÓMMM111yj×å¼âòÂãìÑííóîéþííóèïàã÷Âßî»èòÃÃÓª\iS./+[{h}Û¬~ó¼}ò»ñ»ƒó½‚ñ»‚ñ»†õ¿„ó½„ó½…ô¾†õ¿…ô¾ðº‚ñ»„ó½„ó½~ö¿€ëºwÐ¥\©„a¯ŠƒÞ±ˆò½|ðµzô¸xÄ¢:UL1H@n±’‚ô¿uî´‡ó¾ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ñ»ŠûÂ|í´ò¹†óÂ}ϬHub(7/#G6?mW]™l¶œpÇ«qÒ²oÔ´kÓ²uϲl½¤Z˜‚Lqa•nªµ}¦²€ª¶„¨´„¦²‚§³§´€§µª¹­½€®ºˆnWcE53(tgY¥“tª—r§’vª•y«–w¯˜x¬•u­–v«–w¨•zŽ}cHE=xlZž‹p‡w`NF9icX”†pÿÿÿûûûþþþÿÿÿÿÿÿþþþÿÿÿþþþÿÿÿÿÿÿÝÝÝYYY...chYÊ×±ãôÁâîÊëííìèûíë÷íñëáóÄãñÁëôÁÙ컋€850@QDÇ£€ðº„ô¾ñ»‚ò¼‚ò¼ƒò¼†õ¿ƒïºƒò¼‚ñ»„ó½„ó½‚ñ»…ô¾„ó½~í·yð¹òÀ‰îÁ{Ô¬]®‡[´‰yà­ƒøÁƒï»r§Œ9@;Nh[zÊ¥|ñ¸|ò·ôÁƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼„ó½xï¸}øÀ„ñÀÉ¥Jo[0<679:\}q¨—o°›\¨Yª\°”cµ˜m½ sϬ}Þ¼xà¿rαn³ž]†wEVM6<7CD9AA=II4B@(<71B>6F?9D[LMtdh¡ŒzȰ†àÇۿi¬‘53?3@`Hc¥‚â´€öÁ{ò»ñ»x÷ºtç»Z“~-:2S‚l~à´‚óº†ô¹…øÆ€ï»ñ»ƒø¿xï¸ó¾ŒõÄrÏ¢ARG!*'@?5‘m¦·~¹~§¼…­´{«º€¬»¬»©¸~£°|“rz^ejMqwXyƒeZaR>98|le¤’u¦“nª–w«–z«–w°™y«”t­–v«–w¨•z™ˆnRJ=e[J”†syo^D[R8SI=[P>gX=taS—€o¸žv¿¥Xwn9LC"0%8VCg§‰„幆øÃ~ö¼ì³pâ³[„.?4LzcxÚ°‚ñ½‡ñ¼}ë»ð¼ö½|ô¹€õ¾îÂm¯’(UB/+&AJ6{Šd¦²‚§³ƒ¨·‹£°‚¯µ†¦²€Ÿª|šp}…`nvQnwO}‡\‹–h˜¢x”¡{blU<83{ma§•v«˜sª•y«–zª•v°™y«”t­–v«–w©–{žsbYKVL;udsj\F>1tjY¨•zÿÿÿÿÿÿüüüÿÿÿÿÿÿþþþÿÿÿÿÿÿýýýÿÿÿüüü©©©55563<£«”Þð»àðÀçïÞìëõðíüìíñêðåáèÃâø¾àõÄåçɧ¦’>G:364b»‰‹èµò¾„ð»…õ¿ñ»ƒò¼…ô¾‚ñ»‚ñ»†õ¿…ô¾ðº„ó½…ô¾|ëµrѤiÅ”{Þ¦„öº~÷½uÖªUj67.8CABcTbŸ}æ¶ð¸vô¹zñºò¿ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼yòµyÑ£Mw^-4-5.13564EASqfR“zY›‚k²˜yévǬr̯rϲhʬnɲk½§h§—W|r4F?'2/:IEMb_Wœc•‹Lb]'4,>ZG{¸–Œñ¾vò¶£õÀ€áµ_˜0:-Nu\wÓª…ð¿ïÀŠðÀ‹õÀò¶€ó´ˆí¹a¤„.F<5.3YXN• z™²v’ªt‹–p‹i†„aˆ`uxbpt[qwX~†aŒ–k•¡qŸ«y§³«¹ƒ–§tcqO@?1viY¡p¬™tª•y«–zª•v°™y«”t­–v«–w©–{ uwn`I?.h_QogZKC6uiW¦“xÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÿÿÿÿÿÿÿÿÿþþþùùùÇÇÇJJJ768‹”zØç´æöÁéñÓìììñïûìëûïðôàìÎä÷¾ßó¸ãôÁÃЪcgT0-/q•}ˆç»yñ·Šõ¼ƒò¼öÂñ½‡òºò¹ƒö½ƒô»ï¹ðº„ó½…ô¾ƒï»ƒé²jΞ\Å’€è³…Ï«Hh]=9Tt\|Ô¬|õ¼ðº|ò¿‚ñ½‰ô¼ƒó½€ðº…ô¾†õ¿yå±pÙ¦}ä±ôÁ‚ï·~ç¶wã¯~â®i©†:SIDYQDnUzÖ¥Œï½‰ò¿‚ñ½~ó¼~ðº†õ¿…ñ¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼„ó½‚ñ»ñ»‚ò¼ƒò¾†ôÀ‚îºyâ¯Q“v1J6>QBb”‚‚DzÜÂ}åÄ‚á¿|â¿}ãÀ~äÁ~äÁ}åÂ}åÂ}åÂ}åÂ~íÇwæÀväÀ|åÄáÆÙÀ|Ä­i¨”Osb6ZJ-MBAXPAVMBbQeš€Ç¦}Ϥo¦‹CRJ4211Q@h»”~í¹‚ñ¹|õ¸‰õÀ{ΨAw`8+.8+cjO¨‚§²€ª·¬¹¬º€«¹ª·©¶€©´‚¬¼¬¼«»~¬¼¬¼¬¼ªº}©¹|¬»‚Ž›uX`O=;0rgS¦”w®™z§’w«–w«–w«–w«–w«–w«–w«–w«–w˜ˆq]TFFA>VQNG>1scL¡‘tÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿÿÿÿïï˜435^dQÌØ®æôÄåîÍèìáëëñëëùðîúìóäâðÇãôÁáò¿åôȽŧEH9;VBxÇ ƒò¼Šõ½ðº}ð¾ƒò¾ˆó»„ó¿€îºƒï»‰ò¿{߯\¿aÁ’†äµƒô»‚ñ¿ƒòÀà®Xl+<3;VLI‰k}䱉ò¿ð¼~ð»~ó¼ñ»„ó½…ﺃò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼…ô¾ðº﹂ò¼ƒò¾†ôÀ‚îºwà­Yˆr8P>^ˆv{϶|âÆvåÅyçÅ…ãÁçÄ€æÃåÂåÂ|äÁ|äÁ}åÂ}åÂuâ¼sâ¼tæÁvçÅuåÃ{æÆãÇxÙ¾…Ѳi°–F‚p:eZ;UO4EA4G>AWK9[C8H=0),6135ZJoÉ¥~켎óÀ‚õ¼„Ü´Om.',-#`eJ”¡u©¾‡¬¹ƒ®»ƒ­»©¸{§¶yª¸~®»ƒ°½…«¹ƒª¸‚¨¶€¨¶€©·ª¸‚ª¸‚ª¸‚¬¸†‡‘sW]R?<4l`N¡r²}ª•y«–w«–w«–w«–w«–w«–w«–w«–w¥‘r{m[A=8IGFB<5k_MœŠmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿööö³³³<;=CH9·Áàí¿ãîÆèïÚëííííùíêùïóîßèÍàïÃáò¿Ýí½ÉÓ¯hoT3E4z¼™ò¿„ñ¹ƒò¼òÀñ¼†ñ¹„ò¾„ï¾}浄踆é¹dÁ”S®vÏ£‚ð¶|ï½}òÁzÝ­N€b,91Lm_„ѯ}ë·„ó¿ñ¼~ò½ö¿‚ò¼…ñ¼„ò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼„ó½ƒò¼‚ò¼„ô¾ð¼ƒñ½†ò¾èµi†v7J;b—ƒuÛ¿mâÁpæÃxèÆ†åÃçÄ€æÃåÂ~äÁ|äÁ}åÂ~æÃ~æÃƒåÁåÂçÄ|æÂuà¿xãÂ}åÆ{âÃxå¿~æÃ|ܾwɲz»«k ’R}nKrcOjZKRM8*.;65TjpÔª{ñ¾…à¸PŠr'925/(qjV¥©€ª¸‚¤¶{¨¶€ª¸‚ª¸‚©¶‚ª·ƒ«·…§³ƒŸª|•œy”›x’™v”q„‹hz^pwTjqNdnDT]C;?90+(_RB•ƒf«—t¨”u«–w«–w«–w«–w«–w«–w«–w«–w«•r€iNG>B@@@<;bYK˜‡lÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑÑÑ[Z\9=2›¢‡Öâ¸âïÃéóÕëïéëìöìéøïðôäêÙãðÊæ÷ÄáñÁÚæ¼›¥4>1u§‰Žì½~í·…ñ½„óÁ~ðº‡õ»…ñ½†ï¾zà°|à°ŽñÁ€Ý°g•yÔ§ˆï¶€ñ¿|õÃyß°U†j5B:BfV‚Õ®€ò½õÀ~ò½~ò½ó½ñ»„ó½‡ó¾ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼‚ñ»„ó½ƒó½…õ¿€ï»‚ð¼ˆôÀ~ç´l€t.?2`˜ƒzáÂyéÇwåÃwåÁãÀåÂåÂ~äÁ~äÁ}åÂ}åÂ}åÂ}å‚ãÁ~â¿|â¿{ãÀ{ãÀæÆæÆ€ãÃã¿}ä¿~æÃ|çÆêÉ|äÁtÖ²sÑ®ƒ¶¢GbX0/+9:0lž€pÙ¨|ô¾€é¸kŸ*H;06+pkVžŸw®µ‚¡«v–Ÿm‘m‰”f‚Œa|…]u}XjqNbiH_fETY96pcS Žq­™v­šy«–w«–w«–w«–w«–w«–w«–w«–w®—q Žqg^PDA=:87SMB”…kÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÞÞjik673†Šw×â¼äòÂäñËçîáíîøðîúíìöíïéãîÍãôÁãóÃäñŶ˜NOEf‹q‹ãµ‚ñ»†ò¾…òÁ~ðºŠø¾†ò¾ƒì¹zã°uÜ©ƒé¹ŒðÀ€ã³ƒæ¶Œóºî¾{í¾|ݱ^s>ME4ZHoÅ›|î¹~ð»~ð»€ï»€ðº‚ñ»„ó½…ô¾ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼‚ñ»„ó½ñ»„ô¾ð¼ƒñ½…ñ½qÚ§Uf]2C8o¨“}âÂ|äÁ~â¿}çÀåÅåÂåÂåÂåÂ|äÁ|äÁ|äÁ{ãÀväÀyçÃ{éÅ}éÅyåÁzäÀ|æÂ|æÂˆçÅ…ä‚äÀzå¾ræ»sé¾zíÁ|è½lª”>04?5@M=`œzvܬ~æ·\ª7EC)4*W`F™¡x¤±{›¥p–pŠŒh~…dovUhmPpuZx}by~a{€c‡hŒ–l™o“s—¡wš¤zœ¦|§}ž¨~™£x}†lLPJ<74yl\§•v¬˜u«—x«–w«–w«–w«–w«–w«–w«–w«–w­—s©•vˆzgTMD962E?8‡xeÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýáááihj+,*ehYÎØ´ãó¾àðÁæîÝîðøíìõêèôîîîáëÍáñÁáñÁçóÉÇÔ¨urjPlU~Σ„ô¾…ñ½„ñÀ~ó¼‡õ»‰ó¾ƒïº~êµoÛ¦uá­†ò¾‚ð¼ƒñ½ñ·„ñÁŠóÈ…×­ZhFSK7dQrÏ¢‚ð¼„ò¾…ó¿‡ó¿…ô¾…ô¾ñ»€ðºƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼‚ñ»„ó½ñ»ƒó½‚ñ½…ó¿ƒï»fÏœ>PI9OCw¸¢xãÂ~çÂ…çÃ~èÄvß¾€æÃåÂåÂåÂ|äÁ|äÁ|äÁ|äÁyçÃxæÂzæÂ|æÂ|æÂzçÁxå¿wä¾zåÄ}åÄãÀ‚éÄ}çÂy㾄äÀÖ´Koa3+6BWC3-.LO?Ššq¥ºƒ©º­·ˆ“™v„‰l]`P\_O\`MglW€‡l›¥¦²ˆ¥³ƒ¥³}§µ¨¶€©·©·©·ª¸‚«¹ƒŸ«{t~`AG<@=5…yg­›|ª•u¨”u«–w«–w«–w«–w«–w«–w«–w«–w«˜w«˜wŸŽtmbTGAaSf±•wέ8`N?,)A42rv]›°¡º~¦¶›£{fnO;G+VVPppjrthW[HT\=z‡Yž¯v§»zª¹€«º«ºª¹€©¸¨·~©¸ª¹€Ÿ¬xkvV:A4A>6ƒwe§•v©”t­˜|«–w«–w«–w«–w«–w«–w«–w«–w¦—wª—v©”x„ub[RIOIBWL>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýüüü¦¦¦0/19:6¬´ßîÂáñÁåðÐíñåéëýêîóíï÷èìíãðÊáö¸äóÀáéÄ­»’PQA`xnƒÕ²€óº†ó»…ñ½{ó½…õ»†ó»‚ò¿‚븆ï¼í¸‡ó¾wö¾†å¹a•}.F:2J@L€irˤ|í»ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼~ò½ƒò¼‚ï·„ñ¹‚óºƒò¼ŽòÂnÉœ>RFN_Rq¾£yçÅ}çÃyã¾åÂzæÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ|àÂzèÆ{çÃ}çÂsçÂkãÁ„Ô½Toe571:IE%A4O’mxѦb‡s90-,7-^bIœ£€ª¹€¨»v¥±mo\A@6beO©¡ƒÆÁ”ÈÄ‘¦¤|ijVJP=”Ÿw¥µu©¶‚©¶‚ª·ƒ©·¦´~©·«¹ƒ©·¨vagP9=7FG7‡~cª—|¨‘w¬—w«–w«–w«–w«–w«–w«–w«–w«–w©”x©”x§•x¢‘wƒv`YQ@QMBÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýý¼»½:9=01-ˆyÒáµâóÀáíÉæíØéêøêíõììøëëñäïÕãõÀäô¿áíÃÅÖ«kmZEUJx»›„ð»zí´ð¼…ôÀ}ï¹ó½€ò¼|ï¶y뵄ô¾†ôÀ„ò¾€Ý¸w²–G_M7L=g˜‚€Ô±‰òÁ„ó»ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼~ò½…ô¾‡òº‡ô¼„õ¼ƒò¼‰í½hÖ9MAHYLr¼¢{æÅ}çÃ|æÁ‚æÃ|æÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ|çÆåƒã¿ã¿yçÃxÞÂU}8B<1<4?MG3PA{ºšl°‘*D630(JRA—¢t­¹‰ª¹£´u“rUWCUWD¥¬‰ØÐ¹ÛÕ¬ÚØ¢ÉÈœ‚„nCI8|…d£°x¯¾„ª¹ª¹¬»ª¹©¸«º¬»‚Ÿ¨}_bR586=<.xoT§”y®—}¨“s«–w«–w«–w«–w«–w«–w«–w«–w¬˜y¬˜y«–z§”yŽ€inbPYRCÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ×ÖØXW[,-+`gRÅÓ©ãôÁàïÃæñÐçìïêì÷ëêúëêôéîååóÊãó¾ãðÂØëÀ¡¤‹FJ>_Œqá²wòºõÀzÝ«X®†nÏ£‚ô¿}øÀ|ô½‚í¼yÓ¨V£}BSFv½£{äÃzäÀ|éÃåÂ|æÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂuæÀƒã¿ŽåÀá¿~ÞÀc¦‘/J@342JaY;JB?aPz±˜Rwg#/)EJ;†‹l¤µu§·zª¹©¸–ŸwPR?cgNÄΣûóæãß¼ÕÕŸÉÊž…ˆr>B6qx]£®|§µ¨¶€¨µ¥±žªz›¦x”žs‰“hflI>?5*)+95*shM£Žr®˜|­™v«–w«–w«–w«–w«–w«–w«–w«–wª•uª•u«–v¯›|§–{˜Šsucÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿîí231JP?»Ç£áñÁáñÁæõÉçïåëë÷ëéýíêúííóèðÙáò¿ãóÃÜðÃÇÌ­miVKcKyÈŸyð½ƒõÀtΠDhWQˆm}ЪŽóÆ}ß³e³Ža‘wGcP8OAKiV`txÄêºzñº|ôº‚ó¹ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ñ¼„ó½‡òºð¸€óºƒó½†ï¾iÈ›5OB=NAy»¢~ãÃyá¾{èÂ}ãÀ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂxèÀ„çÁ‚äÀ€åÅxªA_R)0+?MI_w1C66]HCo^)1023/anV¬¯‚¬¿z¨¸{¨·~¢¯{—tIK8dfRÇϪüùëþüÝæç»Àžrrd8;2t{`žªv˜¡y–n|„_gnMX]@SX=MQ8DG1JO243/0,1MG<‹~d¨’v¨“t­šw«–w«–w«–w«–w«–w«–w«–w«–w­–v«”tª”q¬•u©•v¤“x‘ƒlÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþýÿ½¼¾;;;<@4«µ—ÝìÀâô¿âõ¾åðÜíìõîêýîêýîëûèîãàðÇâòÃßôÃÖß·£ž…MVAv¯éº…ð¿xÍ OaZ1I=Pras†T~e$D1.E63C8IwZy»˜è»„ó¿€õ¾ñ»ï»‹öŃò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ñ¼ƒò¼‡òº€ï·ò¹ó½‡ð¿oÑ£9WJ8I4GF<9;/7J;b‹vt¬•|צ‰ìºñ»wï¸wòº‚öÁ†ï¾‰ë½ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼€ò½ƒò¼ˆó»‚ñ¹ô»ô½…ð¿sÖ¨DeW3A5f¢Š„áÂçÄvçÁ~äÁåÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}ä¿{åÁƒëÌ]¨’*F9),#IaUR{:VI=gPp ˆ?WK84/qs]—§xœ£j™¥u¤®„ªµ‡§µ «}dgQ@?5KK=“†£¥‘urdEB:.1(MVA™¦z§´vª¸‚ ®xŸ¬x¥±¦²‚¥°‚¦°…¨²‡€‡l?>:724ofX¥–v®—w¬—x§–u«–w«–w«–w«–w«–w«–w«–w«–wª–w¬—w®—w¯™vª”q¨“s¬—{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüêêꋊŒ/0.\`U¼ÅªáñÂâõ¼äðÌèðßîíöîëûìêöíìõéïäÞðÇÝî»äöÁØá¹ƒpK[Jt¥…~Í¡H£v[ª‰d¤‡T}hA\L5UBN…jwÊ£ƒë¼€õ¼ò¹ñ»‡ùÃ~ò½‚ô¾ðº‡ïºƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼„ó¿…ñ¼‰ô¼ƒòº€õ¼~ó¼ƒð¿{Þ°Wzl1?3TŒu}×¹‚èÅtå¿~æÃåÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ~ãÃãńͷFi[#1&3JB73.-2/+DJ7q[£²°¼‚©¸~ª¹«º€©¸~¨·}­¼ƒ«º¡°wt|^;<3B=<~tb¦•t«’r®˜|©—x«–w«–w«–w«–w«–w«–w«–w«–w¦”w«–zª•u®—w¬–s¨“s¬˜yÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüö÷õÅÄÆ879:<6¤¬•Øæ¼ä÷¾âïÉèðÙíîòîëúëêóïîøëðîßðËç÷Ââ÷ÀØé¾¼¾«EI=OnQÆ›|ݱŠè¹Šä¹i¿j¾¡vѰ€æ¼|ñº{ù¸zò¸ƒøÁð¼ƒï»„íºˆõ½ñµ€ø¸ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼ƒò¼…ôÀ„ð»ˆó»ƒòºô»~ó¼†ó€æ·i2@4H~gvΰåÂqâ¼~æÃ~äÁ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ}åÂ{ãÄ‚ØÀU€q24.-2)Jqa…¾¥0`FCM@p°“Jh/<.lya—©z®·~ª¹€¬»¤°€žªz›ªp”¢l—ŸzˆrmsTITD:;7:57PNFt€b°©¹ƒ¬µ‚ª·ƒª·ƒ«¸„ª¸‚©·ª¸‚¨¶€¡¯ydmL:<0HD?ƒ{d­šw¬“s«•y§•x«–w«–w«–w«–w«–w«–w«–w«–w¦•z«™|©•v«–v¯˜x«–v«—xÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿýßàÞfff,,,BE<©²˜ÜêÁäô¿âîÊîòçîíöíêúëë÷ëîòêñîåëÌâóÀáö·Ü䵉vuˡƫ=XT2oU|«›CYT:;2~eŸ¯©»~¯¹w«º©¸¨·}©¸~«º€«º€¨·}¥µx—¡v†‘cŒ^“Ÿo§³ƒ«·…ª·ƒ«¸„«¹ƒ«ºª¹€¨·}¬»‚©·ª¶„ ¬|W_T55)UM<‘€mª’z­˜y«˜w©™u­—t¬—x©“z¨•zª˜y©–s©”t°˜z±•}­•w©•r§“z©“©–s©šlÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿþ÷øö¡¡¡324/1+v~gÍÙµåõÀßìÆçìÝëìðíêùëëùëíõèíîêð×ÞïÃá÷¼éõÁ¹º YcVJt[‚Ì¢wÑ­Lv]7W?d±Œñ¸ó¼õÂ…õ¿‚ñ»‚ñ»‡ó¾‰õÀˆõ½ƒòºƒòº€ö»‚õ¼‚ò¼ƒï»…ñ½ƒò¼ô»}õº„ó½„ó½„ó½†ò½†ò½†ò½†ò½ˆò½…ﺊò½ˆð»€ì·‚ò¼‚ò¼ƒò¼†õ¿tÀž8R@CQFq±žmÞ¼vçÁƒêÅ|äÃྃä„åÄåÄåÀäÁ€äÁ„èÅsá¿‚êdžçÅ„æÂ‚æÂzä¿uæÀpâ½` 6D@4((0J702&‚‡h¡°}¥´z²»‚¨·~«º¬»‚«º¨¶€§µ¨¶€ª¸‚¯¼ˆª·ƒ¨¶€«¹ƒ­¼ƒª¹€¨·}ª¹§¶}ª¹«»~§·zªº}ª¹ª¹€˜¦pNTI44(\TCš‡r¬•{¬—x©–u§—s­—t¬—x©”y¨–w«˜uª•y®‘ƒ³‘’³Ž’®–x«˜rª’~¨“~ª™r«™pÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÕÕÕIHJ+,(JP=¸Ã£åõÀáïÅäìÕíðîîí÷ëëùììøéíòïñåÞîÌÝö¾ä÷À×ݺ~…p4M9pžh¤Œ$G3HpW~Ô¬€õ¾‚ð¶Œóº€ò¼‡ó¾‚ñ»ƒò¼…ô¾ï¹~î¸ñ»ñ»„ò·ˆóº‡ï¸‰ð½ŠóÀˆñ¾…ïºõ¾„ó½„ó½„ó½„ó½†ò½†ò½†ò½†ò½…ð·‹ñº‰ñº…ô¼…ô¾ˆò½‚ñ»}ñ¼oÑ¥ErX9A7Z~rsѸiäÂoæÀƒéÆèÃ~çÂ|åÀ|åÀ~çÂ~åÀ|ã¾~åÀ|êÈäĀݾ|ß¿væÄ|ìÊ€áÁvÆ©GWP3-(9G;Q …sÙ¶bž€=]DPev±‹CgQ$/%=C2˜p«¹ƒ¦³{ «yžªzŸª|¨z™£x•Ÿu”žt˜¡y¦~¢®~¨´‚­¹‡«·…§´€§´€©¶‚«¸„ª¶†©µƒ¬¹…©·¨¶€¨µ«·…˜¤tDI@55)f\K x­–|¬”v¨•t§–u­—t¬–zª•yª—tª™r¬”~²‹›º†¶³ˆ£®–z«˜r«”~©•v¬–}¯’‰ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿýüýùìììvuw1207<-˜¡‡Úé¶áðÄäïÏíôçííóêêøììúìîøìììãðÚÙñÁÞó¼åïݵ˜OZFWiXNl_(E5m£†…ä¸|ó¼„ôºˆñ¸﵄ô¿…ô¾‚ò¼~ðº€ò½…÷ƒõÀƒó¹…òº†ò½„ó¿}ð¾…ôˆï¼ñ½ƒó½ƒó½„ó½„ó½„ó½†ò½†ò½†ò½‚ø½„ôºñ·‚÷¾﹈ð»ˆôÀ|ô¾yé¹f®Š7RB5H?n¥–{ÜÂxèÆvÞ»yæÀyæÀzçÁ}çÂ|æÁ{åÀ|æÁ~èÊæÃâÀêÉzìÎuãǃÙÁs£‘=OB41,:O@bªŒrß¹m½ Xq]@cHxѦu§‰*A2*/&bjS•¥u«º|©µ{›©y’›sˆ‘i{ƒ^ovShoNciJafI`eHemHiqLltOksNksNmuPowRnvQovSmuPy‚Z‚Œb…e‡‘g–n|„_@D>:8-ndS¢y«•y«“uª•v¬˜y«—t¬–z«—xªšpªšp°’‡¸„³Á{ØµŠ¥«•yª—t«–z©–s°Ž•·‡±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûúüÿÿÿÿÿüúúú±°´:::),#hn[ÈÕ©àïÃßìÆçðÛêììêêöììúìîùíìõéñæÛìÊßõÁêöÄ×Þ¹„†r;<2;B=9VFƒÈ§ê¹{ò»ˆùÀ‡ò¹ƒó¹‡òºŠöÁñ»ñ»õÀ‚ô¿ƒòÀ‚ï¾mòº}óÀŽôņå¸oÕ¦|켃÷Â}ñ¼ƒó½ƒó½ƒó½„ó½„ó½„ó½†ò½†ò½qò·†÷¾ƒð¸ö¿|ñºŠñ¾‰ò¿{ó½ôƒå¹[™{+E5>RFl›‹ŽáÈ~äÁçÄ~äÁ|â¿zâ¿{ãÀ}åÂ{åÁyã¿…å½éÂxãÂyÕ¼q° Ika,82593Osb}Ʀwæº|ݵQ{d?UC\˜y{á²Rvf$1)=<2„Œn¡³~®¾~«º}©¸…ª¶„¢®~˜¤t”Ÿq”žs•Ÿt”žt’œrŠ’m†Ži‚Še‚Še‚Še‰d€ˆc€ˆc‡‘g‹a†e‰”fŽ˜m‘›q‘šrwZ?C=@>4tjX¥‘x¬”v¬•u«–w¬—{«–vª•y«—xªšp«˜r²½ÁÄvé´ª–s©–s«–{ª•v´Š£½Íÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿýþúþþþâáå]\`()%=A5±»—áïÅàïÃäðÒéíçìí÷ììúéëõîìøìñðáëÔæõÉáñ¼åïĺ¾¥NMC:65ChT€Ö¬€ðºô½…ô¾‚ñ»†õ½‰ô¼‰ö¾ï¹ó¾‚ô¿컈ðÁŒïÁ|ìÂrÇ¡d™xLvW?yVrÇ›…òÁzò»ƒó½ƒó½ƒó½ƒó½„ó½„ó½„ó½„ó½uñ½‰ì¼~ت}è·~ò½‰ò¿„íº{ñ¼x빃õÀƒà³]”s3K97OCfšˆγ‚ãÃƒæÆƒèÈçÆzåÄzèÆyéÇsä€çÁÝ»`¨‘?cU081%-#7QCd—ƒuÖ®…ïÀ†÷År»•;U>a•~{Ò°{Äœ4GD)0)ZZH¤¢²}¨¹€©¶‚¦±ƒ©¹|©¹|¨¸{¨¸{¨¸{¨¸{¨¸{§·z«¸„¥²~¢¯{£°|£¯}¡­{¢®|¥±¥´{¦µ|¨·~¦µ|«¸„«·‡›¥zq{Q=>:B@6{o]§”y®—w°—w«–wª•yª”xª•y«˜wª™r«–wµŽ–ÀÆÅuæ°“©–p©˜q«“«“{²—¿Çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿúû÷ýýýø÷ûžœ¢;;;-/)„‹pÖä»áñÂãñÍéðãíðõêëõéíòìéøïîòìîâêñÎãï½é÷ÇÏÙ»ei];63Sj{߯ô»„ô¾€í¼ð¾ó¾†ñ¹„ó»‚ò¼„öÁ‚ñ¿‡ïÀì¿xÒ§\y?_L.A.3O8F|^Ó©ŒðÀ…ïºó½ƒó½ƒó½ƒó½ƒó½„ó½„ó½„ó½…èÀk­ŠVŒiuÇ|鸄ð¼…ïºøÁyð½‚ñ¹ô»Ý¬V›z.XF"E75bQHˆr_ ŠzÀ©ŠÔ¼ŽÜÄŽâÉ…ÞÄvÑ·e¤,[K3+(/*,7-=cMe¯‹‰ì¾wò¸†ñ¹zè´vÁ›A]Fa¤‰ƒá¿KqU*227>1v{\–šp€Š[}Žc‹˜r•›x¡­}¥±ª¶„¬¹…¬º„«º«º€¬»­¼‚«º€ª¹€«º«¹ƒª¸‚ª·ƒ¬¹…¥³}©·¬¹…©µƒ¦°…–žy~„eY^A675E@7sa©—z­–v¯–v¬”vª“y©”y©”yª—vª—t­’}¸šÀ„ÁÅxÚ­‡ª•v©–u«•|«–v¯“{º‡©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýûÿÿÿÿÿÿüÿÿÿúùýÐÎÔMLN./+SYBÁΨÝí½âñËæíÞêíñêìôìñôîîüðíöòïççìÍçóÃáñÁ®½=H872/c˜}|è´|ô¹„ó½ƒí¾‚òÂ}ð¾‡ô¼‚ñ¹ñ»ó¾€í¼Ší¿wѦ3‡]=H>:J?Steu¹ rÜ·zöÈxö¾ó½ó½ƒó½ƒó½ƒó½„ó½„ó½„ó½yŦ0U;$=#uµ‘‰ïÀ†ò¾„ð»|ôºwô‹ô»Šò³}ö¹zì½~Å«]{nM^SLPE9A6+7+-?2D]O]|mY}mBiY7;<946:36DRNgš†Ø²}ì¶~ó´„ö¶“ñ¸õÀqϦBeKStm¢5L6475YbM ¨¨«z‘—nm|\S`FWVA^bIdhOnsXy`‚‰hŠ’m™q”žt“ l”¡m” n•¡q–¢r—¢t• r“r”žtˆ‘iy\jqP\aFHJ7DC9?<7231E@7vb©—z«•r®•u¬”x«”z©“z©”yª—vª–w­¸ŒÂ…½Ã{ά“ª©‘}­™v­œk¬˜hµŒ‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿÿÿÿüüüÿÿÿñññœœœ///200 ¥ßîÂäôÄçòÑëîåìëôìéùíîøííûíêùçëæãôÉÞõ· ¬ˆ206-7+l¨‰‚îº|ò·„ó»ƒñ½‚ñ½ðºŒîÀ†ñ¸„ù´€÷³ƒí¸Ë­Qxi3A=AlQh¥ƒ‚Ø®ˆî¾…ñ¼ƒò¼…ö½|ñºƒò¼‚ñ»ƒò¼ðº€ï¹…ô¾„ó½}ì¶sŒˆ/3.->0i°„ð†ò¾‡òº|ô¹|ô¹‚õ¼‡ó¾‰ò¿‡ïÀè»zà¶pÖ­|ºœL|b'E2(6*8B6EWFHhPAlQ=rQK‰ed²‰xÖ§~ç¶‚ñ¿„óÁ‚ᅡフñ½|ï¾|¿¢B\Je˜}Isa754GK2•œy¨´‚¬¼¤´w¢®|ƒŠgW[BKN>LMDB@@FDD==7DE;@A8LKGGJAHKBHLAGK@FJ?EI=FJ>GK?GH>@A8CD:KQ>V`Bq|[wƒg?H3548ULB—„i®•s®˜u©”x«–{©’x±˜x«–vª”‚¦—w¦—p³‹¤À~о|î“x®–z¬—{ª—v¬–s¶ŒÇ€ÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýÿÿÿýýýþþþÿÿÿËËËQQQ200dgWËØ²Þî¿ãðÊéïÞððöðìÿëíõììøîëûèêëãðÐÚ︘£‚/.24>2s¯…ñ½~ô¹…ô¼„ò¾‚ñ½‚ñ»„íÀƒõ¿zñ´‹ö¾wÈ¡>oY)E8J]Te¸’~ß³…óÃ}ó¾}ò»ò¹ó½~ó¼ƒò¼„ó½†õ¿…ô¾ƒò¼„ó½ðºxç±P{n/!AcKϪñÁﻂï·{ð·ƒô»ð¸ƒòº…òº†ò½ŒöÁŠô¿‡ïº‚ïÁ|à¶sÈ¢m·•r¹˜~̧~Ö®tÓ§‹Þ·„Þ³„ç¹…ó¿‚ô¿}ñ¼}ð¾òÀ~ðº†×ªI“o:nV?iRXŒt2O@142pwV¤®„§´€©¸~®¼†˜¢x`dKQQC~„kns^PTAioXw`s~XclK]eG[`K[`K[aJ\bK]cL^dM_eN`fOjqP{b‰“o’žt™¨u¢²‚ƒkBK1435^TJ›ˆm¯–t­—t©”x«–{ª“y®™s«–p¬”|­–|¯“‚¸„³¿˺‡©ª•vª–s«—t°“…·Š¥ÀËÊvíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÿÿÿüüüÿÿÿôôôˆˆˆ1//56,Ÿ¨ÝëÁáðÄæðÒíïïëæûêíòêêöðìÿëéõæîÝÙéÀ™~/.0;E9z¶—†ò¾õº„ó»ƒñ½‚ñ½ƒò¼ƒóÃxò¼vðº‡ã¸c•}$=/+E7qœ‡wä´~ñ¿wòºxó¹…ø¿„ó»€ðº~ò½ƒò¼„ó½†õ¿…ô¾„ó½„ó½€ï¹xç±M•w+aDe¢~‰è»zð»ƒó½…ñ¼…÷ÁôÀ‚ï·‚õ¼{ó¸yñ¶~õ¸ôµ‚÷¸|÷½øÁó¾~ëºî½…ôÀ€õ¾}õ»ï¿‚ñ¿‚ñ½…õ¿„õ¼€ðº€ï»ƒò¾xܨL‚_@pVTŽr|¹Ÿ=jW(0&CKA’œq¬¸†ª¹€§¶}®ºˆ“šwSUBXVNÏѽ˜š†RV=wZŸ«y¥´{¥³}©y›§uš¦t™¥s™¥sš¦tš¦tš¦tš¦t™¥q¨´€«¸‚©¹|«»~­¹‡s{\>A1843jaT¢t­—t«–v©”xª•z­•y«•y«•r³‘‹»‹§½ƒ¹¾zͼ¾¶’Œª—v©—n­•y¹‰¥ÄyãËmÿÇpüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûÿÿÿÿÿÿýýýþþþÃÃÃA??,+'`fUÊÖ²áñÁçõÌéïäíêúëîòêìôñíÿíèýíïïÝèÎŽ•€01/>H<}¹š…ñ½~ô¹‚ñ¹ƒñ½‚ñ½„ó½„ð»wòºøÅy˨AaP->0Q€f~Ѫ‡ñ¼†õ¿~ñ¸ò¸Šõ¼‰ñº†ò¾ƒôƒò¼ƒò¼ƒò¼‚ñ»‚ñ»„ó½ƒò¼î¸ã·uÇœ‘湉õÀxð¹„öÀí¹ƒò¾‹ð¹ƒòºø¾sòº{ö¾ƒøÁ{í·ñ»„ï¶„ò¸€ï·ƒòº‡ø¿‚óº}î´…õ»~dó¿ƒïº†î·‹ò¹Œò»‰ñ¼ƒì¹q¹CkOh¨‹ŒÝ¼V”|,E;4/&syb£°|¦µ|©¸~©¸~¬¹… ©chMGI6‚{\YTCD4…Œi¬¹…¨·}­»…ª¶†«º}«º}«º}«º}ª¸~ª¸~«¹¬º€°º…¯¹„©·}ª¹{©·}¥¯…abR=8:950{n^©”x­—t«–v©”xª•y­•w¬–}®‘ƒ¼…´ÊyæËwçÄ|ϼƒ¶¶Žš«•ƒ«—t²‘¿ƒ¹ÈrôÇpü½~Îÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿýýýÿÿÿÿÿÿûûûÿÿÿìììxvv/--25,—¡ƒÝí½åõÆáêÕïðôíðõëîóïìüîèÿðïùàæÛ•†/0.AK?‚¾Ÿ„ð¼~ô¹‚ñ¹ƒñ½‚ñ½…ô¾Šñ´ô·ó½p½˜0L9:P>u·”}ﺂ굃ò¼‚õ¼„ôº†ï¶‰ï¸ˆôÀð¾‚ñ»ƒò¼‚ñ»ðº‚ñ»„ó½„ó½ƒò¼ó¾…í¸ó¼|ï¶wð¶…õ¿‚îºð¾Œóº„õ¼yñ»}òƇײ`ªˆ[¡‚vÛ¨†ð»†öÀ}ò»}ô½~ó¼€ðº†ôÀ„ô¾‡öÀƒð¸‰ò¹ö½Šõ½†ò½}ë·h¨ŠBjQƒÓ°xÏ«0XF-93UVF–›t¬º„©¸~­½€¬½~¦µ{¬¹…šlclDLIE75-KM:’™v«¸„¤´wª¹€«·‡©¶€«¸‚¬¸„¬¸„©µ¨³©´‚«¶„­·‚ª´¬¹¯¾¨µ}Ÿ§‚XXL80:B;2ˆzg«—x­—tª—v¨–y«•y®•u¬™v°ŽŽ½|ÈÉuëÈ~ÐÁ†²¾‚¾¾|Õ²‹¤®”ƒ²”{º‡¢ÀÄ»ƒ¸±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿýýýÿÿÿÿÿÿÿÿÿùùù·µµ746'(&\bOËÙ°ãóÄÜéÉêñâìîöìïóìëõíçþïìüàãá—š‘...EOC‡Ã¤…ñ½€ö»‚ñ¹„ò¾‚ñ½„ó½Žö·ƒò´‰ñ¼m±Ž)D42I:j©‰ˆðÁ‡ñ€ñ¿xð¹|õ»ƒô»ƒð¸ƒò¼~ð»‚ñ»„ó½ƒò¼‚ñ»„ó½ƒò¼‚ñ»‚ñ»ô½ƒòºƒó¹ƒ÷¼‚ö»„ó½‡ó¿…ôˆóºƒô»~ð»Œë¿Å¢HrY.N;Mo^tש‡í½ˆôÀ~î¸}﹂ñ½…ð¿‰ñÂxï¸ô½ô»ƒù¾}ò¹wìµ}ñ¼|í»x¼¥=iRu¹š>sX6=.;G5}kª±~§µª¹€¬»«º€£²xª¹¬º„˜¦pƒ‡jjnQy\¡«|«º}ª»x­¼~ª·ª¹{«º|¬»}¬»~¬º€«¸€ª·ª·¬¸„ª¶‚¬¸„ ¯v’ jˆ‘iJN;/-,RI<“…o«—x¬˜uª–w¨–y¬—x®•u«˜s®…´†£»ˆ­¹Ž—·Šš½}ÉÈsý»~ε˜°—o°”v²ƒ­”zª—qÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûÿÿÿÿÿÿÿÿÿûûûàÞÝ`]_,+-59-¨ˆÝëÁâòÉçõÓèéóíñòëìðîëûíêúâä壤 435DNBˆÄ¥ƒï»€ö»‚ñ¹„ò¾ð¼„ó½„ò¸ð¸’ðÁf ƒ&:.%,'>[Ll£ˆŠØ³’îÃ…òÂ~ò½†öÀƒòº‚ñ»…õ¿‚ñ»„ó½ƒò¼ƒò¼„ó½ƒò¼ðºƒò¼‚ò¼ðºð¸„ôº„ôº‚ï·ƒñ½„óÁ€íµó½‚ô¿‹ê½i¯‡.`@?qS·š†é»‰ð½†ð»ƒð¸†ó»‰ó¾‹ð½ðÂñ¼ö¿|ôº|õ»|ñºƒò¾‹óÄzܰM†qBfUKwf4B6A7%x…_¡´«¸‚«¸„«¸„¥²~¨µ­º†ª¶„ª¶„¦²€ª·¡«|§±ƒ®º†«º}ªºz¬»}©·}«»~©¹|§¶|¨·~ª¸‚¨µ£°|Ÿ«y—tƒŠir{Z]gC]hBZeE:@/340dZIžŽw©–u¬˜u§•v¨–y­˜y°•s­•y¬”v«“{­–|­•w°Š»~ÂÉvöÅuî¹…­®•u©™jª˜o©˜mª—qÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿþþþúúúÿÿÿýýýþþþÿÿÿýûú¢Ÿ¡435&("irXÎܳâôÅÞðÁääðíòñëííïíùîëûåæê¯°®<;??I=„À¡ë·~ô¹ð¸„ò¾ð¼„ó½zð»€ï½ׯ\w9DA816+))-80@gM†¿ž›íÈ뻆ð»Šô¿„ñ¹ñ»‚ñ»„ó½‚ñ»ðº„ó½ƒò¼‚ñ»…ô¾„ð¼‡ó¾…òº„ï·‡òºˆó»ï»ƒò¾‡ó¾€÷Àtï·‚ð¼Ý¬o•uÓ¤zç¶zð»}ô½~ö»ö¹ö¹€ô¹€ðºð¼‰ð½…ñ½xè²w籄óĂԩDeEdO?XJ(A=:65tfO¡¬t¯¼~¢²}¡®z™¥sŒ˜h‡‘fŒ–k‹•k’œr ª€¦µw¬¹ƒ­·‰©³…¬¸„ª·¤±{—¢p|dty\kpUgkRehR^`LQS@GI6@B6=>5FG>PTHlra`eV372*+/rfT£”z©”t«—t§•v¦–y¯š{°•s°•z«˜s¨–y¦”}¨—v«“{¸…«ÅvãÍqø¼€½®†«—xª–}¨”{ª•vÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÕÖÔPQO///673£©˜ÛèÂåøÁäïÏêïæëêúìêÿìîøßåä°µ´>=F8=@:BD>HKB\b?ilRt{Z‡•e‘žp^gM/2)260ˆsW¨“w«—x¨”u¬—x©”u¬—wª•u«•|©—rª–s¬–z«˜sª—r³™»ÍÍoü¿½±’}«˜mª–w©•|¨—vÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøù÷“”’)))01/ej[Öâ¾ßñ¼âïÉêïàëë÷ìëÿìîùåêëµ¹º>>D5C?m¢ŽmÅz䯃òº‚Ú¬\ŒpF[L7I85H96M?/E9/B96B<364422)11+0/')#>H8x•{¢à¸—ôÁ€ñ¸‰î»‹ôÁﻎõ€ҧE{XB\D{„pvw[€fRkuÊž‰ò¿‚ò¼„ð»‰ñ¼‚õ¼‹ó¾ˆð»ñ»ô½‹õÀ†ñ¹|ñ¸‚ò¼ñ»ƒó½ñ»‚ò¼†õ¿ƒò¼‡öÀƒò¾wÕ¬@oU/K7U˜yuɧf˜€5J;),0+1,NVE‚Œnœ§ž©{š¦v›¥v–Ÿw“œt˜s•p‡Žk~…du{\qwXqv[jnUdgQfhTikWgjTjoTuz]{†`Šd‚e„g‡’jˆ”jŒ˜n“ŸuŸ¨}¡¨…¢«ƒª·ƒ¢¯`hQ/1+571Žy]©”xª–w©•v¬—x©”u¬—w«–v«–{©—r«—t¬•{«—tª—r±Ž’¹ƒ¿ÌrûÀ¿³’ƒª—rª•z¨“}§•xÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿþÍÎÌGGG,-+48,­¸˜ßïÀäòÂèñ×èìíêêúééùíðøÄÇËOOU5C?f‹{W¡å¶~Ù¬i’s?F91>6=WJStfgŽi”…d’…f’…f‘„dŒ€`†Fkc,=9,(#90&lf£ç¾…ñ¼…ﺃøÁtôÂͧChNZ]N¹¬¤ÓÍȺ¸®v‚prœ}‘ݳˆíºƒò¼ˆõ½€õ¾‡ñ¼Šò½‚ò¼ƒò¾Œñ¾ôÁ~ò½ƒó½ƒó½†öÀƒó½‚ñ»…ô¾„ó½ƒò¼Š÷¿}Õ­?_L-3(Ij[V†t2J>$'%39(V^GŠ“r¦³…©¸©¸{­¼~­½}©¹|ª¹ª¹©¸©¸©·§´€¥²~¦µ{¥´{Ÿ­wªv ­yž«wž¬v§¶}¨¶€­»…­»…©¸©¸ª¹€ª¹«º€¨µ§³ƒ¨µ«º€›¨zSVF/.*AA;—‚fª•yª–w©•v­˜y©”u¬—w«–vª–w©—r«–v¬”~«–wª—r°‘ˆ¶Š©Çxç½…¶²’‡«•y«•|ª”{©”yÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýÿÿÿþðñŽ////2)mu^Õâ¼ãó½åñÍèîãëíõééùððþÆÅÎUVZ675L]ROŽtmǤM…h8B2HSKc‰ƒo¸¨~ͺ‚ÔÁ~×Ãw׿w׿}ÝÅwؾ~Ó¿}ͼ_›‘@4/0WVR…¯žd¢Œ7WFBXLiž”ƒÌÂ~×ÄÙÆsÒ½u×ÁwÜÃuÚÁxÝÃpÕ»{ÙÀqÕ¿yÖÇw¶­Snj.&5VAfŸ€„鱄ﶄõ»ƒô»Œí»y¸‘QgNUOCBCmbsò{ÚÅzØÀw׿y׿{Ö¿€ÚÂÙÅÖÂ~ÕÁ}ÔÀ†Ö¿|Ô½yÙÁwÔ¿xIJXƒx#-'=1/.WBc—ȧŒè¿…ïÀ‚ノôÃrب{È¢zÌ¢„Ⳅð¼}ò»~ó¼ï»‡ð½ƒòÀŠóÀðº€õ¾ŠðÀm¯Œ'N8]~oyᬌô¿Šô¿„ð»„ó½€ðºñ»€ò¼ôµzäµJk.2-;=1o{_€‰aq~PryVmtSovUrxYtz[y‚a~‡fzƒb|‚c|‚c|‚c}ƒd~…d†e‚‰h…ŒkŒ•m•Ÿu– u–¡s™¤v“sˆk†jPPJFF@;<389067.34*:;1IJ@ry^š¤z¤³y¬º„ijV9.8>66uwY«–z©”xª–wª–wª•v¬—x¬—w©”t«•|ª—v«˜s«–v¬•{¬•{­—t¬—q¬˜u«˜sª—tª—vª—r°’¸‡§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýÿÿÿÿþÿýýýýúøþš˜ž23159.¢¨‰Ü齿øÃáðÊçïäàßé‹–435e^eœ¨ªXTYOLNu§н|θ‚ÝÄ{ÜÂ{ÙÀ~ÙÂ}×À}ÖÂØÄØÅ€ÚÇ}ØÁÛÂyÚÀ{ÞÄÛÂf¥•-C>:14>02830;C8>R?T}^yº“ƒà³}ð¿|ó¼}õ»õºð¶„ò¸‡ô¼ƒñ½‚ñ¿‚ナô¾|ô½…뻌ȩ7S@=NCbÊ•„ì·‰ó¾ƒïº…ô¾ƒó½ƒó½€ò¼…ô¶ç¸Q†r2609<,‹•q£¬y¢±w™¤vž©{¨z›©yŸ®{Ÿ¯y›¯tž³u¤²|¢°z¢°z¢°z¡°w ¯v£²y§¶}¦·x«»~¦µ{¨µ£­‚y€_RU?TUE?E4U[Jhn]syhylqwdTZG:@-<@-|…d›¨t­¸†^^N6*6B;8…†d«–z¨“w«—xª–w©”u¬—x¬—w¨“s«”~ª—vª—q«˜s¬•{­•}®—w¬˜o¬”~ª”{ª•zª–w«–v³Œ¿€ÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿþþþÿÿÿÛÛÛSSS...WXVÈÓ²äùºàô¹åîÔåä膂Ž317IHJxz{EDFЇ‰ºÏ̘ÕÇ|ÙÄrÛÀw׿zÚÂÙÂ…ÙÁ{ÜÁkÙ¼pÖ½…ÚÆ…ËÄn°¤s±£w¼¯‚ËÁ‡Æ¼=dT.A,flYlr_FL;:?025,564A@D`]fZ |wÄŸ‹ã»‰ì¾„テò¼…òº†ñ¸ƒ÷¼†ôº†ñ¹ð¼‚òÂ…á¸c™{ 8 dŠnç¸pöº}ô½켄ð€÷º|÷·yä³J‰o*60?70‹Žu¡±‚«»~­¸€®¸ƒª¶‚©µ­¸†ª¶„¦³­º†©¶‚©¶‚©·ª¸‚ª¸‚©¸©¸©¸§¹~¬¹¬·¤°~mzZFOBinYdg@‘]º·‹ÊÄŸÎÈ¥ÓϬÇÇŸ¹ºŽŒŽ`GD9#;1'E:Djdn‹[kdCA9 ªŒ¿É«›¤‰y‚gU]FBH77;/25,63+7:13?36K3:7BCA¯½“ª¹Ÿp•¥u˜¨x•¥u“£t’¡u”|Œ—v‚nx‡gn}^coSYbGW^CUTFb]NpiUrrZq}an}b[eNfhT850S`P†Ç ‡ô¼~ó¶ƒôºƒó½ŠóÀ„ôº…èº`¢…%9,*)CG4goP•šsŽ˜nŠ”j‰“iŠ”i‹aw€Xw~YszUadN^aKZ]GX\C\`GdhOmqXsx]ˆ™n¡¯y¤­zcDE5ŒuÎÍ¡æà«þùúÿÿñôøßêë×ÿûðÿýòèçÍÅÉ {}gUZ=œ¬}grR533?94ƒ|i‹|szrerlYXV>C>/@73?46:30<8-L@WPAb_CmlJ}wZo™‰}·xÂÃ|ÝÊzõÈqÿÃkÿÂpø¼Éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿÿÿþþþÿÿÿþþþÿÿÿãããdce%%%PTIºÅ¥Üì¼âóÀÕàÀˆ~+++4359=B ¦­åáìõí÷Ýëñ·áàÚÊz×ÂzÛÁ|ÕÁeœ“0A>*( RVCp†cƒ–k‹šg†‘c„’pu‚l=G:LUH¼ÇŸª¶Œš§{–¤t”£p—¦s–¤t«{™©s”§p“¥p“¤q–¦vš§yš¤y— u‡žr‹œpoŠ˜hŒ s”mO_@_lRFG>BE6pžŠî¾{ó¸|ô¹yð¹„ï¾pó´zò¼|Ó¯?fV#0(&/%@E6njXŸ­}ª¸ˆ¥´Ÿ«yš¦v— u—žy”šw’œr’œr’œr’œq“r•Ÿt–¡s—¢t™ª£±{§±|Ž‘qCE2ehN»¹ßاëçÎçèÁÛÞ°ÖÖ®ðëÒÿöâêäÇÆÄ›nrYZ`A’ vPXA3-2G?8ybo^U^QA„yc•oŒ„g‚yezoamaUeZLPIFHF7:C99I@6OH4fMQoJpvHŠtGŒyL‘‚S¢‰X®ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÿÿÿýýýÿÿÿýýýýýýÿÿÿ°¯±659))){nØæ½ãóÃÞì쵚984.00148~†ßÚãòêõçíô×íòŽ×Ï{ϽÙÁw¾­Cga+0.MN>o|\}“cˆœg‰ša†“_Œ”o}„iEK4ioXÏÚ´©´Œ™¦z•¢t—¥uœªz“¡q”¡s•ªs•©t–¨s“¤q’¢r˜¦v™¦x”¡s¦t‘§s–¨s k“¢v‰”sPXAchYajV>?/Vr[†Õ®ó¾zó¹}ï¹óÃö½}뻂ҳ^…v5D@'204,6TNC~vXN=0<,&ueXž‘w¤–r¤•n§“p¨Žv¨‰z”„wl…{c‚wau]q[ƒkeˆirzS‡lHvV.5A.C@0Bÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûÿÿÿýýýýýýýýýüüüþþþééépnt-+1;=7¤­’ÝëÁâðÆÆÓ­WWQ*.)-21ZV[ÐÈÒîíöîñùèîõÂéëšÚ΂й]”ƒ(<744.jnU~cŒ—e‰—a…•_Š—iˆgciP`dK¡¦‹Øäº§´ˆ”¡s—¦s™¨u—¦s•£s™¦x•Ÿq™£u §z §z›¢u›¢w›¤y™¢w—¤x™§w˜§t™¨u™£x“tZ\I]\Rv‚dKP;BM=gš€äºó¾‰ð½„ూãb¤‡K{iGYR8>=+647B?451R]Cw…c–¥yªº…«»~¥´v¬»~®º~«¹ƒª¸‚©·¨¶€¨·~©¸ª¹€ª¹€¦¶­º‚­¹}©·†‘pOUDRR@ª¦‰ØÕ˜ÞÚŸÜØ£àÛ®èå¿æäÁÖ×°¢¤zTVB{‚gu€`9:13)5d]L“hzhWubU”€oª–}¬šu­šo³—y¸‘»‹£°’¬”~©—r¬o®Ÿn¯˜x·˜½ƒº»së©_ß‘Q»~Tƒt`[rdRn^Xÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ½»Á@=F)))^dQÎÚ¶àïÃØç»‰Š-4-),*;49º³ºãæîêð÷ïìõâíõ³âÚįP}m-85EB:v{\Œ™e™ŸpŽ™g†–g…—pfuZFQ=}ŠrÑßÃàî¾®¼Œ”¤o—§r™©t•¥p˜§t–¤t•§x“£t•¥v™¦x•¥u–¦v•¨w’§vŸ¥|™¤v‘¡l™«v•£sŠ”p_eLMP@x…_^dK<;-;XHkž|é¸ÛªLŸr=OB-E9$2,:88@;<,74/?87B:3399<:V\I˜wªµ‡¨µ­º‚¬·©·©¸ª¹€«º«º€ª¹ª¹©¸~ ±x¡¯u¦´t¨¹z­„mviAB8ŠuÏǘÜÖ§ÚÕ¨ÖÖ¨ÛÞ±Üà·ÇͪƒfTVCŒ’ydmR32.?5AqkX¡›r¢‘~©“o¬•u®—w­˜r¬–r«Ž…±„«¹Í³Ž–®’©•r«•y®Ž‰´…¦Áz×ÍsÿÌnÿÆu꾄ºµ–‡­šm§”q¦~ÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿùøúùùùŒ‹/0.02,ŠÝéÅãõÀºÇ§LTC*,,=:osVsx[5?.'B8D„n|̧Xˆp9:>79:,438QGZŒzg­–^®—d±œi¯ž`”‚Fjd2BA_aU•—s“™h†f}‡iz€asyZmtSlsRlsPnvQv~Y‡b‡“a’Ÿk˜§n¦µ|¡­{Ž˜nFL-sv`ÌÈ˜ÖØœÕÙžÛÚ´íêÎæçÇ»¿œ\`CkuG’žz?I<437H?6’…eª—r«”z¦™k¬’†©“z©”u®–z®”|³…¢¿Ñ·‡«±“€­™i±‡½€ÄÈvíÏr÷Ípñ½~Ú¶ˆ³®’‡ª—r«–w¬”|©–sÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÒÓÑTUS-.,CG;­·™ßîÂÛ蘣‰FLA578‹Š“ßàêììøéé÷øóüàêñÄÜâj1;5OQ=’œxÑå¶Ùé´£°„v~`GJ:<>2~ƒnÖá»âò½ãñÁÁÏŸ«{–¤t•£sš¨x–¤t—¥u—¥u—¥u—¥u—¥u—¥u—¥u—¥u—¥u—¤v™©t—§r˜¤z—£y”¡uiqS993agN}‚g8>+9LCBn]VŒo-K80/3#63Qrkv«‡Ï¹‡Ù€տÖ‚ÖćÚÁ}½±Y‚{:O@iwS›i“n™o“šw“›v•x˜ {— x– v™£y§}¦±ƒ¨´„©µƒ­¹‡ ª„‹jCF0|}mÄ¿˜ÔÒ©ãßÂöïà÷ôßÛß¼™€KIA‚‹`ƒŽn6>3102WMCŽn¬™tª“yª™r­•«–w­“{³‘‘µ”·†¬Â}ظ‰ª²“„­–v´ˆŸ¿vÜÈpùÌuïÌ{ܽ‚´·Šš²”{®˜n¬–s«”~ª•ÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿüüüùúøûüúžžž-,.)*&agTÍØ¸åôÈÕ⼆‘wGMBQRV¼»ÅäåïñôùíçòåëöÚìó…”—7=8HH6€‡fž¯„¦³…ybQTE55/ceY»Ã¥åòÄáñ»äòÂÖä´°¾Ž–¤t‘Ÿo™§w–¤t˜¦v—¥u—¥u—¥u—¥u—¥u—¥u—¥u—¥u–£u˜¨s—§r—£y–¢x›¨zt|^::4HQ=ƒjOQ=OXN\of;Q?0#=FIe˜ŠÂ²…ÚÄ{ÛÃxØÀ|×Â~ØÅ|ÚÉqÛ¾|ÕÂu±©8_PE[>Ÿpª·¬·«·…«·…«¸„©¶‚¨µ§µ«¹ƒ®¼†ª¶„¨µ§µ©¶‚ž©{y€]@C-Ž~ÌÍ¡üøàÿùòøôéâçÈ­¶ŽejOVWM˜ wjsX/7,643peW¥–u¬™t«•y«—t¯—{­—t±“‚¸‰ª¼„·½ƒ¹ÁxÚ¸‡­¯’ƒ¬˜o²“½ÍÅròËqúÎsøÐoûÎmýÉoðÁ}Ê¸Ž™¯˜x©˜qþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿÿÿÿúûùüýû×ÖØZX^+*,25,œ¢Ýí¾àðÁÊØ¯§NQOpox¢¡ªÐÔÕîçôíïúßèò¬µ¹NQO54&puZiu}^EI6:;2abX¯µžâíÅáï¿áð½àî¾çõÅÒà°³Á‘›©yš¨x–¤t–¤t—¥u—¥u—¥u—¥u—¥u—¥u—¥u—¥u—¤v•¥p–¥r•¢v”¡uœ©{€ˆiCD;8@5z}gUX?HLALPK38/6I@iŽŠƒÑº€ØÀuÚÁnÖ½qÕ¿ÙÆ…ØÉ€ÐÃ{Ó¼u½°}±ªXyr-A.v„`¤±}®º~¨¹z©º{©º{©º{©º{ª»|©º{¨¹z«º¬»ªº}«º€§´€z„Z?D'ˆ‹uËÒŸÿÿòÿýúíòÒÉÕ£w]LT6cž¥€RXA16-FC;‡|h©˜w©•r­—{¬–s­•w®•s°’»‚¹ÀzÕ¾ÄÀyк‚ñ“©™k­štµ˜½‚¿ÂwáÈpùÑnÿÐrÿÑtÿÎpÿÈmþÁwÝºŠ¦þýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿþýÿûûûÿÿþÿÿüùøúÄÁÊFDJ)*(MQFÂͧçõËÜë¿ÛæÅŸ¤•LNN+,0SUV°©¶ááíòôþÛßä“““MLBNP=bkQGJ:@C4nqb¶¼£Ûæ¾ãñÁãñÁæòÈâïÁéöÈãðÂÆÓ¥œ©{”¡s—¤v˜¥w—¥u—¥u—¥u—¥u—¥u—¥u—¥u—¥u™¦z”¤o–¥r—¤x”¡u˜¦v…ŽmLMC594ru_ouVCF6865,60Q|o|ƺx×¼}ÛÂ{ÛÃ{ÚÅ€ÜÉϾf¤˜K}s4\P1SINea[ih9@;ls^žª€¥´zª·ƒ§´€£°|£¯}§³ª¶„«·…©µƒ©µ…ª¶„©¶‚¨µ§²„‡ŽkMQ8bdQ·½šïîàüüìÏØ°“r[aHqzY£¸z•š{@C3571XTI—Šp¬˜uª”q­˜y«–p­”z®”v°•z»ƒ¶Ávà¾~Ƽ¹¼Ì±‰¢«”z«šs­—{¯‘†µŠ—ºˆ¨¹ŒŸº„³¿zÑÆrîÌoÿÏnÿÍmÿýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþþýÿþÿýüýùýýýõóùœ™¢768+-'hmXÈвàíÇÜêÁÝçÉ¡¦—JMK++143:1E@f£•v×ÃvÙ¿}ÛÃ}ÔÀÓÁ†ÑÁf¡“4VK!2)7<-EK:QVGQTK>=9FH<~‡f‰™d|ƒ`szWhoNdkJfmLioPjpQioPkqRlsRt|Wzƒ[‚‰fƒˆk`bOAA5mkaššŠ¥©vzaTWAafK—¢|¤³€„j78.:95kdU “s­™v¬•u«—x«™p¯”®–x±˜v¸Š§À|Ó¾‚¿¸Š¶Š§¯‘Œ«—x«–z«”~ª•v«—n®™l©”~ª˜s®˜u·Ž–Á~ÉÊsíÎqôýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþþýÿûûûûüøÿÿÿûùÿðîôvuw13-0.-|~rÕÝ¿äòÈßîÂèòÔÉÊÆ‡…‘=@D.15BCGPOSCDH=?@@BBsuu®´ØàÁãðÄâñ¾áð½èöÆåòÄáîÀâïÁàí¿äñÃ×䶨µ‡—¤v˜¥w•¢t—¥u—¥u—¥u—¥u—¥u—¥u—¥u—¥u—¤x–¦q™¨u˜¥y˜¥w•¤q†‘kMPA724YcEš§yˆ‡m9627PLo³¢{ÛÃ{ÙÁ}ØÃƒÙÇŠÕÇz²§BdY)5)KI>mqT€‡d|‡aluZLPD?B3‚Škš¦tš¤z”u‘šr‘™t—r‰mƒŠg€‡d€†g~…b‹a‰”fšo•xŠqdhOOO?RU;TW=YYGqtZ“Ÿoª·ƒ¨±‰dhO660C?>xe¤–r®˜t®—w©•v©—r¬•­™v­—s±Ž’º†¶¸†®´“„¬”|«™pªšo©—z©“ª•zª—r¬–s§•v¦’y¨‘{­’}²“„¹Ž›¾‚¾ýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþýüþüúÿýýýþÿûõöôÿþÿúøþßßßSUO.(3/-,‚ˆqÚç»ãõÀÝêÄíðçàÚë®´³…‰ŠŽ°¯³™™Ÿ”—œ´·¼ÕØÝàéÈèôÊãó¾äô¿áîÀåòÆàî¾æöÀåòÄßì¾Ùæ¸ÅÒ¤˜¥wŠ—i“ rš§y—¥u—¥u—¥u—¥u—¥u—¥u—¥u—¥u–£w—¦s—¦s”¡u˜¥w˜¨s‰”nMPA716EQ3žk’Žq=724MIt¸§~Ö¾ÚÆwÓÀØÈ‚ʾZ‡~'8/64)vi€‘f‚˜d|•]{dKX@?E2–u§²€ªº}§·z¨·}«ºª¹€¥³}¢°z£°|¡¬~ ¬zš©p¥¶w­¾¥´z­º†Ÿ«{“œq{‚]wz`v «y°Ãz¤µr§°…NQ;873MHG†r§—r¯—s®–x¨•t¦•t«•|«šs©•r­‚´Œžµ‰ ®•s«–wª˜s¨—v¨”{¨•z¨™rª—t«’~ª–w«–z¬–z«–v©–q©•r«•yþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýÿþÿÿýÿÿüþÿþÿÿüþÿþÿôñóÍÊÌDC?.+-0-/‡ŠzÖá¹äòÂåðÊîóÞìèûåâñãâìêìôéìñçèòîïýëëûêìæçîÙßìÆâòÃåòÄàíÁãñÁæöÁÞò½¿Ì¦|€mcd[^`TX`Iv‚d‹šz”¥y•¦z•¤x”¤u—¤v–£u˜£uœ¨x“¡w—§w”§p“©o’¦q’¦y‡–v\iQ882=@7Œf•hDB*/=9u®ŸtÒ¹†ÑÁ}ؾzÚ¼y¼­D[]422LR;w]ˆše„•b„’hx‚dEJ5W]D•¡w§¸¥¦~šžuˆ’h{‰`o|Vq}Yz`v{[mpZfkPkqRnsVsx]|‚cŒ–l¨µ¦³¥±§³ƒ¦³©¸©·¬¶Œ“t.6=52-k]J¤s®™}©”x¨“w¬—x«—t«–v«–w«•y«”z«”z«•y«•y¤’{«–€¯šz®›n¬™l®–x¬“©‘ª“}¬™t¬™s­”z­’}«–v«–wþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýþûýýúüüùûüùûýúüûøúÿüþÿþÿòïñ±¯¯:792009;/£«ŒÜè¾çòÌêòÔìîïîîôíë÷ííùîïùíîøëë÷ææöíîòíñæåïÑáðÄàñ¾âñ¾åóÃßì¾ÃÔ©q{]…ˆyÊÈÀÆÆ¸…‹t`gL~ˆjŸp”¤u–¦v–¦v˜©v–§t”¦q–¨s”¡u—¤v•¤q—§q–¦qš¨x–¢xv[<:9451grR—¡sYXD*44W†~~ɹƒØÉvÖ¾wؾr´¨8MO4/1]_K†™n‰œc‰™i„n`ePZ`I]`JRU8-sa¥’w¬—x¬—{§”y¬—x¯–t«”z«•y«–v¬™t«˜s«—tª•uª•v®—qµ‘‘ÁƒÅÉuóÊoÿÅuæ»·µ‹–¬—q«˜r«—xª–}©—x©—r«’~üùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûüùûþûýÿýÿûøúú÷ùüùûú÷ùüùûþúÿù÷÷÷õõ²¯±95;0..@C4£ªÙç½áíÉãìÒéíâíïðíìõïíùîí÷íðôììøíèýðìÿëìðçîßåðÐØæ¼«¹•gpV=?375-88,9=*GN9hq]ƒ’}‰—…‡–ˆ‰“Š—€‹™{”|–yŒ”y‹’|Œ’’ƒ–„˜‹y…s>F;@4{‚a•¡o^hDbe\†j™o‹—g˜j‡hŠ’m‰’j˜jŽ›g‘žj•¢nœªt¥´{«º©¸~£²xtvcafK½Á¤ùøÞõóÔÜÞ°ÙÚ¨ÎÌœ”˜tU[8bhIs{]xƒckvUksUgjTlpWovUs|T|ƒ`|fPOAID;WSHœ‰n£‘r«˜u«˜u©–sª•v¬—x¬—x¬›pª•y©—z©s©œp«‘¸…«Ã}ØÏqøÑmÿÐlÿÎmÿÍoüÑoÿÔoÿÕoýÆq÷ËnÿÄ{߶޶’ÂzÚÆvíûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúûøúú÷ùøõ÷ûøúú÷ùÿþÿóðò™–˜8571,5540ioVÉÔ¬Úæ¼ßçÈïñåñïïðíýêêöëíõíï÷íîøêì÷èêôèìñëïôæìçèîÛæîÐ×ãÇ—¤”|Љ}Ž—|‡›u‰DMJLSFdhU{€e˜¡y²¾Žµºš™„hlaQVWfoxƒ™|Œ“{‹‘Œ”kwyKPN?@6ouV˜¤tmwS\`UŒ—i§´€¨·}ª¹€©¶‚¬¸ˆª·ƒ¨·}¬¸†«·…©¶‚ª·ƒ¬º„¬º„©¸¤³z‡jW\A¢¡“ëæÝÿ÷êðëÒÞܳÔןÉÌŸk]_IONDsvf›¦€›©y™¤v–žyš¥w—¤p˜¢w{~dURDLF9eaO¡Žs¨“w¬™x«˜u©–u«–w«”z«“{¬’©–u¨–q©—r¬™s³Œ¿€ÆÌsøËoöÍqúËrøÈtòÇsïÊrôÎrùÐrùÌpýÎnÿÊsòÂ|ÏÄxÝÇoÿÅvëú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùùöøú÷ùþûýûøúñîðýúüëèê ŸFAJ+'-=;:ptaÐÙ¸ßêÂãìËéðÕíêùëè÷êêøììøêíòêíñëïôëí÷ìëÿéé÷ðíöòòòêîé·¾¹’ š~‹|„‘gonKT@‰p¸»”ÉÊž×Ú£ØÝ ÖÙ¨ÐÑ©®°“w|mdkh{†Šxˆ~—€Œ–uƒ[b_=@7\aF– uŠdPUF…d©¶‚¨·}¨¸{«¹ƒ©¶‚¦´~£²x– v“sšo™nšo›mšlšl†fVYC~|rËÆ½òëâöíããÞÅÙ򨧯¿ÖÕ¯¦§…baSMLB™u§¹~©¼}«·…®½ƒª»|¤°€nqWNJ?RK<yb§’vª•y«–zª–w«–v«–w«•y«”z­•}«‘€©‘{¬—q³“†½~ÃÉpõÑqþÍqÿÈpùÂuä¼Á·Š¤»‹¨Â|ÖÇmÿÓmÿÑmÿÐnÿÎmÿÌkÿÇoÿ½½ú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùú÷ùùöøüùû÷ôöüùû÷ôö÷ôöÿüþðíï¡¢?;A/+1873imZÆÏ®ßëÁãðÄèìæîïóñîýíìüéêôëîóðòúêì÷íëþêèûìèûìéùòñûâçèÌÙѪ¼¯‡Ž‰PZIv~_º¾šÕÓ°åܺæÝ¸ÜÒªÖÕ˜Ø×ŸÖ׫«®Žio^hsp{‰zŒ—{‰•z‡‰jpoDEAMO;–nŒ—qLS>lqT‘™tŒ˜hŠ–dšl‡‘f‡’dˆ”bˆk…h„Œg†Ži‡jˆkŠ“k–n‰pcgN_bI«¯’åæÌõñß÷ðáûôãÿëðåà¹ÈГ•šsDF3z‚c¢²}¨º}¨µ}ª»|¨»|šnWWED;7bVJšŽv©—r©•vª”{«“{¬—x¬™s®šq¬—q¬–r­—t±˜x·‰ ÀußËr÷ÏsúÏhÿÉpûÂ|׸‰ª±“ˆ«–vª’|²ˆŸº‚ÃÑo÷ÒpøÐoûÑmÿÌkÿÅt鹉£ùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøûøúüùûôñóùöøÿþÿýúü÷ôöøõ÷ìéë›™™;99.,,976kn_ÈбâïÃáìÌéðáëëñîêýíêúëëùîîúèèöëîóîí÷ïìüêæùêêøîò÷î÷ô×åÚ–š”MS@Ÿ¥†ÏÓ°ìêÈûòÑïã¿âÖ®áßŸÙØ›ØÖ ÄÅ™†iak_z‰Œxˆ•zŠ–|‹rzyLNNEE7~…b• zZaF]`J”s™¤v™¥sŸ«{›¥z¡¬~¤°~«·…ª¶„ª¶„«·…«·…©µƒª¶†¬¸ˆ¨¯Œˆ’hQ[1uzZ½Á¤òô×þýèÿúíÿ÷öáá³ÔÞœ®´‹FG7puXŸ«{¬º„©¶€­¼ƒ¤²‚hpRC@8F::}lc¥“|ª›mª—v«“}¬”~¬—w­šo­šm¬™l«“o±›r»‹§ÅrìÎmÿÑoÿÎrûÇzÖº‡¬´Œ—°”ƒ¬—wª—q©•r®…´œÏsêÏròÐsöÍr÷ËpûÈröÁ{Õùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøùöøûøúùöøú÷ùùöø÷ôöøõ÷øõ÷ùöøúøøëêæ£¢ž:882.30..jm^·¾£Úè¿èñÖçëåíìõðíýêç÷êéùêéùîðñííóîïùððüêêöéëóéîñÜáâš™Y[Uµ¹¦ÓؽóöÖòòÊÝÜ©ÖÕ˜ÚÖœÞÜ¢ÙÖŸÕÕ¥¥©†]dUtƒ}šyŠ—{Žs}}STX=>5flM•žvltUSX=‡jª·ƒª¹©¸~§µ¬º„¨·}§¹v§¹v©ºzª»{©ºz¨¹z©º{ª»|¨·~¡°wjtIKN8qqa¹¼¢ÙÞ¾çëÎãá¿ÚݯÀƇ‡wCC7y€]š§q«q¨´€ª´‰‡’rDI:830YMI–ƒt©‘y­o¬˜u¬”|¬”|­–v¬–s­”z¯“‚¶½~ÄÇtîÌsùÍrýÈw쾄»µ°˜t®•uª“s©˜m­šm³•„»†²ÂyÝÍnÿÏqþÏtùÌsùÍoÿÎlÿÌnÿøõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷ôñóùöøüùû÷ôö÷ôöú÷ùøõ÷÷ôö÷õõêè蚘˜857+))532ZYU«´™×àÅèïÚëñæïðôëéõíêúìëûðîúëêôæèðìîöêìôêëõééõÞÛꑎ—edhÍÐÎèìæðóêáãÏÖØ´ÓצÙÔ§ÛצÔÑžÑО©«‡U[Hw€ƒ~‹™v‰–}Ž‘uZZ`;:6PU:Œ•m{…aQS@qxWŸ«{©¸ª¹€¨µ«¸„§¶}ª¹«º€«ºª¹€©·©·ª·ƒª·ƒ§¶}¯»‰¥€rw\UWC^aKty^Ž“v„Œdu|[\^JJKA`ePŸ©~§³y¢®t£°z™¡|Y_N9;5?;6xn]¦“x®•s¬™t¬—x¬–z®—w­—t­‘€²‹š¹‡¯ÅvãËtôÌpýÉròÁ|Ì·Ž–®–x¨“w°…­“{­–v±“‚¸ˆ¥Ã|ÓÍsôÒpÿÅsôÂ|ÖÁÎÆuéÉnÿËmÿËoüøõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷øõ÷÷ôöýúüöóõöóõùöøøõ÷ùöøøõ÷øôùôðöüøþóðò®­©DC?/,./)4QUI§®™×áÃáêÐèíäííóñïûíêùíçÿïêÿììøíñöêîóîïùíêúÝØíœ›Z[_ÆÈÐììüèçûíêúòïñèæÜåâ¼Ú׫Û×§ÎÌœ™œuKQ>‰‰|‡•v‰˜’•y……ack@>=GK2ˆ‘i„gURMTVC|ƒ`Ž˜mŽ˜m†f…e†e‰mˆl„‹h|ƒbv|]tz[rwZpuXvW|ƒ`Š’m“rƒŒdknX\\PGG;KN?NTCbhUu~c• xª·ƒ¦°{µ¼‰§µ{”q8<0DECPNCˆk¨—p´œrª”xª”x«–v®™s­—t¯Ž‹¹…µÂ€ÙÌmÿÎmÿÌróÄ|È·‹‘­”t¦•t¥•~¬–s±¸…±¿{ÔÈröÑmÿÓoÿÓrò¸„¹±‘„°‘‚½}ÅÆoõÆqëÇuà÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôööóõ÷ôöøõ÷öóõòïñ¯¬®HEG-*,-,0EGAž¥ÖáÁáëÍêðßòñóîéøìîïíîòíìöëëùììúììúçéóâåí³²¼YXb¯­¹èæòíêùôñÿèåõíêúîîüçæðéåêÎÉÈkhdZ\\{„ˆ}‹‘{”Ž—€Š”hoxEKJ;B3rz\šrcdTOR7pe]—‰w¡‘t¬›tŸ“w«•y°»‰¡À˾væÆv÷ÂpñÀѹ‚»µŒ¡¬‘ƒª—t¬šu¥“v§”»šÉyÜÒkÿÔjÿÑnúÏoüÃxค´³šz©‘u¬”~¢ˆv\iZ;`^=v÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôö÷ôöôñóõòôùöøôñóöóõùöø¹¶¸VSU.-1'($>C4œ¥‹ÑÛ½ÝæÌãéØìðåîëúíêùîìøëìöéêôììøîîúêëùÉËÌ]^b€€†ÌËÔêéóëéõïìûíêùééõòñúèå禢¡WUTƒ„¶¾Å¸ÂÌ£¯µ”Ÿ§Œ•ŸzˆORV-2)]eN›£„w|gRX?aiJ†‘k›qœpq‘s—¢zŒ—q†l…Žmˆq‹”s‹”s‘›w’˜”™~”›x‘›q˜j‰”f‰“hŽ˜nŒ•m–¡s¡°}§¸ª»‚­º†¥±— ukl\::.2/*84361.LF;ngTƒk§”sº›ÇƒÄÊyÚÅxÙ¿~ÉÀ„º¾‚«´Œ—°ŒŒ²”ƒ®—w©–p¬™t¬—{«”~³™ÁÑËpÿÏnÿÍsõÅ{Û¸†®«‚©–q«˜w›qj]MB964+8xoŠöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõøõ÷øõ÷öóõùöøóðòùöøöóõÆÃÅYX\666')#59-‡ŽyÓÝ¿ÛæÅãðÊíìõìëôìëõëéõééõîîüîîúååñãå匎ŽVXYŠ‹ààæíìõîíöèçñëíõáá礡£TRRWTV¹¹¿åéôãëøêðõåçñèêõÔÔà—:=;TXL¹¿¬´·µlpkSXO…Œ£ª››¢“”…{‚urzckr]kpajncfi`dg^dg^lofqnwqpr{ttydpvW}„_‡_„Œdˆ’dŽ˜i˜¢s ª{ž¨}”qhmPFI3200+*,*,--/0/12(+)984gga‹}a¦„‹¾ˆ³»ƒ´³† ¬ˆ¬‘w²•v­—t«•q«•q¯št®™s¯™u¯™v§‘n§ˆ¯‰¥¹Â¾€Æ¼…¶¶Žš«“{¤–f©™u¦˜{‰~hGD6372Uac°ÃÈöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõöóõôñóüùûñîð÷ôöùöøìéëóðòøõ÷ÍÌÎdcg/.2*)+13-bhU¼Ç¦ßíÃßèÍèîÛìðëðïøðíüêéùêêøñòüêéóÓÒÛvu~MLU––œÖÖÜìíñØÙݹ¼Àˆ‰KJLTSU ž¤ãâìæçõéëýììòìëôôòþïìû¼ºÆQQW8;9•™“ÐÐÜŽ™_`j—™¡ÚÜäåçïßáéÒÔÜÑÑ×ÉÈÑÈÇÑÅÃÏÄÁÐÈÅÔÉÇÓÍÌÖÅÃÖ·µÁ©««”ˆx~g|d{€a|a„Ž`‚Œ^‰fˆjquXJN;48-150.5>AIP\gk`nmO[[7AA&-0).1;2CH9:=4/42BLL†•˜ÍßæÎððÓõôÞÿûÛûöÚõñßõóÂÑÓŠ–šLYI5=3///3485=<8@959-63%7--TJCnfU‚y^œ’p«žx¨—p«™p«˜m«“w­’}®–z¯˜x¬–z«–v©™jª—v›qSI841)FLKÒäãØóïôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóóðòñîðöóõöóõöóõöóõñîðôñóòîôöò÷öôôÞÜÛžœ›GDF2.3/*321-€…vÈÒ´ÝëÂÞìÂßìÌäìÛæêäìñèèìæêîéèêêàáåÆÆÌ³²»ÊÉÓáàêìí÷ëë÷ççóííùîìøìëõðì÷êìöíïùéëöììøìí÷ÓÒÜ{zƒ99?`^jÅÂÑ¿¼Ì‰†–™–¥ÄÃÍ××ÝÊËϽ¿¹¦¨¢’“y{u`cZW[OV\KW]J`fM^eJMW9YbGjt]fp_9B87>91<94=:,12169dmqª»¾ÓìîÚùúÖöõÜüûÛýý×øûÚùüäÿÿáúüÔëíÏà㞨²u~ˆ{ŠŒ“«¡´¦w‚87@.-6('+52-C>/leL›’p¥›s¨q¬•u«”zª•z¥–u¢–tž’v™Žp•Œfnyo^JD9.0*8@?‘£¢Ïçåôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñóôñó÷ôöôñóòïñõòôôñóòïñöóõ÷òûöóõóóíôöêðòæÂ¼b_a1,54+@,'0GK@…q¼Ê¡Õæ»ÝìÆÞìÊÝéËàëÑäíÙçíâåèæêêðîìøëèøîìøææôîîüìíûííùîí÷ìéòðîôçíøçëöéíøîðúéêôèç𥣩KIOJKI©©©ÑÐÒ²±³¡¡¡ÂľÏÓÇž£”XYU?@>444213.-/..../-01/8141,-422TSUilq]^l58Mab~{‡>GP/4=u|…Ë×Ýäùû×÷öÓûöãýýÙôøÙõüÛúÿÔõþÓõûÛûÿÙúýÕóþÖó÷ÓòïÓõïËññÓõûËá웩µNVU287244.*)D;7ymc‹|lŽl›ƒm”i†v_vhUfZNYMINACE7;B79=47738.16,6=/?F˜®´öñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóöñóõðòõðòùôööñóôïñóîðÐËÍ—’”QMR;8:-++32.BC:\^R‹Ž¸»«×å¼Üè¾àíÁÝëÂÖãÃÁ̼¹ÄÂÕÞçææöììúíë÷ìéòñíóòîóïëðñðôìêöïíùêèôííùêêöííù×Ù䈉—JJJvhzÓÍή½¢~‹uŽ|ohTB>,25%/0.++7'(<"):"*7!)6!(7#&B)/:$,9ir€ˆ–œDOWDQa•¦³ª´@LV[]eÅÎÒØòòÖýû×ûûÙõöÚ÷ûÚ÷ûÚ÷ûÛøüÜùýÜùýÚ÷ûÙöúÚùüØ÷úÝúþÜùýÝøüàûÿÚó÷ÜõùÍßà—ŸŸ=8580)52*IJH:9=>;D=858305010,1+)50/C/2N&)H_c uc+)F;=*BC3õðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòõðòùôöôïñöñóõðòñìî÷òôúõ÷ñìîÜÙÛ¡ž a__?=<55/23*78.?@6MS@|‚k¨¯”ÁʯÒÛÆºÄ¸›™Š”›™§­ª¸¾¼ÈÎÅÐØÌÖàÔÝëÕßñÑÚîÌÓÜÏÖßËÓÚÑÙàÐÙÝÐÛßÕáã»ÇÉO^PLJI†Œuž´ƒŠžsjlOC?-/--#+8%BS^ej p u]+*Q??Q…‘£”¨³DVWO[aŸ®¾’­·L[dZ]eÃÎÒÚôôÏöô×ûûàüýÛøüÛøüÛøüÜùýÛøüÛøüÜùýÞûÿÜûþÚùüÜùýÜùýØõùÙöúÚ÷ûÛøüÒõùÄÛÝFPP',*BKH†•—m}„hv‚Yp€Qe~8Gn'ci v€ˆ„„…}h+*J38;ôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñôïñõðòðëíóîð÷òôóîðïêìòíïöñóñïïíëëÛÙÙ±¯¯trq@>=-+*1/./.220/33-12(9=2HNIS[[\dk]h~lw‹vƒ“{ˆ–y‡“~Œ˜Žœ¨›§ƒ’„‘“€„‘“„”}‰|ˆŒ}‰Sd`/26>D1uˆ]}‹gEH.**$(+Gi s ‡‰‹’‡fG?^ ™¶ÄZurBPN‡˜—²¼ar{=ELœ¨¬Öðð×üúÖøøÙ÷øÜùýÜùýÜùýÝúþÛøüÙöúÚ÷ûÞûÿÞûÿÚ÷ûØõùÛúýÜûþÙúýÜýÿÙúýËóø¦ÀÆ4?C).1T`b¨»À¨¿Ç¨À̳ÈЯÂÑš¸fkœIH,&… {”•‘‡m26Yóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðòíïòíïòíïôïñ÷òôöñóóîðòíïóññòðððîîêçéÚ×Ùº¶»•‘–{w|]ZcGCH><<:950/+.00058*07 &1)/:+2;8@G@FKGLOY]^`bb[bkW]hSYdUXfbetnp‚uvŠ€•w}ŠWNc918DE8=rsw‡’–zŠ‘o€‰dhbSWRAB@>;=GBKMGXE?X94Qwˆ“’{./ióîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðöñóôïñïêìïêìðëíñìîôïñðëìóîïôïñôïñôîóõîõóìóðéðãããÔÒÑ¿»´±­¤¢¡Š‰‹]]c./9%*9%+> 5":)*>)*40-/0-((+0(+/,/3*,-(+)*.)*+',.(()';17E:<>:97122*+-,N mˆŽŽ‹ŒbALT‚žžŸÂÐw›GLOiŠ ©HTZCOS™­®ÓííÚøùÙõöÛøüØõùØõùÛøüÝúþÜùýÛøüÜùýÙöúÜùýáÿÿÖõøÛúýÖ÷úÕöùÝþÿÑãâ\dcA??=89ACC8DDN]_SbdWceajmƒ‹‹•œ‚ŠŠpy|`koHTZ5Ai lŒˆ z(&aóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðóîðòíïóîðõðòöñóóîðòíïõðòñìíóîðôïññìîïéîñëðôîóõîõîðêòòìõòíõòíõñðéæè¨¦¬MLVMXcff`VN F?!#A&)>&)7&,1)/.*1,)1&++%.2'%,%-,(73./.V ƒ…‰‹ˆ‰Œˆ‘ t$'MVen”²Å˜²ÃZfj;MX„“œq}ƒ?JNUdf´ÈÉà÷ùßøúÝúþÜùýÛøüÛøüÛøüÜùýÜùýÛøüÝüÿØ÷úÛúýÕòöÞûÿÝúþáüÿÙôøÀÖÑWfbBKH]kg—¬©©ÄÀºÓÏÅÜØ¢¶»cvyJ]`h{~•¨«¿ÕÛÆÝå§ÀÊ{ˆž)-g sІs'$Uñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìîñìî÷òôñìîïêìòíïòíïðëíïêìíèêñìîðëíðëíôïñ÷òôöñóñìîíèêïðîîìëñíìòìíñêíúôùÞÚà–“œ13QMk …ˆ„ € z s rnifb WMKG&(@0/+"$C yŒ“‰…‡‰ˆ‰…h44Xu†“ž¸Æ›©@NZWcm†—IRV$-0P]_¨»¾ÚñóÖó÷ÛøüÝúþÛøüÚ÷ûÛøüÛøüÙöúÚûþÕô÷Ø÷úàûÿâûÿÚðõã÷üºÍÒ\mj?MKn~}­ÅÅ×÷öÞÿÿÔððª¿ÀAGF=DAAHC?G@5B:O_X“§¢Íâß¹ÇÙguˆ+0g„ q !MðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíðëíïêìðëíóîðòíïîéëñìîôïñðëíóíòñëððëíðëíîéêíèéïëêóïîíêóîêððéðôìóñêïòìñïëñÙ×ÝŒƒ;:NY }–Œ‡‰”މŒŒŽŠ ˆx^*)3#&;n‡‹‹ŠŠŽ”ˆ‘ˆSCJSŽ¥­“·Ïˆ” 7AKcmt…Š>EH(14=LO€•—ÆãçÒïóÜùýÜùýÚ÷ûÛøüÛøüÚ÷ûÚýÿÚûþÛúýÙôø´ÊÏ‹ž£Ÿ¥LZ`GLOpv{¿ËÑÚðö×÷üÛûÿÓéïv‚ˆB8>C:=?78?:9?=<387?GG^jl¿ÕÛ™²¨Pcj"'r † | PñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïçÔ嘒‹/61 M {“ƒ‰‘˜‰}„‹”ƒ‡’ q G''70!@„‡‰‹Š‰Š„ u^KOg•œ•¯Ìl€…EVRmx€ƒ™JYU)10>;JWYY’š™ÆÕ×ÖððÖõöÝþÿØøýÖóü×úöÙõöÜëô¤«´W\]=CB@HH?JNit|©ÅÅÎñíÚùøãýÿÙöûÂÚÚUc_754?;:?:9@;:501:::@FEP[Y¿ØÔ¼ÐÑowm;1>$k€€ñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïñêïóèëØÑÔ}~‚27LT y‰†‹ˆ‡”ŠŠŽ _""@**0] wŒŒ†‰Ž‡ƒ‡‡ m"OCTQ{˜•ª«[pq2BNjv‚œ s€‚GT\?JN6BDJZY‚–—´ÉÊÒèæßóôäùûÚ÷ôµÊÌkv~AEJ9>=283;FD[fj]rz™µ¶ÕóîÚ÷ôÙöúßùÿ·ÊÍ9A@.32133/11022156EOO{‰ˆ¸ÊÉ»×Þ’«¯iwv4:AP|‚ðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðéîðëèòêñÎÆÐtwu.5>!$W yŠŽ‰†Ž‘‹ˆ‰Ž‹Œ~R .*'(2U |‹ˆ…‹’”‡Š•‰ i\@LX„—Ÿ¤¬Wjw?IZfo}š¨´¤¹Á‚•_ln>KI6BBEOOgnk–“žªªy‹Š@MO<@E<>?>?;BHCUaa ®´?]h-CH©»ºàùõÝûüÐé탒•?II/;;:FFUacvƒ…š¬­ºÏÑÑíîÙ÷ø¶Óâ[sG]i#;A(4)%fïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèíïèííêìéäæîæç¿¹´ll`48=V|”†ŠŒ‹‹‰“ k%?0-)$(3T {Ž‹ˆ‘’’ŽŒŠ……),YCQhƒ–ž¯¸iq‚;BSPYgfps†“wkrkEKJ36:976DEC-9;/775845860;O276QRHNVVBGPA=B[^bM]iEIJhimPOQ@CA0:4Ugf§ÁÏ“®È2Ru%1I:;E€ŽÌèèßýþÚö÷ÙõößöøÛôöÚ÷ûÚùüÞÿÿÓöúÖûÿÐõùx‡‰,;K.N5Z(5E@:572Rîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçìîçììéëðéðòèî÷ìîïäæÂºÁ………BH=#'WwŒˆ‡†‡ŒŽ‰‰ŒŒˆ qQ")2(6\ ‚‰”„ u t t y ~ vk"O)7$-A*5Q#1C%->72Q:@e<;D€‚|•£©cp~58@kqx€•¤ijnKLP?@D198CUT­¶–»×9`Œ Cu0U ':%04r†‡ÌåçÜøùÚùøÝöøÝùúàýÿÛúýÔõøÝûÿÚ÷üªÇÌ?FC-=,P &U#G-418=>íæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëóíîìäëìãíèáæèâçïèïÙÔÕ†ˆ|KPN0/V"u €… ŠŒ‹‹ŽŒˆ‹’ {X!%> "A] y„s Y L!F!%N*0[#)VODQi p ot ~#$`0-F‚ŠŠ·Ão‡™1;Bhqtˆ¡«[_d*.38?BTce˜³·¦ÌÞ:h‘:v 6v:j.F*2!*-APR•ª«ÔììáøúáúüÚö÷ÛùúÞùýåûÿ²ÅÊTbh+,0->1S"P"K'?*6íæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíæëíãéíæéïéîéåðìêðåãâçâäÛÑÞ‰ŠvAE?/3V!‰‘Šˆ—‰‡††‘–“~ Y(&:"$<]˜Ž{ ` @'&:/-J"G^o„‘•ˆ‡e++Ou‹•·Ç…¥¸EQU\ebm„†9?D1:>R]a°ÅÇÍïõi—¯ Bt6{3|8m;W)5A//5#*-$35P]_Š¢¢®ÆÆ³ÍÍÂÛݼÑÓ‘¢¥R\c+18.+:2F 7ZVn…މ„ŠŽŽŽŽ‹ˆ ~=@Us{t˜ªÁpˆ”:D>01/JURŠ¢ ÂÞßÔõþ£ÇÙR-;N4J0N7^ 7b2] .[ 3d;e2P7[c£ÁƱÆÈ§¼º½ÓѼØÙ®ÌÑêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèéæÞèãâêàæÐÊË……@BB+.=)+Ik x…‹ŒˆŒŠ‡‰ŒŒ  w"M"A"Db‚“‡ŒŽˆ‰Œ…h76J>96;;G5GHSkc•··¾ñôÕûÿÁçóEj„"F"I*L2L!6K/,B!(71CJI]^fuwgpyQZh=H\5E/H5Y6a:h3[0H1;Bƒ¬®±ÏÐVeg;GG›°®ÚööØúúêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèêãèëâåíåæëãäîäêÙÐÚž—ž]\X37+,/=$#Ut ‰Œ‘‹‰‰‰‰ˆ‰‹Œ ˆY*2#%= gˆŽ‡ŒˆˆŽˆzP=?GMID…ˆ£·¸±ÐÍÇðù©ßðªÔàfŽ¡>^D(P1P+>.7)59[ss™¼¸®ÖѵØÔÛ÷øÆáå³ÏÖ›«±M]d)@V 0Z 5d0R$19VZT¡ÅźÏÐAKK Œš™Ûóñ×öõéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçéâçæÙçíâìïåëçÝããÛâêãèþ»sqfGCB.-7!#A"Yl zˆ‘‘’‘ŽŽŽ’‚d'I'G_ ~’…Žˆ‹‘†s!5:?>784cnrÁÝÞÒøúÈñÿšÉß‚ª½B\A#J5W+B"1:3?A}£»ßÙÅäáxŒYeg¸ÅÇâúú×ùø¼ÏÒLW[.AV 7h6r4_'6FU__¶ÐÐÇÛÜamo6?Bª¬æûüàúúèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæìßïêÞêèáæëäçåàáèáäæßäÑÊω„†\X^55;.660:A&-Nc wƒ„†ˆŒŒ‹‰ {‰‡f!D#A] xˆ‹‡Œ“ „k18;SZWAKK:PU§ÍÏÏúýÊòþ¡ÅÕ¡¾!Bc"E,N-I 0A%15‡ÅÝÝáõöÏØÛ\[_0*/x{ÑæçÓúø¢±³:CL.B[>n7x 3n4T?PY­ÁÂÜñòºÑÓ¡¶¸ÍâäßöøÛ÷÷èáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèáæèÜèîæíäßáäßàëèêçáæäÜæìãíàààÀ½¿}‚KGL8885:84<;4>>&.V"UV_# h$!qr q w rokaN&A%(= |ˆŒˆ’ €c275…·ÅËµÑØÆòóÅõöŸÅÊYvYu˜#?bB &F1G/;;GIÂÉÄ×õúÙøûÁÛÛO_^'//JQTÄÕØÙôø’™”-)L$(A%>N`g "X(C%*IRk ’•… x'&:jm|ÍÝäÖöüÂðû™ËÝ.Tr $H+T)W"K*F1K,3LNXbÀàÕÖüÿÖ÷úÚïñŒ&22UdfÇÜÝÓïðz…‰*9B)C9f6t7v 6k5^:FJk{³ÍÓÕõúÓõûÞþÿËèíéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæéÞæåÚâëàèêàæêàæèÞäéßåíäçâÙÜź½kdgQPRGLMFNNKSSEJKtxy~’—q{{opnIJN2:K2Q7[8^7Z8T=X:g 3t 1y 5k7['5G"/E!'J V^`c_55CTVaÀÎÔÐîóÊøÿ•Å×)Pl@'L +Y&X+W5W)2MCMW·×ÒÕõúÛøüßöøÇÛÜm‚€¬ÁÂÝùúÁßàVae.:#= 5e:w6x 7m 2^&0-69IUcw‚‚˜£”œPcjèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåèÝåëÜäìÝåëÝãêÜâèÜâìàæëàãßÔת¥§?<>DCE\`aemm_iiwƒƒ¯½¼”£¦`llJVV);F5P 3]2c 6k$K)L3U7c4n5t8t:n5^5S1B&4@&->'*?25J27L+)//27‘ÇåæÑþÿšÉ×9a}"I&F.Z1h1l 8g-I2;D¡¾»ÙòößúþØôõÙõõÐììâþþÖôõ¡¾Â1;B'4!? 4e:y7x7q/c"8%8!5$6"*;(6#/çÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäëÞæåØàèÜâçÝãÞ×ÜÑËм·¹¨£¥€‚ƒACD/128<=BJJcoo¹ËÊš°®AHK7??AMO#9E4N5\'U!O DD"J(P)V-`2m 6u ;q=l9^6Y2V"3T*:Q &H2b5s:r/N+3:‹›”ÕîòØö÷ãÿÿÔöõÓõôÜøùÃÙÞL^e+5#5 )L 6k7v6w6t3k!C #A =9!8&:':çÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäçÜäèàçߨßâÞãÏÎÒ¢£§svzNST>FF6?B;#<%=&D*P,X%XO'T-Z.X2P';F{ŒˆZa\ivx¡º¾ÎððÓúøÌ÷ú³ßöR}¤ 8aA !@)S2f6`+<651“ª¬ßøúáýýÞøøÊáã„”š)2<&'5 !<B 7j:x4s:w8u:w:o1c'T$N$L)P0[åÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâåÚâãØàçßæËÅÊrquQTX†‰`nm“”ÌáâæþþàúúÞöö½ÑÒvƒ…9BE.0;3 >@@ %C6$8 (= #;-@05>rtt™¦¤“˜ºÙâÎó÷ËóîÉòôÃîÿ\‰® >q)V"G$K.Z 7f3U (9/8)11+55p„…ÔììÔóò×÷ö¯ËËXlm0<>9<@:]:` 6c 9q5x6z:w8k3e'RB?A B @"=C<":%:2.1@326MJE‰›š³ÍÔÇéöÌò÷ÙÿüÂêé•ÀÓGt™ C~8r -]'N)S4d9e*K.,2,*0-.2*.3&-#08$0$1"I7h8w3v7t9q8p7s6x9w;sDI9DHdpt¬¯ÊìëÕôõßôö¸ÃÁ]b`: #=&4,36BGH>FF:JI‹›šÑ忨ö÷ÏûúÇ÷øÌúûÉïó‹³ÖI{6r6p5o9w4j7_#=%:'9(9#5 4 = %G8t8t8t8t8t8t8t8t 9s9s9u:u:u:r] 7d "< > %C%;!*7.15jik‹ŒJVV:DDmz|ž¶¶»ÝÝÎõ÷×úýÏìð–¼ß%T‡8t8r5s7|7x/c *O$F=9<!D*R2`8t8t8t8t8t8t8t8t9r8t8t8t7s7s8tãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàãØàáÚáâ×ßæÙáèÙáèÛãߨßÝÝãÈÌÑdgkLQTt}€·ÆÈÚïñÛ÷øØ÷øÚüüØ÷ø¡»»DTSPXWENR1F>f4l2^$OGGI)V 7j :p9q8s6q8t :r6j0^"K@@ ">"3&.5KHJ°ª¯ËÃͶ»¼]abBEI:FHf{}ºÓÕÍãè·ÇÍ[s‰,Nr9f6d;p8{:|8q 8m0a)Y)V,\0c7m (8+16977š“–ÙÎÖȼÈJJJ3./=69MJLMRU;FJ'26>DK€‡€·ÃÇ‹š£DPZ(=S:g8q8q8u7s7s8t8t7s7t8v8t8t8t8t8t8t8t8t8t8t8t9v:u:u:ráÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞáÖÞÞÖÝâ×ßâÕÝßÒÚÞÖÝÚØÞ’–›_jn¾ÖÖÜôô·Ïσ››²ËÍßøúãüþ×óôÞôò¬ÀÁ=NW2K;d0f ={5r 1b /]%LA #A!?:= !E )R(V+^2h8m:o6i-L(=.3<1.0VQRÉÃÈÓÏÕüÃINM422814A@BFORp–§ª¯¾ÁÑçåÜöýÈÞ锤«C[o:i8w8y8t8t9u:s9r8q9r:s8t8t8t8t8t8t8t8t 9s8t8v9w;v;n9càÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝß×ÞàÕÝâÕÝçØàäÙáÖÏÖww}vz¤­°‚‹Ž>KM=OP¥º¼×ðòßýþÛúûÌÞÝ[lo0ET9\ 6k @2p;s:v :p 3b)O#E #A"@"@!?!@<D*U 4a:i 8i4H)5A968KAAˆ‹ÒÐÖÐÓØœ ¡DLKACCCAA;?@Q`b®ÈÈãÿÿÞ÷ùÙûûÏóûÔñö«º¼CVc3[6r8v7s7s8t8t8t8t6p7o8t8t8t8t8t8t8t8t 9o8t7x8z9r 7b4MàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝàÕÝÜÕÜáÖÞáÔÜçØàÞÑÙÕÍÔcagCFKF@E@my{ÎáäÛ÷ø×ùùËññ©º·GX[6H4_0m3v2n !:!<"D"G )T /]2?9BFG??‰{|ÜÒØÏÑÙàé튕“:EBEKJegg‡‡–«©ÆæåÒööÖúúÙý÷ÚþþÖí鈒†%114O@BCEOOš¬­ÓííØ÷öÚüûÛøüÓõûÊéòcpr1,-12@8_7u5p;w 6q 4r2u8{9t:l9s :p ;o8p6t6t 9q:k;z2v4z:x7&E#@ 5):%/9;=E~z€µ®µÌÅÊÚÓØËÇÌgjn?KKBRQNSTKSS>JJ5DFƒ˜™ÎèèàüüÚøùÛøüØøþÅâçLVV.*)25D5`;}7t7t 5j4e5i9u7s r9e7Y+C/+7àÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛàÓÛáÔÜÞÓÛäÙáàÑÙâÒÙÚÎÔÑÍÒ±¶¹COQrƒÊßàÛ÷÷ÜúûÙ÷øÛ÷ø¼Õד¡–O`i/Q2^ 3`.Z,[6l8q:w7u8p9g,O=!>=$C#:/,8!,4<>F‡‘ËÃÊÞÓÛÝÑ×ÞÔÚ¼Ácdh@JJdrqšª©²ÄøÌÍ·ÌÍÏççàúúÝöøÝùúÙøûàýÿ¨½¾275/+*,4E4b9:t8r:f2M3V6p5w7q7w7t8q7t6x6x7t8p >i9a5T ,A1@*/>**:ßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚÛÎÖàÑÙßÎ׿ØÞÚÐÖÅÄÈy|€AST¬ÀÁ×ïï×óóÛùú×õöáýþÉâ䋟’1GS)Q7g,W#F#G-Y )^/f4q8u6n)ZG D %E%@"4(/8$+./47†‚ˆØÊÕÙÌÔâÕÝÚÌÒáÕÛÜÕÚÌÍÑŽ––HVUAONVceq€‚¯°ÆÛÜãúüÜõ÷ÜøùÚ÷ûäýÿq}()%...-@ 5f4z7o8p=a+83H7o6~8{8o9q;s:v:y;s6b1R,F!,B%,;/5!03!(1&4ßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÒÚßÔÜäÕÝåÒÛâÑÚáÕÛÖÐÕ´µ¹UX\_stÁÖ׿þþáûûáýþÜøùàüý½ÙÚ_sg"8D7\7e$J=< AE 'T 6k:v3r/i -_)U0L"/E#&4*+/?B@†„„ÕËÑäÓÞäÕÝÝÎÖæÖÝÛÍÓÝÖÛÒÓ×ÐÚÚ˜¦¥uvzUZ]4;>-9=\or¾Õ×ÝùúÞûÿÜùýÑåæ@HG*+)(,1$; 1a7x3r2p8^+4+;K6c4q9n 8k ;o7s1r2s 8k4S+9&.5-*3/+1/8;(37#)0 *4ÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÞÑÙÕÍÔàÑÙâÏØãÒÛÙÒ×ÏÐÔ•˜CHK™«¬Òäå®ÂÃÃØÙàùûÛ÷øÞüý½ÛÜGVR"3@1Q $L@#> != !@<*L :f=u5u8t ;n5\!2E#,:0/8B=?{zËÆÇáÖÞàÐÛÞÏ×ÙÊÒâÒÙÜÎÔÁº¿‹ŒkwwGWVLMQORVZcgdpt…˜›ÍæèÝúþØ÷úÜøø›­¬+01*-1%/ :(T:s9{3o3W+4=TZa1B\ 5U(6M5a:g;p:v9w;l!6R&/9%.+0..2/117<-3:2/8+*3ÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÚÖÜÞÑÙáÎ×àÑÙ×ÓØÒ×ÚluxT[^¸ÄÆš§©0?Ak}~ÉÞàÜøùÚùú¶ØØHQU".:%<:><78"?,L3^4l6t:s9c4N,5=BKއŽÂ¸¾ÒËÐÜÖÛØÏÙÙÍÙßÐØæ×ߨÊд¨®]W\MPTR`_r„ƒ©¸º¸ÉÌÍàã×îðÙõöáþÿÙúýÙúýÓîëXhg).1$)2"3: G0];j8^"0FC?D…|^]g=>H-+++>!0C(:Q*B`&@d"9Y(6I26A/99ZV[qjoXY]GGMJBL+&/ÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÝÐØÕÓÙØÍÕàÍÖßÐØÖÕÙÏØÛQ]_gpsª³¶MVY$02fuwÇÜÞàüýÚùú¶ÚÚLQZ'-:(:"9 << >"=@$I"Q&` 3r7m1S.>(7:ž¡¦ØÐ×ÛÎÖÜÑÙÕÍרÐÛÛÑÝÛÎÖÞÏ×ÕÇÍ“‰@;;;A9;FMNXhflŽšÁ¶ÀÔÆÌ˜“•wvztpv05>ÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜÎÙÜËÔßÐØÜÏ××ÐÕÐÑÕÊÓÖ;KJwŒŠgii>=?156—¦¨ÌëêÝÿÿØö÷Ìàåhhh%.;-I#E >$= #;#; 9"ADK ,W0O$3C.16}t~ËÂÌßÔÞØÍ×ÛÐÚÚÌ×àÒÝÜÎÙãÒÝÛËÖÕÈЮ§®YY_FOSCPRL^_Yliammjnohory‹ŒÑêìßüÿ×ôø‘—,66(6!>@ B 1&(",3$*1<;D¨ ªÔÉÓÙÉÔÞÎÙÒÂͼ±¹±¦®¥š¢Ÿ”œ¡–ž¬¡©¼±¹È½ÅÙÎÖÚÍÕÚÍÕÔÊлÀ…†134ÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÜÍÕÜÍÕÙÌÔ×ÐÕÕÑÖÇÊÎ=FIWed8::356HMNµÇÈÕôóÑõõØö÷Ïåêqxu!2;0L&I== "B>"7 #= @@!@)A&6KLV½´¾ÛÐÚØÍ××ÌÖÛÐÚÙËÖÜÎÙ×ÉÔÜÌ×ÜÌ×ÜÏ×ÕÊÒüÃÇÅ˪­±•šƒ•”Œ˜˜u}}P\^xØö÷Ú÷ûÄßãP[Y(4:%67A <!.$/3%-4!)RQZûÅÛÐÚÚÊÕßÏÚàÐÛÚÏ×ÙÎÖÙÎÖÛÐØÛÐØÚÏ×ÚÏ×ÛÐØÖËÓÝÐØßÒÚÖÌÒĽ‚~ƒ./3ÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÛÍØÜÏ×ÛÎÖÙÌÔÝÐØÔÍÒ¾º¿MNR@CGUWW=ABV``ÈÜÝÛúùÕ÷÷ÜûüÅàäv‚| 297Q2Y!L#N )RG6 #? <:'<-=+3@”” ÚÏÙØÍ×ÖËÕÚÏÙÛÍØÙËÖÜÎÙÛÍØÚÌ×ÞÎÙÞÏ×ÝÎÖÝÎÖÙÎÖÔÎÓÓÏÔÀÐϹÅÅeqs€”•ÁßàÐòòÖó÷“©®/8;-9 #9 ; !;"3$-6%)."%-ACK”˜ÚÑÛÚÌ×àÐÛÞÎÙÙÉÔÜÏ×ÛÎÖÛÎÖÛÎÖÛÎÖÚÍÕÚÍÕÛÎÖÚÏ×ÞÑÙÝÐØ×ÊÒÏÅËŽˆ.-1ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÙÎØÜÎÙÜÏ×áÒÚÙÌÔÎÄÊ”’{uzprr7<=_kkÏäåØ÷öÙûûÝüýÂßト'69&;Q8] 1^0a 3d'Y&P -VC :)7&-BCM¿»ÇÖËÕÕÊÔÛÐÚÞÐÛÙËÖÚÌ×ÜÌ×ÛËÖÝÏÚÙËÖÖÇÏÞÏ×ÞÑÙÎÇÎØ×ÛÉÌкÈÇiwvtƒ…·ÑÑÔööÛþÿÜ÷û„–,6@"4!:";$5%.&&,1/5mluž›¤ÐÈÒÛÐÚÒÄÏáÑÜÚÌרÊÕØËÓØËÓÙÌÔÚÍÕÛÎÖÛÎÖÛÎÖÛÎÖ×ÌÖÙËÖÜÏ×ÛÎÖÛÎÖ¨¡¦MINÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌ×ÚÌרÍ×ÙÎØÛËÖÞÍÖÜËÔàÑÙÖÊÐÀ¶¼rpp389s€ÓëëÖòòÜúûÙøùÎí𜣞:?B-5F-L 5`8k:q4l1m 7p'W(F)5,/3yu{ÎÅÒÚÏÙ×ÌÖÚÌרÊÕÛÍØàÐÛÛËÖÜÌ×ÕÇÒÜÎÙÛÌÔÛÎÖÒËÒÐÓØéöø»ÏÐl|{ŽÃÕÖãüþÖ÷úÖ÷úØòøhz".@ "8 :!5-6&)-3-2vnuÈÃÌ×ÏÙÖÍ×ÚÌ×ÞÎÙÛÍØÖÈÓÞÓÝÙÌÔÚÍÕÜÏ×ÜÏ×ÜÏ×ÛÎÖÚÍÕØËÓÚÏÙÙËÖßÏÚÛÌÔÚÍÕÒÇϯ¨­ÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖ×ÌÖÙËÖÙÉÔÛÊÕÚÉÒÝÎÖÜÏ×ȽÅxrs378hxwÍâãàøøåþÿÝùúÒñô©µµFHI52;%75W;l:r8u8w8x 3j7Z%1=[[[Ä»¾ÝÏÛÛÍØØÊÕÖÈÓØÊÕÞÎÙÜÌ×ÙÉÔßÏÚÙÎØßÑÜÝÎÖÚÍÕÒËÒÈÎÓÂÔÕuvˆ‰ËÚÜÑàã·ÊÍÇâæÕô÷ÓëñSel$>'= 2+8!'.405zpvŸÀÖÎØ×ÎØÒÄÏÛËÖàÐÛÚÌ×ÙËÖ×ÌÖÝÎÖÝÎÖÛÌÔÙÊÒÙÊÒÚËÓÜÍÕÜÍÕÖËÕ×ÉÔßÏÚÝÍØØÉÑÝÐØÒÇÏÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖÙËÖØÊÖØÊÕÚÊÕÞÍØÝÍØÛÎÖÓÈÐÆ¾Å‘†ˆ9;€|{ÛÍÑÙÈÖÙËÖÙËÖÙËÖÞÎÙÛËÖÕÅÐÖÆÑÚÉÔÓÊÔÕÇÒÙÈÑÜËÔÛÎÖÄÂÈ— £]op£¸¹¢±³ƒŽ’bnrŽ¢§ÏçíÃÛáAT[ !?!8!.,.6.,2jcjÁ¶¾ÜÏ×ÔÉÓÛÍØÜÌרÈÓÖÆÑØÊÕÜÑÛÒÉÓ×ÈÐÚËÓÜÍÕÜÍÕÜÍÕÝÎÖÜÍÕÚËÓÙÍÙÙËÖØÈÓÝÌרÇÒÜÍÕÙÌÔØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕØÊÕÛÍÙÛÊ×ÙÉÔÙÉÔÛËÖØÍÕÑÉÐÑÊѧšœCBDIWV®ÂÃxŠ‹HY\©ÀÂÕòöÁåë[hfUKD2.-6F :` 9s2u )PK"O.L.7@’ŠÖÇËÝÊÙÙËÖÚÌ××ÉÔÛËÖÙÉÔÛËÖâÑÜØÇÒÔÌÖÖËÕàÍÖàÈÒáÌÕö¾{z~[`cQkk`oq{†rx§µ»Ñçí•«±3HPA4.08/(+VNU¼´¿ÖËÕÚÌÒÙËÖÕÇÒÙÉÔÜËÖÜÌ××ÉÔÖËÕÖÍ×ÚËÓÛÌÔÛÌÔÙÊÒÙÊÒÛÌÔÜÍÕÚËÓ×Ë×ÚÌØÖÆÑßÎÙÛÊÕÙÊÒÚÍÕÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔ¾´ºPOS>EH ªªltt%//aroÆÝÙÉôñ±ÔІ—”**0(1?:T/V'W ?!>$= $8%/@“Ž×ÇÒâÊÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔ×ÇÒØÈÓÚÊÕÚÊÕÚÊÕÔÄϹ©´˜ˆ“Ÿ‘œª¨®jy{€˜–ÈáãÏî÷”¼ÎDZ(--3$'/RJT¶¨³ÝÍØ×ÇÒÜÎÙÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔ½·¼gjn1=?ˆ–•’œœ:?@:BBŽ›™ÎîíÖ÷ó²ÇÅ;@C'0:9Q0ZU"K@ 'B0B)1>…ŒÖÆÑÛÈÑÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÙÉÔÜÌ×ÛËÖÚÊÕÖÆÑÖÆÑÚÊÕÙÉÔÐÀËËÀÊ¿ÀÄaon´ÊÈÖïñÝùÿ­ÒàCV)/'.=@A@BCotuÂ×ÙÓðô¤¹·CIH09F;b ;y2n6f-L9?LFEGhdcÐÆÌÑÃÎØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓÙÉÔ×ÇÒØÈÓØÈÓ×ÇÒÙÉÔ×ÇÒÐÀËŸœžY]^€‹L_\|‘ÆÛÝ­ÀÇ4GO:2<‚yƒÖÈÓÙÉÔÔÃÎÖÆÑÖÈÓ×ÌÖØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓØÈÓ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒÞÉÒÍÅÌÅÉÎMY[DMPfkn6;?‰—ÈâèÎäâyƒ}@HO.Gg2f9u6d/;WRS]PLKOLHÈÁÄÕÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒÚÊÕØÈÓÖÆÑÔÄÏÖÆÑÛËÖÕÅÐȸÃqnpJIKPVUXfd¬¾½ÊÜÝfrv.7;~p{ÓÃÎØÈÓÛÊÕÛÊÕÔÄÏÖÈÓÒÄÏ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒßÇÑÙÊÒÎÊн½ÃZY]>=A27:|ˆŠU]]FQU†™žÆÜÚ¾ÍÉP\^3I[>^9i9]FLc`\bb^]@>=¦Ÿ¤ÛÊ××ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒÔÄÏÖÆÑØÈÓÖÆÑÖÆÑØÈÓÑÁÌó¾ngl@:?kjn~ˆˆÂÒÑŽž9AA\[]ʺÅßÏÚÕÅÐÒÂÍÚÊÕ×ÇÒÖÆÑÙÉÔ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒ×ÇÒÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÅÐÒÅÍÏÇÎÓÈм­µthnWVZÁÈ˪¼½S\_GPS‡™˜ÉàÜ‘£¤Sfm;Yd@`%>XVYhYRW}yxNNN}u|˸ÇÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑ×ÇÒÖÆÑÔÄÏ×ÇÒØÈÓÔÄÏÀ³»¦™¡°©°€„‰±ÀÂVegPUV¹³´ÛËÖÐÂÍ×ÉÔÓÅÐ×ÉÔÕÅÐ×ÇÒׯÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÑÈÒÍÅÏÐÅÍÛÊÓÙÁËØÃËÁ·½ÄÅÉÓíí­´·\^_AQP{••ÅÚÛ—©¨¤ T”Mcusq}QJOˆ††mln{r|ȳÂÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑ×ÇÒÔÄÏÕÅÐØÈÓÖÆÑÕÅÐÕÅÐÔÄÏÕÆÎÐÀË—Œ–—ix{3BDœ ¡ÐÈÉÔÆÑÑÆÐÏÄÎÖËÕÑÃÎÔÄÏ×ÆÑØÄÐÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÖÆÑÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÛÄÒÎÀ̺¹Â_ko7IJbrqkxvGMLhy|¢¥ŠŸ¡Uhkdnu¥¤­È½ÇÓÂÍÖÆÑÖÆÑÖÆÑ×ÇÒ×ÇÒÖÆÑÖÆÑÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÚÉÒö¾‰ƒˆ`_aB?AaZ_Ŷ¾ÝÈÑÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÔÂÏÒÄÐÈÃÌÉÍÒ‚‹ŽCOOMWWS[Z;HJbqsŸ±²•¤§ALP¤¤ªÃºÄÖÆÑÔÄÏÔÄÏÕÅÐÕÅÐÖÆÑÖÆÑ×ÇÒ×ÇÒÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÔÃÎÄ·¿ysxNKMLIK©¢§×ÈÐÙÅÑÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÕÅÐÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏØÇÔ˽ÉÙÎØËÄ˵³¹©ª®hmnNSTFKLQYYu˜¡¤^ehklp±ª±ËÀÈÔÄÏÕÅÐÖÆÑÕÅÐÔÄÏÓÃÎÔÄÏÕÅÐÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏ¿²ºe^cD?ArmoÎÄÊÓÄÌÕÁÍÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÏÃÏÖÈÓ̼ÇÖÅÐÕÈÐÒÊÑÔÓׄ‡‹WTV<;=[]^cghlmqLKO‚|»´¹ÒÂÍÔÄÏÖÆÑÕÅÐÓÃÎÒÂÍÒÂÍÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÕÅЮ¡©PFLUNS¯¨­ÐÄÊÕÆÎÙÈÓÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÔÄÏÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÐÅÏÏÁÌÜÈÔØÂÎÔÀÌÌ¿ÇÉÂɾ¼Â¥œŸslo†‰®¨­¹³¸¨¢§Š‚‰—–ͽÈÐÀËÓÃÎÕÅÐÔÄÏÓÃÎÔÄÏÕÅÐÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÕÇÒž›E:B}syÔÈÎÎÁÉÖÆÑνÈÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÎÃÍÔÄÏÒÁÌÚÄÐÓ¿ËÚÉÔÒÇÑÈ¿ÉÑÅËÓÇÍÏÃÉ×ÊÒǺÂÒÅÍÐÂÍÍ¿ÊͽÈÐÀËÓÃÎÔÄÏÔÄÏÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎ˽ɓ…[NV¯£©ÔÆÌÕÆÎÖÆÑÒÁÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÓÃÎÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÏÁÌØÈÓÏ¿ÊÕÄÏׯÑÕÃÐνÊÖÅÒÑÄÌÏ¿ÊÕÄÏνÈÖÅÐØÆÓÍ»ÈÔÂÏÒÂÍÓÃÎÓÃÎÓÃÎÒÂÍÑÁÌÑÁÌÑÁÌÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÏÃϳ¥°Ÿ˜ÓÅËÑÁÈÓÄÌÏ¿ÊÕÄÑÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÓÃÎʺÅÔÆÑ̾ÉÎÀÌÔÃÐÔÂÏÕÁÎÑÃÎÓÃÎÑ¿ÌÚÆÓÕ¾ÌÔ½ÌÙÄÓÔ¿ÎÓÃÎÒÂÍÑÁÌÑÁÌÑÁÌÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÍÁÍÐÂÍÐÁÉνÆÔÃÌÔÃÌÑÁÌпÌÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÒÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÓÂÍÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÒÁÌÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËÑÀËuqm-0.6.2/sc2/build/win32_install/uqm-installer.nsi0000644000175000017500000005306710552352410020615 0ustar joeyjoey; Script generated by the HM NIS Edit Script Wizard. Var PACKAGEDIR Var UQMARGS Var MAKEICON Var UQMUSERDATA ; HM NIS Edit Wizard helper defines !define PRODUCT_NAME "The Ur-Quan Masters" !define PRODUCT_VERSION "0.6.2" !define PRODUCT_WEB_SITE "http://sc2.sourceforge.net" !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\uqm.exe" !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" !define PRODUCT_UNINST_ROOT_KEY "HKLM" !define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir" ; MUI 1.67 compatible ------ !include "MUI.nsh" ; MUI Settings !define MUI_ABORTWARNING !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\win-install.ico" !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\win-uninstall.ico" !define MUI_WELCOMEFINISHPAGE_BITMAP "orzshofixti.bmp" !define MUI_HEADERIMAGE !define MUI_HEADERIMAGE_BITMAP "ultron.bmp" !define MUI_HEADERIMAGE_RIGHT ; Welcome page !insertmacro MUI_PAGE_WELCOME ; License page !define MUI_LICENSEPAGE_BUTTON "Install" !define MUI_LICENSEPAGE_TEXT_BOTTOM "Press the Install button to continue." !insertmacro MUI_PAGE_LICENSE "COPYING.txt" ; Components page !define MUI_COMPONENTSPAGE_TEXT_COMPLIST "You can preconfigure the options to mimic the original platforms by selecting those install types. Note that more complete installs will need to download more packages." !insertmacro MUI_PAGE_COMPONENTS ; Directory page !insertmacro MUI_PAGE_DIRECTORY ; Package Dictory !define MUI_PAGE_HEADER_TEXT "Choose Package Location" !define MUI_PAGE_HEADER_SUBTEXT "Choose the folder that holds packages that have already been downloaded." !define MUI_DIRECTORYPAGE_TEXT_TOP "Setup will look for already-downloaded content packages in the following folder. To copy them from a different folder, click Browse and select another folder. If you are doing a net install, leave this field alone. Click Next to continue." !define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Source Folder" !define MUI_DIRECTORYPAGE_VARIABLE $PACKAGEDIR !define MUI_DIRECTORYPAGE_VERIFYONLEAVE !insertmacro MUI_PAGE_DIRECTORY ; Start menu page var ICONS_GROUP !define MUI_STARTMENUPAGE_NODISABLE !define MUI_STARTMENUPAGE_DEFAULTFOLDER "Games\The Ur-Quan Masters" !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}" !define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}" !insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP ; Instfiles page !insertmacro MUI_PAGE_INSTFILES ; Finish page !define MUI_FINISHPAGE_RUN_NOTCHECKED !define MUI_FINISHPAGE_NOREBOOTSUPPORT !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\README.txt" !define MUI_FINISHPAGE_RUN "$INSTDIR\uqm.exe" !define MUI_FINISHPAGE_RUN_PARAMETERS $UQMARGS !insertmacro MUI_PAGE_FINISH ; Uninstaller pages !define MUI_UNCONFIRMPAGE_TEXT_TOP "This program will now uninstall The Ur-Quan Masters entirely. If you wish to preserve content or expansion packs, select Cancel now and back them up. Otherwise, press Uninstall to continue." !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES ; Language files !insertmacro MUI_LANGUAGE "English" ; MUI end ------ Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" OutFile "uqm-0.6.2-installer.exe" InstallDir "$PROGRAMFILES\The Ur-Quan Masters\" InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" "" ShowInstDetails show ShowUnInstDetails show AllowRootDirInstall true DirText "" "" "" "Please select a folder." InstType "Typical" InstType "Minimal" InstType "Mimic PC" InstType "Mimic 3DO" InstType "No Content" InstType "All Expansions" Function .onInit Push $0 StrCpy $PACKAGEDIR $EXEDIR StrCpy $UQMARGS "" StrCpy $MAKEICON 0 ReadEnvStr $0 APPDATA StrCmp $0 "" NoAppData ExpandEnvStrings $UQMUSERDATA "%APPDATA%\uqm" Goto GotAppData NoAppData: ReadEnvStr $0 USERPROFILE StrCmp $0 "" NoProfile ExpandEnvStrings $UQMUSERDATA "%USERPROFILE%\Application Data\uqm" Goto GotAppData NoProfile: StrCpy $UQMUSERDATA "$INSTDIR\userdata\uqm" GotAppData: FunctionEnd Function Random Exch $0 Push $1 System::Call 'kernel32::QueryPerformanceCounter(*l.r1)' System::Int64Op $1 % $0 Pop $0 Pop $1 Exch $0 FunctionEnd Function RandomServer Push $0 Push 15 Call Random Pop $0 IntCmp $0 0 0 +4 +4 StrCpy $0 "ovh" Exch $0 Return IntCmp $0 1 0 +4 +4 StrCpy $0 "mesh" Exch $0 Return IntCmp $0 2 0 +4 +4 StrCpy $0 "easynews" Exch $0 Return IntCmp $0 3 0 +4 +4 StrCpy $0 "switch" Exch $0 Return IntCmp $0 4 0 +4 +4 StrCpy $0 "superb-east" Exch $0 Return IntCmp $0 5 0 +4 +4 StrCpy $0 "jaist" Exch $0 Return IntCmp $0 6 0 +4 +4 StrCpy $0 "ufpr" Exch $0 Return IntCmp $0 7 0 +4 +4 StrCpy $0 "heanet" Exch $0 Return IntCmp $0 8 0 +4 +4 StrCpy $0 "puzzle" Exch $0 Return IntCmp $0 9 0 +4 +4 StrCpy $0 "superb-west" Exch $0 Return IntCmp $0 10 0 +4 +4 StrCpy $0 "optusnet" Exch $0 Return IntCmp $0 11 0 +4 +4 StrCpy $0 "surfnet" Exch $0 Return IntCmp $0 12 0 +4 +4 StrCpy $0 "belnet" Exch $0 Return IntCmp $0 13 0 +4 +4 StrCpy $0 "kent" Exch $0 Return IntCmp $0 14 0 +4 +4 StrCpy $0 "nchc" Exch $0 Return StrCpy $0 "umn" Exch $0 FunctionEnd # To use: # Push the file name. # Push the installation location. # It will install it from the Package Directory if necessary; otherwise it # will download it to a temp file and install that. Var DOWNLOADTARGET Var MANDATORY Var MD5SUM Function HandlePackage Exch $0 # File location Exch Exch $1 # File name Exch Push $2 Push $3 # Check to make sure the file wasn't already installed IfFileExists "$0\$1" 0 NotThere md5dll::GetFileMD5 "$0\$1" Pop $3 StrCmp $MD5SUM $3 0 NotThere MessageBox MB_ICONINFORMATION|MB_OK "The package $1 has already been installed." Goto PackageDone NotThere: SetOutPath "$0" SetOverwrite ifdiff IfFileExists "$PACKAGEDIR\$1" 0 CheckForZip md5dll::GetFileMD5 "$PACKAGEDIR\$1" Pop $3 StrCmp $MD5SUM $3 PackageOK MessageBox MB_ICONINFORMATION|MB_OKCANCEL "The file $PACKAGEDIR\$1 appears to be corrupt. The expected MD5 sum was '$MD5SUM', but the actual MD5 sum was '$3'. Press OK to attempt to download a fresh copy from the distribution site, or Cancel to skip the package." IDOK AttemptDownload IDCANCEL PackageDone PackageOK: CopyFiles "$PACKAGEDIR\$1" "$0\$1" Goto PackageDone CheckForZip: IfFileExists "$PACKAGEDIR\$1.zip" 0 AttemptDownload md5dll::GetFileMD5 "$PACKAGEDIR\$1.zip" Pop $3 StrCmp $MD5SUM $3 ZipPackageOK MessageBox MB_ICONINFORMATION|MB_OKCANCEL "The file $PACKAGEDIR\$1.zip appears to be corrupt. The expected MD5 sum was '$MD5SUM', but the actual MD5 sum was '$3'. Press OK to attempt to download a fresh copy from the distribution site, or Cancel to skip the package." IDOK AttemptDownload IDCANCEL PackageDone ZipPackageOK: CopyFiles "$PACKAGEDIR\$1.zip" "$0\$1" Goto PackageDone AttemptDownload: Call RandomServer Pop $2 GetTempFileName $DOWNLOADTARGET Delete $DOWNLOADTARGET CreateDirectory $DOWNLOADTARGET NSISdl::download "http://$2.dl.sourceforge.net/sourceforge/sc2/$1" "$DOWNLOADTARGET\$1" Pop $2 StrCmp $2 "success" DownloadSuccessful StrCmp $2 "cancel" DownloadCanceled StrCpy $2 "Could not install the package $1 due to the following error: $\"$2$\"." Goto CheckMandatory DownloadCanceled: StrCpy $2 "Download was canceled by user." CheckMandatory: IntCmp $MANDATORY 0 NotMandatory StrCpy $3 "THIS IS A MANDATORY PACKAGE. Without this package, $(^Name) will NOT run." Goto DisplayError NotMandatory: StrCpy $3 "This is an optional package. $(^Name) will still run, but some content will not be available." DisplayError: MessageBox MB_ICONEXCLAMATION|MB_YESNO "$2 $3 Do you want to retry from a different mirror?" IDYES AttemptDownload Goto DoneWithTempFile DownloadSuccessful: md5dll::GetFileMD5 "$DOWNLOADTARGET\$1" Pop $3 StrCmp $MD5SUM $3 DownloadedPackageOK IntCmp $MANDATORY 0 NotMandatory2 StrCpy $3 "THIS IS A MANDATORY PACKAGE. Without this package, $(^Name) will NOT run." Goto DisplayError2 NotMandatory2: StrCpy $3 "This is an optional package. $(^Name) will still run, but some content will not be available." DisplayError2: MessageBox MB_ICONEXCLAMATION|MB_YESNO "The downloaded file $1 doesn't match the internal MD5 sum. This probably means the download was corrupt. $3 Do you want to retry from a different mirror? (Select NO to install the downloaded package anyway - for instance, if you know that the content pack was upgraded or modified since.)" IDYES AttemptDownload DownloadedPackageOK: CopyFiles "$DOWNLOADTARGET\$1" "$0\$1" DoneWithTempFile: RmDir /r $DOWNLOADTARGET PackageDone: Pop $3 Pop $2 Pop $1 Pop $0 FunctionEnd SectionGroup "!UQM" SECGRP01 Section "Executable" SEC01 SectionIn 1 2 3 4 5 6 RO SetOutPath "$INSTDIR" SetOverwrite try File "AUTHORS.txt" File "COPYING.txt" File "libpng12.dll" File "Manual.txt" File "ogg.dll" File "OpenAL32.dll" File "README.txt" File "SDL.dll" File "SDL_image.dll" File "SDL_gfx.dll" File "uqm.exe" File "keyjam.exe" File "vorbis.dll" File "vorbisfile.dll" File "WhatsNew.txt" File "zlib1.dll" SetOverwrite off SetOutPath $UQMUSERDATA File "keys.cfg" File "uqm.cfg" SetOverwrite try File "uqm-pc.cfg" File "uqm-3do.cfg" IfFileExists "$INSTDIR\content\packages\uqm-0.5.0-3domusic.uqm" 0 DelOldContent StrCpy $MD5SUM "a20cacc8e66f5ff1fdf5e1d3a3b93fd2" md5dll::GetFileMD5 "$INSTDIR\content\packages\uqm-0.5.0-3domusic.uqm" Pop $0 StrCmp $MD5SUM $0 0 DelOldContent CopyFiles "$INSTDIR\content\packages\uqm-0.5.0-3domusic.uqm" "$INSTDIR\content\packages\uqm-0.6.0-3domusic.uqm" DelOldContent: Delete "$INSTDIR\content\packages\uqm-0.3-3domusic.zip" Delete "$INSTDIR\content\packages\uqm-0.3-voice.zip" Delete "$INSTDIR\content\packages\uqm-0.3-content.zip" Delete "$INSTDIR\content\packages\uqm-0.4.0-3domusic.uqm" Delete "$INSTDIR\content\packages\uqm-0.4.0-voice.uqm" Delete "$INSTDIR\content\packages\uqm-0.4.0-content.uqm" Delete "$INSTDIR\content\packages\uqm-0.5.0-3domusic.uqm" Delete "$INSTDIR\content\packages\uqm-0.5.0-voice.uqm" Delete "$INSTDIR\content\packages\uqm-0.5.0-content.uqm" ; Shortcuts !insertmacro MUI_STARTMENU_WRITE_BEGIN Application !insertmacro MUI_STARTMENU_WRITE_END SectionEnd Section "Core Data" SEC02 SectionIn 1 2 3 4 6 CreateDirectory "$INSTDIR\content\packages\addons" SetOutPath "$INSTDIR\content" SetOverwrite ifnewer AddSize 12261 StrCpy $MANDATORY 1 StrCpy $MD5SUM "7e8f0ed8490e24231431420ea2ba6a03" File "content\version" Push "uqm-0.6.0-content.uqm" Push "$INSTDIR\content\packages" Call HandlePackage ; Shortcuts !insertmacro MUI_STARTMENU_WRITE_BEGIN Application !insertmacro MUI_STARTMENU_WRITE_END SectionEnd Section "Desktop Icon" SECICON SectionIn 1 2 3 4 5 6 StrCpy $MAKEICON 1 SectionEnd SectionGroupEnd SectionGroup /e "3DO Content" SECGRP02 Section "Music" SEC03 SectionIn 1 4 6 AddSize 18536 StrCpy $MANDATORY 0 StrCpy $MD5SUM "a20cacc8e66f5ff1fdf5e1d3a3b93fd2" Push "uqm-0.6.0-3domusic.uqm" Push "$INSTDIR\content\packages" Call HandlePackage ; Shortcuts !insertmacro MUI_STARTMENU_WRITE_BEGIN Application !insertmacro MUI_STARTMENU_WRITE_END SectionEnd Section "Voiceovers" SEC04 SectionIn 1 4 6 AddSize 112291 StrCpy $MANDATORY 0 StrCpy $MD5SUM "d31577b896be935cc2238afd07299b8b" Push "uqm-0.6.0-voice.uqm" Push "$INSTDIR\content\packages" Call HandlePackage ; Shortcuts !insertmacro MUI_STARTMENU_WRITE_BEGIN Application !insertmacro MUI_STARTMENU_WRITE_END SectionEnd SectionGroupEnd SectionGroup "Modern Remixes" SECGRP03 Section "Pack 1" SEC05 SectionIn 6 AddSize 49012 StrCpy $MANDATORY 0 StrCpy $MD5SUM "2df402b2951c0187604a81c3997fbb9d" Push "uqm-remix-pack1.zip" Push "$INSTDIR\content\packages\addons\remix\" Call HandlePackage StrCpy $UQMARGS "--addon remix" ; Shortcuts !insertmacro MUI_STARTMENU_WRITE_BEGIN Application !insertmacro MUI_STARTMENU_WRITE_END SectionEnd Section "Pack 2" SEC06 SectionIn 6 AddSize 58869 StrCpy $MANDATORY 0 StrCpy $MD5SUM "d5a9fb72b369bf5a5dbca3db9f1e1ea3" Push "uqm-remix-pack2.zip" Push "$INSTDIR\content\packages\addons\remix\" Call HandlePackage StrCpy $UQMARGS "--addon remix" ; Shortcuts !insertmacro MUI_STARTMENU_WRITE_BEGIN Application !insertmacro MUI_STARTMENU_WRITE_END SectionEnd Section "Pack 3" SEC07 SectionIn 6 AddSize 38989 StrCpy $MANDATORY 0 StrCpy $MD5SUM "567bc2d9e3ca067d21170c5ac5538441" Push "uqm-remix-pack3.zip" Push "$INSTDIR\content\packages\addons\remix\" Call HandlePackage StrCpy $UQMARGS "--addon remix" ; Shortcuts !insertmacro MUI_STARTMENU_WRITE_BEGIN Application !insertmacro MUI_STARTMENU_WRITE_END SectionEnd # Section "Pack 4" SEC08 # SectionIn 6 # AddSize 50000 # ESTIMATE: Update later # StrCpy $MANDATORY 0 # Push "uqm-remix-pack4.zip" # Push "$INSTDIR\content\packages\addons\remix\" # Call HandlePackage # StrCpy $UQMARGS "--addon remix" # ; Shortcuts # !insertmacro MUI_STARTMENU_WRITE_BEGIN Application # !insertmacro MUI_STARTMENU_WRITE_END # SectionEnd SectionGroupEnd Section -ShortcutsAndIcons SetOutPath $INSTDIR !insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateDirectory "$SMPROGRAMS\$ICONS_GROUP" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\The Ur-Quan Masters.lnk" "$INSTDIR\uqm.exe" $UQMARGS CreateDirectory "$SMPROGRAMS\$ICONS_GROUP\Documentation" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Documentation\AUTHORS.lnk" "$INSTDIR\AUTHORS.txt" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Documentation\COPYING.lnk" "$INSTDIR\COPYING.txt" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Documentation\Manual.lnk" "$INSTDIR\Manual.txt" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Documentation\README.lnk" "$INSTDIR\README.txt" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Documentation\WhatsNew.lnk" "$INSTDIR\WhatsNew.txt" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Key Configuration.lnk" "$WINDIR\notepad" "$UQMUSERDATA\keys.cfg" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Options Configuration.lnk" "$WINDIR\notepad" "$UQMUSERDATA\uqm.cfg" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Keyboard Test.lnk" "$INSTDIR\keyjam.exe" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Saved Games.lnk" "$UQMUSERDATA\save" IntCmp $MAKEICON 1 0 NoIcon NoIcon CreateShortCut "$DESKTOP\The Ur-Quan Masters.lnk" "$INSTDIR\uqm.exe" $UQMARGS NoIcon: CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninst.exe" !insertmacro MUI_STARTMENU_WRITE_END SectionEnd Section -Set3DOConfig SectionIn 4 !insertmacro MUI_STARTMENU_WRITE_BEGIN Application SetOutPath $UQMUSERDATA Delete "uqm.cfg" CopyFiles "$UQMUSERDATA\uqm-3do.cfg" "$UQMUSERDATA\uqm.cfg" !insertmacro MUI_STARTMENU_WRITE_END SectionEnd Section -SetPCConfig SectionIn 3 !insertmacro MUI_STARTMENU_WRITE_BEGIN Application SetOutPath $UQMUSERDATA Delete "uqm.cfg" CopyFiles "$UQMUSERDATA\uqm-pc.cfg" "$UQMUSERDATA\uqm.cfg" !insertmacro MUI_STARTMENU_WRITE_END SectionEnd Section -Post WriteUninstaller "$INSTDIR\uninst.exe" WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\uqm.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\uqm.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" SectionEnd ; Section descriptions !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${SECGRP01} "The core executables and content libraries for The Ur-Quan Masters. All elements in this section must be installed for the game to be playable." !insertmacro MUI_DESCRIPTION_TEXT ${SEC01} "Includes the main program, all subsidiary libraries, and basic documentation for The Ur-Quan Masters. Required for play." !insertmacro MUI_DESCRIPTION_TEXT ${SEC02} "Graphics, sound, and the PC-edition music for The Ur-Quan Masters. Required for play. If this package is selected and not present in the packages directory, the installer will attempt to download it." !insertmacro MUI_DESCRIPTION_TEXT ${SECICON} "Adds a desktop icon linking directly to The Ur-Quan Masters." !insertmacro MUI_DESCRIPTION_TEXT ${SECGRP02} "Optional content packages containing music and sound unique to the 1993 3DO release." !insertmacro MUI_DESCRIPTION_TEXT ${SEC03} "Optional package which includes the remixed songs from the 3DO release. If this package is selected and not present in the packages directory, the installer will attempt to download it." !insertmacro MUI_DESCRIPTION_TEXT ${SEC04} "Optional package containing the voiceovers from the 3DO release. If this package is selected and not present in the packages directory, the installer will attempt to download it." !insertmacro MUI_DESCRIPTION_TEXT ${SECGRP03} "Optional content packages containing the official UQM remixes by The Precursors. Selecting any element from this group will also enable the 'remix' addon by default in any shortcuts." !insertmacro MUI_DESCRIPTION_TEXT ${SEC05} `Ur-Quan Masters Remix Pack 1 - 'Super Melee!' Optional add-on music package. If this package is selected and not present in the packages directory, the installer will attempt to download it.` !insertmacro MUI_DESCRIPTION_TEXT ${SEC06} `Ur-Quan Masters Remix Pack 2 - 'Neutral Aliens - Don't Shoot!' Optional add-on music package. If this package is selected and not present in the packages directory, the installer will attempt to download it.` !insertmacro MUI_DESCRIPTION_TEXT ${SEC07} `Ur-Quan Masters Remix Pack 3 - 'The Ur-Quan Hierarchy.' Optional add-on music package. If this package is selected and not present in the packages directory, the installer will attempt to download it.` # !insertmacro MUI_DESCRIPTION_TEXT ${SEC08} `Ur-Quan Masters Remix Pack 4 - 'The New Alliance of Free Stars.' Optional add-on music package. If this package is selected and not present in the packages directory, the installer will attempt to download it.` !insertmacro MUI_FUNCTION_DESCRIPTION_END Function un.onUninstSuccess HideWindow MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer." FunctionEnd Function un.onInit MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2 Abort FunctionEnd Section Uninstall !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP Delete "$INSTDIR\uninst.exe" Delete "$INSTDIR\content\packages\addons\remix\uqm-remix-pack4.zip" Delete "$INSTDIR\content\packages\addons\remix\uqm-remix-pack3.zip" Delete "$INSTDIR\content\packages\addons\remix\uqm-remix-pack2.zip" Delete "$INSTDIR\content\packages\addons\remix\uqm-remix-pack1.zip" Delete "$INSTDIR\content\packages\uqm-0.6.0-voice.uqm" Delete "$INSTDIR\content\packages\uqm-0.6.0-3domusic.uqm" Delete "$INSTDIR\content\packages\uqm-0.6.0-content.uqm" Delete "$INSTDIR\content\version" Delete "$INSTDIR\zlib.dll" Delete "$INSTDIR\zlib1.dll" Delete "$INSTDIR\WhatsNew.txt" Delete "$INSTDIR\vorbisfile.dll" Delete "$INSTDIR\vorbis.dll" Delete "$INSTDIR\uqm.exe" Delete "$INSTDIR\keyjam.exe" Delete "$INSTDIR\SDL_gfx.dll" Delete "$INSTDIR\SDL_image.dll" Delete "$INSTDIR\SDL.dll" Delete "$INSTDIR\README.txt" Delete "$INSTDIR\OpenAL32.dll" Delete "$INSTDIR\ogg.dll" Delete "$INSTDIR\Manual.txt" Delete "$INSTDIR\libpng13.dll" Delete "$INSTDIR\libpng12.dll" Delete "$INSTDIR\COPYING.txt" Delete "$INSTDIR\AUTHORS.txt" Delete "$INSTDIR\stderr.txt" Delete "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Options Configuration.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Key Configuration.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Keyboard Test.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Saved Games.lnk" Delete "$DESKTOP\The Ur-Quan Masters.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\The Ur-Quan Masters.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Documentation\AUTHORS.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Documentation\COPYING.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Documentation\Manual.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Documentation\README.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Documentation\WhatsNew.lnk" RMDir "$SMPROGRAMS\$ICONS_GROUP\Documentation" RMDir "$SMPROGRAMS\$ICONS_GROUP" RMDir "$INSTDIR\content\packages\addons\remix" RMDir "$INSTDIR\content\packages\addons" RMDir "$INSTDIR\content\packages" RMDir "$INSTDIR\content" RMDir "$INSTDIR" DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" SetAutoClose true SectionEnd uqm-0.6.2/sc2/build/unix_installer/0000755000175000017500000000000010552600273015645 5ustar joeyjoeyuqm-0.6.2/sc2/build/unix_installer/buildinstaller.sh0000700000175000017500000000525610543202107021211 0ustar joeyjoey#!/bin/sh # Script for creating self-extracting installer files for unix-like systems. # By Serge van den Boom, 2003-02-20 TEMPDIR="/tmp/buildinstaller_$$" if [ $# -ne 2 ]; then cat >&2 << EOF Usage: buildinstaller.sh